Skip to main content
This page documents the key data models returned and accepted by the API, including all enumerated values and field-level details.

Customer

FieldTypeDescription
customerIdstringUnique identifier for the customer
namestringFull name of the customer
emailstring (email)Email address
phonestringPhone number in E.164 format (e.g. +2348192837465)
countryCodestringISO 3166-1 alpha-2 country code (e.g. NG)
metaobjectOptional metadata you attach to the customer
createdAtstring (ISO 8601)Timestamp when the customer was created
updatedAtstring (ISO 8601)Timestamp of the last update
On create and update requests, supply the customer’s full name as fullName; responses return it as name. KYC details are submitted separately through the Update KYC endpoint.

Transaction

FieldTypeDescription
transactionIdstringUnique identifier for the transaction
customerIdstringID of the customer who owns this transaction
sourceIdstringID of the source payment method
destinationIdstringID of the destination payment method
sourceAmountstringAmount debited from the source wallet
sourceCurrencystringISO 4217 currency code of the source wallet (e.g. USD)
destinationAmountstringAmount credited to the destination
destinationCurrencystringISO 4217 currency code of the destination (e.g. NGN)
typestringTransaction type. See Transaction Types
channelstringPayment channel of the transaction. See Transaction Channels.
statusstringCurrent status. See Transaction Statuses
merchantReferencestringMerchant-supplied reference (mirrors meta.reference from the create request)
metaobjectMetadata attached to the transaction. See TransactionMeta
createdAtstring (ISO 8601)Timestamp when the transaction was created
updatedAtstring (ISO 8601)Timestamp of the last update

Transaction Types

ValueDescription
WITHDRAWSend funds from the Afriex wallet to a recipient’s payment method
DEPOSITReceive funds into the Afriex wallet
SWAPConvert funds between currencies within the Afriex wallet

Transaction Channels

ChannelDescription
BANK_ACCOUNTLocal bank account transfer
SWIFTInternational SWIFT wire transfer
MOBILE_MONEYMobile money wallet (e.g. M-Pesa, MTN MoMo)
UPIUnified Payments Interface (India)
INTERACInterac e-Transfer (Canada)
WE_CHATWeChat Pay
CARDCard payment
CRYPTOCrypto rail
VIRTUAL_BANK_ACCOUNTHosted virtual bank account
POOL_ACCOUNTShared pool account for incoming deposits
ACH_BANK_ACCOUNTUS ACH bank transfer
PAYBILL_TILLPaybill / Till (M-Pesa business numbers)
RFPRequest for Payment
VIRTUAL_CARDVirtual card
ALIPAYAlipay
WALLETAfriex wallet (internal leg)

Transaction Statuses

StatusDescription
PENDINGTransaction has been received and is awaiting processing
PROCESSINGTransaction is actively being processed
SUCCESSTransaction settled successfully
FAILEDTransaction failed. Check meta.failureReason for the reason code. See Failure reasons.
CANCELLEDTransaction was cancelled before processing
REFUNDEDFunds were returned to the sender
RETRYTransaction is being automatically retried
UNKNOWNStatus could not be determined. Contact support.
SCHEDULEDTransaction is scheduled to be processed later
CUSTOMER_ACTION_REQUIREDTransaction is paused pending an action from the customer
REJECTEDTransaction was rejected after review
IN_REVIEWTransaction is under manual review
DISPUTEDA dispute has been raised against the transaction
DISPUTE_RESOLVEDThe dispute has been resolved
DISPUTE_WONThe dispute was resolved in your favour
DISPUTE_LOSTThe dispute was resolved against you
DISPUTE_EVIDENCE_SUBMITTEDEvidence has been submitted for the dispute
Subscribe to Transaction Events to receive real-time status updates instead of polling the API.

TransactionMeta

The meta object passed when creating a transaction. idempotencyKey and reference are required.
FieldTypeRequiredDescription
idempotencyKeystringYesUnique key to prevent duplicate transactions. Use a UUID or your own unique identifier.
referencestringYesYour internal reference for the transaction (e.g. order ID). Returned on the transaction as merchantReference.
narrationstringNoHuman-readable reason or description for the transaction
invoicestringNoBase64-encoded invoice document to attach to the transaction
{
  "meta": {
    "idempotencyKey": "550e8400-e29b-41d4-a716-446655440000",
    "reference": "ORDER-12345",
    "narration": "Payment for invoice #12345",
    "invoice": "base64EncodedStringHere"
  }
}
Always provide a unique idempotencyKey per transaction attempt. If you retry a failed request with the same key, Afriex will return the original transaction instead of creating a duplicate.

