Payouts
Payouts move money out of a workspace wallet. The API exposes three related operations:
- Transfers — send to any bank account.
- Bank lookup — list banks and resolve an account name before sending.
- Withdrawals — send to a saved beneficiary, using the same ledger path as a
transfer but recording the outflow with
channel: "payout".
Every payout debits the wallet in the requested currency and creates a ledger transaction you can
read from Balances & transactions. NGN payouts are live; the wallet catalog marks EUR
and GBP as sandbox and USD/USDT/JPY as coming_soon, so a payout in a coming_soon currency
returns 501.
Endpoints
Section titled “Endpoints”| Method | Path | Scope | Success |
|---|---|---|---|
POST |
/v1/transfers |
payouts:write |
201 |
GET |
/v1/banks |
read |
200 |
POST |
/v1/banks/resolve |
read |
200 |
POST |
/v1/withdrawals |
payouts:write |
201 |
Send a transfer
Section titled “Send a transfer”POST /v1/transfers
| Field | Type | Required | Notes |
|---|---|---|---|
currency |
string | Yes | Uppercased by the API. Must exist in the wallet catalog and not be coming_soon |
amount |
number | Yes | Major units, minimum 1 |
account_number |
string | Yes | Destination account |
bank_code |
string | No | Required in practice for NGN bank transfers |
account_name |
string | No | Sent to the rail and recorded on the ledger row |
bank_name |
string | No | Display/ledger metadata |
narration |
string | No | Defaults to Telliport transfer at the rail |
idempotency_key |
string | No | Ledger-level de-duplication key (see Idempotency) |
curl -X POST https://api.nuansis.co/v1/transfers \ -H "Authorization: Bearer $NUANSIS_API_KEY" \ -H "Idempotency-Key: payout-2026-10-18-0007" \ -H "Content-Type: application/json" \ -d '{ "currency": "NGN", "amount": 50000, "account_number": "0123456789", "bank_code": "058", "account_name": "Adaeze Okafor", "bank_name": "Guaranty Trust Bank", "narration": "October salary", "idempotency_key": "payout-2026-10-18-0007" }'{ "data": { "id": 4421, "type": "debit", "direction": "out", "category": "send", "channel": "transfer", "status": "completed", "reference": "snd_9f2c1a7b4e6d8c0a1b", "idempotencyKey": "payout-2026-10-18-0007", "businessId": 42, "walletId": 7, "currency": "NGN", "amount": "50000.000000", "fees": "0.000000", "title": "Send money", "description": "October salary", "provider": "novac", "providerReference": "nv_8c1e2f3a", "counterpartyName": "Adaeze Okafor", "counterpartyAccount": "0123456789", "counterpartyBank": "Guaranty Trust Bank", "counterpartyEmail": null, "metadata": { "provider": "novac", "raw": {} }, "createdAt": "2026-10-18T10:26:07.412Z", "updatedAt": "2026-10-18T10:26:08.118Z" }, "meta": { "request_id": "3d4e5f6a-7b8c-4d9e-0f1a-2b3c4d5e6f70" }}Response shape
Section titled “Response shape”Transfers and withdrawals return the raw ledger transaction, which uses camelCase keys and string decimals:
| Field | Notes |
|---|---|
id |
Ledger transaction id |
type |
debit for payouts |
direction |
out |
category |
send for transfers, payout for withdrawals |
channel |
transfer for transfers, payout for withdrawals |
status |
processing, completed, failed, or reversed |
reference |
Nuansis-generated snd_… reference |
amount, fees |
Decimal strings with 6 fractional digits |
providerReference |
The rail’s reference, when one was returned |
counterparty* |
Name, account, bank, and email as supplied or resolved |
The transaction row is created with status processing before the rail is called. If the rail
throws, the row is marked failed and the API returns the provider error; if it succeeds, the row
becomes completed (or failed if the rail reports a failure). This means a failed payout is
recorded — it is not erased.
Pre-flight checks
Section titled “Pre-flight checks”Before calling the rail, the API:
- Uppercases and validates the currency against the wallet catalog.
- Loads the wallet for that currency. A missing wallet returns an error rather than creating one.
- Compares
amountwith the available balance and fails with400 invalid_request/Exceeds balance: <available> <currency>if insufficient. - De-duplicates on
idempotency_key(or the generatedsnd_…reference if none was supplied).
Available balance excludes pending holds; see Balances & transactions.
List banks
Section titled “List banks”GET /v1/banks?country=NG
{ "data": [ { "bankCode": "058", "bankName": "Guaranty Trust Bank" }, { "bankCode": "033", "bankName": "United Bank for Africa" }, { "bankCode": "011", "bankName": "First Bank of Nigeria" } ], "meta": { "request_id": "4e5f6a7b-8c9d-4e0f-9a1b-2c3d4e5f6a7b" }}country is accepted but the current NGN lookup rail always returns Nigerian banks; it defaults to
NG when omitted. Bank fields are camelCase (bankCode, bankName).
Resolve an account
Section titled “Resolve an account”POST /v1/banks/resolve
| Field | Type | Required | Notes |
|---|---|---|---|
account_number |
string | Yes | Account to resolve |
bank_code |
string | Yes | Bank from the list above |
currency |
string | No | Defaults to NGN |
curl -X POST https://api.nuansis.co/v1/banks/resolve \ -H "Authorization: Bearer $NUANSIS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "account_number": "0123456789", "bank_code": "058", "currency": "NGN" }'{ "data": { "accountName": "ADAEZE OKAFOR", "accountNumber": "0123456789", "bankCode": "058", "bankName": "Guaranty Trust Bank" }, "meta": { "request_id": "5f6a7b8c-9d0e-4f1a-8b2c-3d4e5f6a7b8c" }}Resolve before every payout: the returned accountName is the name to pass as account_name, and
it catches typos in the account number before money moves.
Withdraw to a beneficiary
Section titled “Withdraw to a beneficiary”POST /v1/withdrawals
| Field | Type | Required | Notes |
|---|---|---|---|
currency |
string | Yes | Uppercased; the beneficiary also has a currency |
amount |
number | Yes | Minimum 1 |
beneficiary_id |
integer | Yes | Id from GET /v1/beneficiaries |
narration |
string | No | Defaults to Withdrawal to <beneficiary name> |
idempotency_key |
string | No | Ledger-level de-duplication key |
curl -X POST https://api.nuansis.co/v1/withdrawals \ -H "Authorization: Bearer $NUANSIS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "currency": "NGN", "amount": 25000, "beneficiary_id": 17, "narration": "Vendor settlement" }'The response is a ledger transaction with category: "payout" and channel: "payout". An unknown
or inactive beneficiary returns 404 not_found with message Beneficiary not found.
Common errors
Section titled “Common errors”| Status | Code | Cause |
|---|---|---|
400 |
invalid_request |
Insufficient balance, unsupported currency, missing field |
401 |
unauthorized |
Missing or invalid API key |
403 |
insufficient_scope |
Key lacks payouts:write |
404 |
not_found |
Unknown beneficiary, or no wallet exists for the requested currency |
429 |
rate_limited |
Request budget exhausted |
501 |
coming_soon |
Currency marked coming_soon in the wallet catalog |
503 |
provider_error |
Payout rail not configured or unavailable |
502 / 504 |
provider_error |
Rail failure or timeout |