Cashout
Cashout pays fiat directly to a recipient's bank account, debiting your crypto fund. You name the recipient yourself, in the order itself.
- Quote it —
review-cashout. - Create it —
create-cashout. - Track it —
orders/details, plus a webhook.
The user must be KYC-verified first. See KYC. Cashout and scan-to-pay share the same order lookup, the same order object, and the same webhook.
Quote a cashout
POST /api/v2/orders/review-cashout
Signed string
partnerCode|userEmail|fiatCurrency|fiatAmount|cryptoCurrency|<secretKey>
Request — every field is required.
| Field | Type | Notes |
|---|---|---|
partnerCode | string | |
userEmail | string | The end user. |
fiatCurrency | string | VND, PHP, IDR… |
fiatAmount | number | What the recipient receives. |
cryptoCurrency | string | The crypto to debit — USDT. |
signature | string |
Response data
| Field | Type | Notes |
|---|---|---|
fiatAmount | number | Echoed from your request. |
currency | string | The crypto code. |
price | number | |
tokenAmount | number | The crypto that will be debited. |
totalPayment | number | |
processingFee, systemFee | number | |
signature | string | Over fiatAmount|currency|price|tokenAmount|totalPayment|secretKey. |
The live minimum and maximum reach you through errors 24 and 25, whose messages carry the
current limit.
Errors — 46 SERVICE_NOT_AVAILABLE, 24 / 25 (below min / above max), 16
AMOUNT_OUT_OF_RANGE (below the payment provider's own floor, 10,000 VND for Vietnam), 7
PARTNER_INSUFFICIENT_BALANCE, 9 SERVICE_UNDER_MAINTENANCE, plus the KYC codes (34, 59, 60,
61, 62, 64) and the shared ones.
Create a cashout
POST /api/v2/orders/create-cashout
Signed string
partnerCode|externalOrderId|userEmail|cryptoCurrency|fiatCurrency|fiatAmount|<secretKey>
The string is cashout's own — different from scan-to-pay's in both fields and order. It signs
cryptoCurrency and fiatCurrency, and the recipient's bank details travel in extendInfo,
outside the signature. Sign exactly the string above.
Every segment is always interpolated: an omitted fiatCurrency or fiatAmount puts the literal
text undefined into its place, and the order then fails with 46. Send both fields.
Request
| Field | Type | Required | Notes |
|---|---|---|---|
partnerCode | string | Yes | |
externalOrderId | string | Yes | Your unique id, and the idempotency key. |
userEmail | string | Yes | Must be KYC-verified. |
cryptoCurrency | string | Yes | The crypto to debit — USDT. |
fiatCurrency | string | Yes | Omitting it is not rejected as a missing field, and no default is applied. See above. |
fiatAmount | number | Yes | Same. |
extendInfo | object | Yes | The recipient. |
webhookSecretKey | string | No | Without it the order settles silently, read through orders/details. |
signature | string | Yes |
extendInfo — the recipient
| Field | Type | Required | Notes |
|---|---|---|---|
recipientName | string | Yes | |
recipientNumber | string | Yes | The bank account number. |
recipientBankCode | string | Yes | From the bank list. |
transferContent | string | No | The transfer remark. Unaccented letters only, where the provider checks it. |
recipientType | string | No | If you send it, it must be a recognised value — otherwise 5. |
{
"partnerCode": "ACME",
"externalOrderId": "acme-co-1042",
"cryptoCurrency": "USDT",
"fiatCurrency": "VND",
"fiatAmount": 5000000,
"webhookSecretKey": "81663eae...",
"extendInfo": {
"recipientName": "NGUYEN VAN A",
"recipientNumber": "0123456789",
"recipientBankCode": "VCB",
"transferContent": "ALIX CASHOUT 1042"
},
"signature": "I7XDfTngWIraq...=="
}
Response data — the order object, with type: "CASHOUT".
For a cashout, tokenTransfer.address, tokenTransfer.network and bankTransfer.qrUrl are
null; the payout goes straight to the recipient's bank account.
Errors — everything review-cashout can return, plus:
11 DUPLICATE_TRANSACTION_ID | externalOrderId is already used. |
13 WEBHOOK_SECRET_NOT_FOUND | webhookSecretKey matches no registered endpoint. Checked before anything else, so the order is not created. |
18 INVALID_BANK_ACCOUNT | extendInfo is missing, or the account could not be verified. |
56 BANK_NOT_SUPPORTED | recipientBankCode is not in the provider's list. |
17 INVALID_TRANSFER_CONTENT | transferContent has accents or special characters. |
27 USER_EMAIL_INVALID | userEmail is malformed. |
5 INVALID_REQUEST_DATA | recipientType is not a recognised value. |
12 TRANSACTION_CREATE_FAILED | The payout failed after the order was created. You are already refunded, and data holds the order. |