Afriex SDK
API Reference

Payment Methods API

Manage bank accounts, mobile money, crypto wallets, and virtual accounts.

Create Payment Method

const paymentMethod = await afriex.paymentMethods.create({
  channel: "BANK_ACCOUNT",
  customerId: "customer-id",
  accountName: "John Doe",
  accountNumber: "1234567890",
  countryCode: "NG",
  institution: {
    institutionCode: "044",
    institutionName: "Access Bank",
  },
});

customerId, channel and countryCode are always required. The account fields depend on the channel:

ChannelaccountNameaccountNumberinstitution
BANK_ACCOUNT, MOBILE_MONEY, SWIFT, ACH_BANK_ACCOUNT, WE_CHATRequiredRequiredRequired
UPI, INTERACRequiredRequiredNot needed
VIRTUAL_BANK_ACCOUNTNot neededNot neededNot needed

Creatable Channels:

ChannelDescription
BANK_ACCOUNTBank transfer
MOBILE_MONEYMobile money (M-Pesa, MTN, etc.)
VIRTUAL_BANK_ACCOUNTVirtual bank account
ACH_BANK_ACCOUNTUS ACH bank account
INTERACInterac (Canada)
UPIUnified Payments Interface (India)
SWIFTInternational SWIFT transfer
WE_CHATWeChat Pay and Alipay (China)

ALIPAY, CARD, CRYPTO, PAYBILL_TILL, POOL_ACCOUNT, RFP, and VIRTUAL_CARD are response-only channels — they're returned by get()/list() but can't be passed to create().

Alipay has no channel of its own. Create it on WE_CHAT with institution.institutionCode and institutionName both set to ALIPAY. Cards are collected through a checkout session.

For MOBILE_MONEY, send accountNumber as digits only: country code plus national number, such as 254712345678. A leading + is rejected.

Get Payment Method

const paymentMethod = await afriex.paymentMethods.get("payment-method-id");

The returned PaymentMethod carries currency, capabilities, status and reference. Virtual accounts and other provider-issued accounts also carry bankAddress, the issuing bank's postal address.

List Payment Methods

const response = await afriex.paymentMethods.list({
  page: 0,
  limit: 20,
  channel: ["BANK_ACCOUNT", "MOBILE_MONEY"],
  currencies: ["USD", "NGN"],
  status: ["active", "pending"],
});

Parameters:

FieldTypeDescription
pagenumberPage number, starting from 0
limitnumberItems per page (max 100)
channelstring | string[]One or more of BANK_ACCOUNT, MOBILE_MONEY, INTERAC, UPI, WE_CHAT, VIRTUAL_BANK_ACCOUNT, RFP, SWIFT
currenciesstring | string[]Filter by one or more 3-letter currency codes
capabilities"WITHDRAW"Only WITHDRAW is supported, and it is the default
statusstring | string[]active or pending. Defaults to both

Any other filter value answers 422. Deposit-only, deleted, expired and blocked payment methods cannot be listed; fetch them by ID.

Delete Payment Method

await afriex.paymentMethods.delete("payment-method-id");

Get Institutions

List supported banks or mobile money providers:

const response = await afriex.paymentMethods.getInstitutions({
  channel: "BANK_ACCOUNT",
  countryCode: "NG",
});

for (const institution of response.data) {
  console.log(institution.institutionName, institution.institutionCode);
}

// Returns: { data: Institution[], total, page }
// Institution: { institutionName, institutionCode, institutionAddress?, institutionBranch? }

Supported channels are BANK_ACCOUNT, SWIFT, MOBILE_MONEY and ACH_BANK_ACCOUNT. Any other channel answers 400 INVALID_TRANSACTION_CHANNEL.

Resolve Institution Code

Resolve a bank code (SWIFT code or US routing number) to the corresponding institution name:

const result = await afriex.paymentMethods.resolveInstitutionCode({
  searchTerm: "021000021",
  country: "US",
  codeType: "routing_number",
});

console.log(result.data?.bankName); // 'JPMORGAN CHASE BANK'

// Returns: { data: { bankName } }, with data null if the code does not resolve

