Skip to main content
This guide sends one payout to one bank account. You pick the bank, check the account name, send the money, and read the transfer back to confirm it settled. Every step is one API call. All of them live on the accounts service:

What you’ll need

  • Your secret key. Every call in this guide authenticates with it.
  • A funded account in the currency you are paying out. See Give a Customer a Virtual Account for reading balances.
  • The recipient’s account number and their bank.
Transfers are on /accounts/api/v1, not /gateway/api/v1 — including /transfers/banks/{currency}. The gateway path returns 404 No static resource.

The shape of the flow

1

Find the bank code

List the banks for the currency and pick the recipient’s.
2

Resolve the account name

Check the account number maps to a real name before you send.
3

Send the transfer

One call, with your own reference attached.
4

Read it back

Look the transfer up by your reference and confirm it settled.

Step 1: Find the bank code

Spotflow has its own bank codes. They look like SPB-60046 and they are not NIBSS or CBN codes.
The path segment is a currency, not a country: GHS, NGN, and so on.
For NGN, some entries carry the local codes in metadata, which is empty for Ghana:
You still send bankCode in the transfer. The metadata is there for reconciling against your own records.

Step 2: Resolve the account name

Before sending, confirm the account number belongs to who you think it does.
Both accountNumber and bankCode are required.
In test mode this does not really validate anything. The dev resolver is a mock: it returns John Doe for any account number, and it returns 200 even for a bank code that does not exist, such as SPB-00000. Do not build a “the account is valid” check on a 200 from this endpoint in test mode. Verify the behaviour again in live mode before you rely on it.

Step 3: Send the transfer

Three things to read carefully:
  • There are two references. Yours (reference) and Spotflow’s (spotflowReference, an SPF-TRSF-… string). You look the transfer up by yours; support will ask for Spotflow’s.
  • fee is charged on top of amount, and it is flat. Here the fee is 12.00 GHS on a 5.00 GHS transfer — more than twice the amount being sent. Batch small payouts rather than sending them one at a time.
  • status is processing, not done. The money has been accepted, not delivered.

Your reference is the idempotency key

Sending the same reference again is rejected:
400, and no second payout. This is what makes a retry safe: if your request times out and you do not know whether it landed, send it again with the same reference. You will either create it once or get this error — never pay twice.
A reference shorter than 5 characters is rejected before anything happens:

Step 4: Read the transfer back

Look it up with your reference:
status has moved from processing to successful. That is the transfer delivered.
In test mode this takes a few seconds. Poll every few seconds rather than in a tight loop, and treat processing as “not finished” — not as a failure.
If you kept the internal id instead, GET /transfers/{id} returns the same shape.

When things go wrong

GET /transfers/resolve-fee is documented as taking amount, currency and type, but every type value we tried on dev was rejected with Invalid transaction type, and the spec declares no enum for it. Until that is settled, take the fee from the fee field on the transfer response.

What to do next