Fund a Card via Bank Transfer

Bank-rail (fiat) funding requires registering the cardholder's sending bank account, after which the cardholder initiates a transfer using your Program's inbound bank details. An optional trace notification can be sent to expedite straight-through processing. This guide walks through every step.

Prerequisites

  • The card must be issued (cardId exists).
  • The cardholder must have status = 1 (Approved) — bank account registration is a cardholder-level operation.
  • Your Program's inbound bank credentials (account number, routing/sort code, BIC/SWIFT, reference format) must be retrieved from Account Management in the production environment — they are not available via the program-level API. See Funding & Deposits: Step 2.

Step 1: Register the cardholder's bank account

POST /cardholders/{cardholderId}/register-bank-account

This registers the sending bank account — the cardholder's own bank account from which they will initiate the transfer.

FieldRequiredConstraintsDescription
senderAccountNameYesmax 50 charsThe name on the cardholder's bank account
senderAccountNumberYes7–34 charsBank account number, IBAN, or equivalent
senderRoutingNumberYes6–12 charsRouting number, BIC/SWIFT, sort code, or equivalent

Example request

{
  "senderAccountName": "Jordan Reyes",
  "senderAccountNumber": "GB29NWBK60161331926819",
  "senderRoutingNumber": "NWBKGB2L"
}

Response:

{
  "depositId": 7741,
  "statusText": "pending"
}

The SMS OTP confirmation

❗️

Bank account registration is not completable via the API alone. After this call, the cardholder receives an SMS from an anonymous short code (by default) and must reply to that SMS to confirm the registration. The reply-to-confirm methodology is a deliberate security design: it prevents internal personnel from associating an arbitrary bank account with a card programmatically, which would otherwise create a mechanism for diverting incoming funds.

Design your application UX to instruct the cardholder to look out for and reply to this SMS before attempting to fund their card.

You only need to register a bank account once per cardholder per bank account. Once confirmed via SMS reply, subsequent deposits from that account are matched automatically.


Step 2: Cardholder initiates the transfer

The cardholder sends a bank transfer from their registered account to your Program's inbound bank account, using your Program's reference format to ensure the transfer is matched to the correct card.

🚧

Program inbound bank credentials are only available in Account Management (production). The account number, sort code/routing number, BIC/SWIFT, and required payment reference format for receiving deposits are not exposed by the program-level API. Retrieve them from Account Management and present them to the cardholder within your application's funding-instructions UX.

Typical reference format guidance (confirm with Axys):

  • Include the cardId as the payment reference, or use a Program-specific reference format configured in Account Management
  • Instruct the cardholder to use the exact reference — missing or mismatched references slow matching and may require manual reconciliation

Preventing unallocated deposits — critical

❗️

Never direct a cardholder to send a transfer before completing bank account registration. Transfers that cannot be matched automatically are placed in a suspense account — not returned immediately and not credited to any card. This is most likely when a cardholder sends funds from an unregistered bank account, uses a wrong or missing payment reference, or targets a card that isn't issuerCardStatus = 1 (Active).

Funds held in suspense create AML, KYT, and Source of Funds compliance exposure. Processing times and outcomes cannot be guaranteed, and unmatched funds may be returned to the originating source less correspondent banking or banking partner fees.

Always confirm bank account registration is complete (including the cardholder's SMS reply) and the card is Active before sharing your Program's funding instructions. See Funding & Deposits: Suspense accounts and unallocated deposits for the full prevention checklist and how to respond if funds are unallocated.


Step 3: Post a trace notification (optional but recommended)

POST /cards/{cardId}/bank-deposit

A trace notification pre-matches the transfer to the card, expediting straight-through processing. All fields are optional — include whatever details you have from the payment initiation:

FieldTypeDescription
transactionAmountintegerExpected amount (decimal-implied, e.g. 10000 = $100.00)
transactionReferencestringThe unique transaction reference or payment ID from the bank's remittance advice or transaction receipt
senderAccountNamestringThe sender's bank account name
senderAccountNumberstringThe sender's account number, IBAN, or equivalent
senderRoutingNumberstringThe sender's routing number, BIC/SWIFT, or sort code

Example request

{
  "transactionAmount": 50000,
  "transactionReference": "WIRE-20240614-001",
  "senderAccountName": "Jordan Reyes",
  "senderAccountNumber": "GB29NWBK60161331926819",
  "senderRoutingNumber": "NWBKGB2L"
}

Response:

{
  "depositId": 7742,
  "statusText": "pending"
}

The more fields you include, the more precisely the platform can match the inbound transfer. At minimum, transactionReference is the most useful single field if you have it.

Wallet-level bank deposits

To direct a bank deposit to a Wallet rather than a Card, use the equivalent endpoint:

POST /wallets/{walletId}/bank-deposit

The request and response schemas are identical. Funds land in the Wallet's fiat balance and can then be transferred to Cards or other Wallets — see Transfer Internal Fiat Funds.


Step 4: Monitor the balance

Poll GET /cards/{cardId}/balance to track the deposit:

flowchart LR
    A["Transfer initiated"] --> B["Transfer arrives\nat Axys\n(correspondent banking)"]
    B --> C["ledgerBalance increases\nstatus: PENDING"]
    C --> D{"Clearing complete\n(~5 business days)"}
    D --> E["availableBalance increases\nstatus: COMPLETE\nFunds spendable"]
StageledgerBalanceavailableBalance
Transfer not yet arrivedUnchangedUnchanged
Transfer received, clearing in progressIncreasedUnchanged
Transfer cleared and settledIncreasedIncreased
📘

Clearing window. Bank-rail funds typically take 3–5 business days from transfer initiation to availableBalance update, depending on the sending country, correspondent banking relationships, and payment rail used (SWIFT, domestic ACH/BACS/SEPA, etc.). Funds in ledgerBalance but not yet in availableBalance are reserved and cannot be spent.

Recommended polling intervals for bank deposits

Time since trace notification or expected transferInterval
Day 1Every 6–12 hours
Days 2–5Once daily
Day 6+ without availableBalance updateRaise a support ticket referencing depositId

Troubleshooting

IssueLikely causeResolution
ledgerBalance not updated after 5+ business daysTransfer not yet received; reference mismatch; transfer returned by correspondent bankRaise a support ticket with depositId, transactionReference, and transfer confirmation from your bank
Cardholder didn't receive the SMS OTPWrong phone number on the cardholder record; SMS delivery delayVerify cellNum on the cardholder record; ask cardholder to wait up to 10 minutes; raise support ticket if not received
Cardholder lost the SMS OTP before replyingSMS expired or missedRaise a support ticket to reset the bank account registration

What's next