country defaults to US and accepts any ISO country code for swift_code lookups; routing_number is only supported when country is US.

Resolve Account

Verify account details before creating a payment method:

const response = await afriex.paymentMethods.resolveAccount({
  channel: "BANK_ACCOUNT",
  accountNumber: "1234567890",
  institutionCode: "044",
  countryCode: "NG",
});

console.log(response.data.recipientName);

// Returns: { data: ResolvedAccount }
// ResolvedAccount: { recipientName?, institutionName?, institutionCode? }

institutionCode is required on both channels: the bank code for BANK_ACCOUNT, the provider code for MOBILE_MONEY.

Get Crypto Wallet

Get or create a crypto wallet address:

const response = await afriex.paymentMethods.getCryptoWallet({
  asset: "USDT", // or 'USDC'
  customerId: "optional-customer-id",
});

for (const { network, address } of response.data.addresses) {
  console.log(network, address);
}

// Returns: { data: { id, addresses: [{ address, network }] } }
// One wallet, carrying an address per supported network
// (ETHEREUM_MAINNET, POLYGON_MAINNET, SOLANA_MAINNET, TRON_MAINNET).

The API reference documents crypto wallets as production only.

List Virtual Accounts

Get existing virtual accounts for a customer:

const response = await afriex.paymentMethods.listVirtualAccounts({
  customerId: "customer-id",
  currency: "NGN",
});

// Returns: { data: PaymentMethod[], total, page }

The call is read-only. When no account exists it returns an empty list; it never creates one.

Create Virtual Account

Generate a new virtual account:

// Static: a permanent account, grouped by purpose
const staticAccount = await afriex.paymentMethods.createVirtualAccount({
  currency: "NGN",
  label: "SALES",
  customerId: "customer-id",
});

// Dynamic: a one-time account for a specific amount
const dynamicAccount = await afriex.paymentMethods.createVirtualAccount({
  currency: "NGN",
  amount: 50000,
  customerId: "customer-id",
});

if (dynamicAccount) {
  console.log(dynamicAccount.accountNumber, dynamicAccount.reference);
}

Parameters:

FieldTypeRequiredDescription
currencystringYes3-letter currency code
labelstringNo*One of SALES, OPERATIONS, PAYROLL, COLLECTIONS, VENDOR_PAYMENTS, TAX, REFUNDS, MARKETING, TREASURY, GENERAL
amountnumberNo*Amount for a dynamic account, which expires after a short window
customerIdstring-The customer to create the account for. Omit it to create one for the business. A customer's virtual account can only be NGN

*Mutually exclusive: provide label OR amount, not both.

createVirtualAccount() returns null when the issuing bank opens the account after the request returns. The account then arrives through the PAYMENT_METHOD.CREATED webhook.

Simulate a Transfer (Sandbox)

A sandbox virtual account receives no money on its own. Credit one the way a real bank transfer would:

const transfer = await afriex.paymentMethods.simulateTransfer({
  accountNumber: "6520751033",
  amount: 2500,
  currency: "NGN",
});

console.log(transfer.reference);

Parameters:

FieldTypeRequiredDescription
accountNumberstringYesThe virtual account number to pay into
amountnumberYesThe amount transferred
currencystringYesThe account's currency
referencestring-The reference a one-time account was issued with. Needed only for that account
outcome"success" | "failed"-Defaults to success

The deposit is reported by the transaction webhook, and the balance changes as it would in production.

Sandbox only. Production answers 403.

Get Pool Account

Get the pool account for a supported country:

const poolAccount = await afriex.paymentMethods.getPoolAccount({
  customerId: "customer-id",
  country: "NG",
});

console.log(poolAccount.accountNumber, poolAccount.reference);

Pool accounts are shared across multiple customers in a country. Use the reference on the returned payment method to reconcile incoming deposits. Every call also sends a PAYMENT_METHOD.UPDATED webhook carrying the pool account.

listPoolAccounts() is the deprecated name for the same call.

After a customer pays into the pool account, submit the proof of payment to have the deposit credited.

On this page