Server-set meta fields

Afriex also sets fields on meta after the transaction is created. These echo alongside any fields you passed on create.
FieldTypeDescription
otpRequiredbooleantrue when the customer must complete an OTP challenge before the transaction can settle. See Simulating OTP-required deposits.
failureReasonobjectPresent only when status is FAILED or REJECTED. Carries a stable code, a customer-safe message, and a retryable flag. See Failure reasons.

Failure reasons

When a transaction reaches FAILED or REJECTED, meta.failureReason explains why using a stable AFX_* code and a customer-safe message. Branch on code rather than the underlying rail so your integration stays stable across routing changes.
FieldTypeDescription
codestringStable AFX_* failure code. Safe to switch on; the set grows over time but existing values do not change meaning.
messagestringCustomer-safe short description of the failure. Suitable for display; do not parse. Branch on code instead.
retryablebooleantrue when re-submitting the same request (or, for AFX_PROPOSAL_EXPIRED, starting a fresh proposal) may succeed. false when the caller must change the request before retrying.
{
  "meta": {
    "failureReason": {
      "code": "AFX_VELOCITY_LIMIT_EXCEEDED",
      "message": "This transaction exceeds the allowed velocity limit. Try again later.",
      "retryable": true
    }
  }
}
CodeMeaning
AFX_REQUEST_FAILEDGeneric failure while processing the request. Usually retryable.
AFX_SYSTEM_ERRORInternal Afriex error. Retry with backoff.
AFX_SERVICE_UNAVAILABLEA downstream service was unavailable. Retry with backoff.
AFX_INVALID_CURRENCYThe requested currency is not supported for this route.
AFX_INVALID_AMOUNTThe requested amount is invalid or outside allowed limits.
AFX_INVALID_RECIPIENTThe recipient payment method is invalid or incomplete.
AFX_RECIPIENT_NOT_FOUNDThe recipient account could not be located at the destination institution.
AFX_BENEFICIARY_RESTRICTEDThe beneficiary is restricted and cannot receive funds.
AFX_INVALID_SENDERThe sender’s payment method is invalid or ineligible.
AFX_INVALID_REQUESTThe request payload is malformed or inconsistent.
AFX_VELOCITY_LIMIT_EXCEEDEDThe customer has exceeded a velocity limit. Retry after the window resets.
AFX_AMOUNT_LIMIT_EXCEEDEDThe request exceeds a per-transaction, daily, or account limit.
AFX_PAYMENT_FAILEDThe payment leg failed at the payment rail.
AFX_COMPLIANCE_REJECTEDThe transaction was rejected during compliance review.
AFX_PROPOSAL_EXPIREDThe rate proposal expired before the transaction was committed. Start a fresh proposal.
The AFX_* set may grow over time as new failure modes are surfaced. Existing values will not change meaning. Handle unknown codes by falling back to message.

PaymentMethod

Empty fields are omitted from responses. Account-shaped channels (BANK_ACCOUNT, MOBILE_MONEY, SWIFT, etc.) populate accountName, accountNumber, and institution; the CARD channel instead populates last4, brand, expiration, and cardName.
FieldTypeDescription
paymentMethodIdstringUnique identifier for the payment method
customerIdstringID of the customer who owns this payment method
channelstringPayment channel. See Payment Channels
countryCodestringISO 3166-1 alpha-2 country code
currencystringISO 4217 currency code. Use this instead of inferring from countryCode, which is ambiguous (e.g. a USD account in a non-US country)
capabilitiesstring[]Operations this method is enabled for (e.g. DEPOSIT, WITHDRAW). Filterable via the capabilities query parameter on List Payment Methods
referencestringIdentifier used to reconcile incoming deposits against
accountNamestringAccount holder name. Present for account-shaped channels
accountNumberstringAccount number. Present for account-shaped channels
institutionobjectBank or provider details. See PaymentMethodInstitution
recipientobjectRecipient contact details. See PaymentMethodRecipient
transactionobjectPer-transaction overrides. See PaymentMethodTransaction
statusstringLifecycle status. See Payment Method Statuses
last4stringLast 4 digits of the card. CARD channel only
brandstringCard brand (e.g. Visa, MasterCard). CARD channel only
expirationobjectCard expiry with month and year. CARD channel only
cardNamestringName on the card. CARD channel only
expiresInMinutesintegerMinutes until a dynamic virtual account expires, when applicable
amountnumberRequested amount for a dynamic virtual account, when applicable
extraobjectAdditional channel-specific properties
metaobjectOptional metadata attached to the payment method

