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
sourceAmountnumber | ${number}One of the two amountsAmount in source currency. Send it alone and the API derives the destination amount at the live rate
destinationAmountnumber | ${number}One of the two amountsAmount in destination currency. Send it alone and the API derives the source amount. A SWAP takes exactly one of the two
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.invoicestringYes for SWIFT withdrawalsObject key of the uploaded invoice, as returned by the media upload endpoint. The file must already exist in storage
meta.settlement"spot" | "request"-spot (default) debits the Payout wallet at once. request is for WITHDRAW only: it debits the Collection wallet and queues the payout for the next business day
correspondentBankNamestring-Correspondent bank name for a USD payout with meta.settlement: "request". A fallback for the value on the payment method. Send it together with correspondentBankAccountNumber
correspondentBankAccountNumberstring-Correspondent bank account number. Send it together with correspondentBankName
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",
});

Submit a Pool-Account Payment Proof

When a customer pays into your pool account, submit the proof of payment so the deposit can be confirmed and credited.

import { readFile } from "node:fs/promises";

const proof = await afriex.media.upload({
  fileName: "transfer-receipt.pdf",
  type: "transaction",
  file: await readFile("./transfer-receipt.pdf"),
});

const deposit = await afriex.transactions.submitPoolAccountProof({
  amount: 5000,
  customerId: customer.customerId,
  countryCode: "NG",
  reference: customer.reference,
  fileKey: proof.key,
  timestamp: new Date("2026-05-18T10:00:00.000Z"),
  senderDetails: { name: "John Doe", bankName: "GTBank" },
});

console.log(deposit.status); // IN_REVIEW

Parameters:

FieldTypeRequiredDescription
amountnumberYesThe deposit amount, in the major currency unit
customerIdstringYesThe customer to credit. It must be the customer reference names
countryCodestringYesISO 3166-1 alpha-2 code of the pool account
referencestringYescustomer.reference to credit a customer, or the pool account's own reference to credit the business
fileKeystringYesThe key of the uploaded proof. Upload it with type: "transaction"
timestampstring | DateYesWhen the payment was sent
senderDetailsobject-name (required when the object is sent), accountNumber, bankName, countryCode

The deposit is created IN_REVIEW. An operator then confirms the bank inflow: approval arrives as a TRANSACTION.CREATED webhook, rejection as POOL_DEPOSIT_REQUEST.REJECTED.

A second submission that matches on every field is rejected with 409.

Get a Settlement Advice

A USD withdrawal created with meta.settlement: "request" gets a settlement and remittance advice, as a PDF.

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

console.log(advice.url, advice.status, advice.version);
FieldTypeDescription
urlstringDownload URL for the PDF, valid for 5 minutes
referencestringThe advice reference. It stays the same when the advice is regenerated
status"PENDING" | "COMPLETED"PENDING until the withdrawal succeeds
versionnumberStarts at 1 and goes up when the advice is regenerated
generatedAtstringWhen this version was generated

Any other transaction answers 404. The advice is not a tax invoice.

Simulate an Outcome (Sandbox)

Complete a pending sandbox transaction now, with the outcome you choose.

const transaction = await afriex.transactions.simulate("transaction-id", {
  outcome: "failed", // or "success"
});

The transaction must still be PENDING, PROCESSING or UNKNOWN. A deposit waiting for an OTP has to be authorized first.

simulate() returns the transaction as it stands before it is finalized. The final status arrives a few seconds later through the TRANSACTION.UPDATED webhook, or on the next get().

Sandbox only. Production answers 403.

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