Afriex SDK
API Reference

Transactions API

Create and track money transfers.

Create Transaction

Withdraw (Default)

Send funds to a customer's payment method:

const transaction = await afriex.transactions.create({
  customerId: "customer-id",
  sourceAmount: "10",
  destinationAmount: "5000",
  sourceCurrency: "USD",
  destinationCurrency: "NGN",
  destinationId: "payment-method-id",
  meta: {
    idempotencyKey: "unique-key-123",
    reference: "order-456",
    narration: "Payment for services",
  },
});

Deposit

Pull funds from a customer's payment method:

const transaction = await afriex.transactions.create({
  customerId: "customer-id",
  type: "DEPOSIT",
  sourceAmount: "10",
  destinationAmount: "5000",
  sourceCurrency: "USD",
  destinationCurrency: "NGN",
  sourceId: "source-payment-method-id",
  meta: {
    idempotencyKey: "unique-key-456",
    reference: "deposit-789",
  },
});

Swap

Exchange funds between currencies in the business wallet:

const transaction = await afriex.transactions.create({
  type: "SWAP",
  sourceAmount: "10",
  sourceCurrency: "USD",
  destinationCurrency: "NGN",
  meta: {
    idempotencyKey: "unique-key-789",
    reference: "swap-101",
  },
});

Parameters

FieldTypeRequiredDescription
customerIdstringYes for DEPOSIT and WITHDRAWCustomer ID. Optional for SWAP when using the business wallet
sourceAmount${number}YesAmount in source currency
destinationAmount${number}Yes for DEPOSIT and WITHDRAWAmount in destination currency. Optional for SWAP; the API calculates it
sourceCurrencystringYesSource currency (e.g., USD)
destinationCurrencystringYesDestination currency (e.g., NGN)
typestring-WITHDRAW (default), DEPOSIT, or SWAP
destinationIdstringYes for WITHDRAWPayment method to send to
sourceIdstringYes for DEPOSITPayment method to pull from
meta.idempotencyKeystringYesUnique key to prevent duplicates
meta.referencestringYesYour internal reference
meta.narrationstring-Transaction description
meta.invoicestring-Base64-encoded invoice document
shouldPreferSourceAmountboolean-Derive destinationAmount from sourceAmount via the forward rate even when both are sent. Defaults to false (destination-wins)

Get Transaction

const transaction = await afriex.transactions.get("transaction-id");

List Transactions

const response = await afriex.transactions.list({
  page: 0,
  limit: 20,
  status: ["PENDING", "PROCESSING"],
  currency: ["USD", "NGN"],
  fromDate: "2025-01-01T00:00:00.000Z",
  toDate: "2025-01-31T23:59:59.999Z",
});

console.log(response.data); // Transaction[]

Supported filters:

FieldTypeDescription
transactionIdstringFilter by Afriex transaction ID
referencestringFilter by meta.reference
statusstring | string[]One or more transaction statuses
typestring | string[]One or more transaction types
channelstring | string[]One or more source or destination payment channels
currencystring | string[]One or more 3-letter currency codes
fromDatestringISO 8601 lower bound for creation time
toDatestringISO 8601 upper bound for creation time

Authorize Transaction

Complete a transaction left in CUSTOMER_ACTION_REQUIRED that needs an extra authorization step — for example, an OTP on a mobile-money deposit (meta.otpRequired: true). Today the only supported variant is OTP.

const transaction = await afriex.transactions.authorize("transaction-id", {
  type: "OTP",
  otp: "123456",
});

Status Values

StatusDescription
PENDINGCreated, awaiting processing
PROCESSINGCurrently processing
SUCCESSSuccessful
FAILEDFailed
CANCELLEDCancelled
REFUNDEDRefunded
RETRYRetrying
UNKNOWNStatus unknown
SCHEDULEDScheduled for later execution
CUSTOMER_ACTION_REQUIREDWaiting on customer action — see Authorize Transaction
REJECTEDRejected
IN_REVIEWUnder review
DISPUTEDDispute opened
DISPUTE_RESOLVEDDispute resolved
DISPUTE_WONDispute resolved in your favor
DISPUTE_LOSTDispute resolved against you
DISPUTE_EVIDENCE_SUBMITTEDEvidence submitted for dispute

Failure Reasons

When status is FAILED or REJECTED, meta.failureReason carries a stable Afriex-side code (AFX_*, e.g. AFX_VELOCITY_LIMIT_EXCEEDED), a customer-safe message, and a retryable boolean — switch on code, not message.

On this page