Payment Channels

ChannelDescription
BANK_ACCOUNTLocal bank account transfer
MOBILE_MONEYMobile money wallet (e.g. M-Pesa, MTN MoMo)
SWIFTInternational SWIFT wire transfer
INTERACInterac e-Transfer (Canada)
UPIUnified Payments Interface (India)
WE_CHATWeChat Pay
ALIPAYAlipay
CARDCard payment
CRYPTOCrypto rail
VIRTUAL_BANK_ACCOUNTHosted virtual bank account
POOL_ACCOUNTShared pool account for incoming deposits
ACH_BANK_ACCOUNTUS ACH bank transfer
PAYBILL_TILLPaybill / Till (M-Pesa business numbers)
RFPRequest for Payment
VIRTUAL_CARDVirtual card
Not every channel is valid when creating a payment method. The Create Payment Method endpoint accepts a narrower set of channels; the list above covers all channels that can appear on a returned payment method.

Payment Method Statuses

StatusDescription
activePayment method is active and usable
pendingPayment method is awaiting activation or verification
deletedPayment method has been deleted
expiredPayment method has expired (e.g. an expired card)
blockedPayment method has been blocked

PaymentMethodRecipient

Recipient contact details attached to a payment method, when supplied.
FieldTypeDescription
recipientNamestringName of the recipient
recipientEmailstring (email)Email address of the recipient
recipientPhonestringPhone number of the recipient in E.164 format
recipientAddressstringAddress of the recipient

PaymentMethodTransaction

Optional per-transaction details attached to a payment method.
FieldTypeDescription
transactionNarrationstringOptional reason or description for the transaction
transactionInvoicestringBase64-encoded invoice for the transaction

PaymentMethodInstitution

FieldTypeDescription
institutionIdstringUnique ID of the bank or mobile money provider
institutionNamestringDisplay name of the institution
institutionCodestringInstitution code (e.g. bank code)
institutionAddressstringPhysical address of the institution, if required
Use the List Institutions endpoint to retrieve valid institutions for a given country and channel.

Error Response

All API errors return a consistent JSON body:
FieldTypeDescription
codestringMachine-readable error code (e.g. AUTHENTICATION_ERROR)
errorstringShort error category (e.g. Bad Request)
details.errorMessagestringSpecific error reason (e.g. PHONE_COUNTRY_MISMATCH)
details.friendlyMessagestringUser-friendly message you can display to end users
details.dataobjectOptional caller-safe context. On a customer-create uniqueness conflict (EMAIL_ALREADY_EXISTS, PHONE_NUMBER_ALREADY_EXISTS) contains { customerId } for the existing customer so you can adopt it without a follow-up lookup
{
  "code": "INVALID_BUSINESS_CUSTOMER_REQUEST",
  "error": "Bad Request",
  "details": {
    "errorMessage": "PHONE_COUNTRY_MISMATCH",
    "friendlyMessage": "The phone number does not match the customer's country."
  }
}

Common error codes

CodeHTTP StatusDescription
AUTHENTICATION_ERROR401API key is missing or invalid
INVALID_BUSINESS_CUSTOMER_REQUEST400Customer request validation failed
PHONE_COUNTRY_MISMATCH400Phone number country does not match countryCode
EMAIL_ALREADY_EXISTS409A customer with this email already exists. details.data.customerId returns the existing customer’s id.
PHONE_NUMBER_ALREADY_EXISTS409A customer with this phone number already exists. details.data.customerId returns the existing customer’s id.
NOT_FOUND404The requested resource does not exist
RATE_LIMIT_EXCEEDED429Too many requests. Slow down and retry with backoff.