Skip to main content
POST
Create a transfer destination

Three shapes, one endpoint

Every “not found” looks the same

For own_account and sakawave_tag, one code covers every reason the target cannot receive: it does not exist, it is not active, it cannot be credited, its currency differs, or — for your own accounts — it is a customer wallet or is not yet transferReady.
That is deliberate: a caller must not be able to probe which accounts exist. When you meet it against your own account, read the account and check status, canCredit, currency, and transferReady yourself.
You cannot use own_account to pay a customer wallet. Wallets are excluded from that shape; pay them by sakawave_tag.

The counterparty profile

On an external route that settles through the international provider, four fields are required by the payout rail even though the parser treats them as optional: recipientRelationship, recipientEmail, recipientAddressLine1, and recipientCity, plus a resolved country. Omitting them fails with 422 recipient_profile_incomplete, listing each one. Domestic NGN routes do not ask for them.

Verification

Where the route supports it, Sakawave looks the account up with the provider and replaces accountName with the verified name. The displayName you get back is therefore the name the bank holds, not the name you sent — show it to the payer before they confirm.

Error codes

Authorizations

Authorization
string
header
required

A secret API key, sent as Authorization: Bearer sk_test_… in sandbox or Bearer sk_live_… in live.

Body

application/json
type
any
required
accountId
string
required

A 26-character ULID.

Required string length: 26
Pattern: ^[0-7][0-9A-HJKMNP-TV-Z]{25}$
Example:

"01K2Z3AB4C5D6E7F8G9HJKMNPQ"

currency
enum<string>
required
Available options:
NGN,
USD,
GBP,
EUR,
GHS,
ZAR,
UGX,
CAD,
MXN,
AED

Response

Successful response.

id
string
required

Send this as destinationId when previewing or creating a transfer.

Required string length: 26
Pattern: ^[0-7][0-9A-HJKMNP-TV-Z]{25}$
Example:

"01K2Z3AB4C5D6E7F8G9HJKMNPQ"

type
enum<string>
required
Available options:
own_account,
sakawave_tag,
external
currency
enum<string>
required
Available options:
NGN,
USD,
GBP,
EUR,
GHS,
ZAR,
UGX,
CAD,
MXN,
AED,
AUD,
SGD,
HKD,
KES,
TZS,
BRL,
CNY,
XAF,
PHP,
USDC
displayName
string
required

The verified account name for an external destination, the account name for your own, or the resolved holder for a tag.

routeId
string | null
required

The payout route, for external destinations.

Required string length: 26
Pattern: ^[0-7][0-9A-HJKMNP-TV-Z]{25}$
Example:

"01K2Z3AB4C5D6E7F8G9HJKMNPQ"

recipientId
string | null
required

The saved recipient this was built from, when it was.

Required string length: 26
Pattern: ^[0-7][0-9A-HJKMNP-TV-Z]{25}$
Example:

"01K2Z3AB4C5D6E7F8G9HJKMNPQ"

institutionName
string | null
required
accountNumberLast4
string | null
required

The only part of the destination account number ever returned.

Required string length: 4
expiresAt
string<date-time>
required
Example:

"2026-08-14T09:00:00.000Z"