Errors
On failure you get a non-200 status and a unified error body:
json
{
"code": 400,
"reason": "AMOUNT_BELOW_MIN",
"message": "amount below minimum",
"metadata": { "minAmount": "10" }
}| Field | Description |
|---|---|
code | HTTP status code |
reason | Stable error identifier — branch on this |
message | English text for developers; may change, don't parse it |
metadata | Dynamic parameters (string → string), see below |
Reasons
| reason | HTTP | Meaning | metadata |
|---|---|---|---|
BAD_REQUEST | 400 | Invalid parameters (missing field, bad format, …) | |
VALIDATOR | 400 | Field validation failed; message names the field | |
TOO_MANY_REQUESTS | 429 | Too many requests; retry later | |
NOT_FOUND | 404 | Resource not found | |
MERCHANT_AUTH_FAILED | 401 | Invalid / disabled API key, disabled merchant, or missing signature headers | |
SIGNATURE_INVALID | 401 | Signature mismatch | |
REQUEST_EXPIRED | 401 | X-Timestamp missing or outside ±30 s | |
NONCE_REPLAYED | 401 | X-Nonce reused or of invalid length | |
IP_NOT_ALLOWED | 403 | Source IP not in the allowlist | |
PERMISSION_DENIED | 403 | The API key lacks the required scope | |
CHAIN_NOT_SUPPORTED | 400 | Chain unknown or disabled | |
TOKEN_NOT_SUPPORTED | 400 | Token unknown or not configured on this chain | |
ADDRESS_INVALID | 400 | Malformed address | |
USER_NOT_FOUND | 404 | User wallet does not exist (no address requested yet) | |
INSUFFICIENT_BALANCE | 400 | Insufficient user balance (internal transfer) | |
TX_NOT_CREDITABLE | 400 | Rescan: transaction not found, not yet on-chain, failed, or not paying a platform address | |
RECREDIT_REJECTED | 403 | Rescan: the receiving address does not belong to this user | |
WITHDRAW_DISABLED | 403 | Withdrawals are not enabled for the merchant | |
WITHDRAW_NOT_ALLOWED | 400 | Withdrawals of this token on this chain are not allowed | |
AMOUNT_BELOW_MIN | 400 | Below the minimum withdrawal amount | minAmount |
DUPLICATE_REQUEST | 409 | biz_id already exists | withdrawId, status |
INVALID_STATE | 409 | The current state does not allow this operation | |
HOT_WALLET_INSUFFICIENT | 409 | Platform outbound wallet balance is insufficient; retry later or contact us | |
SIGNER_UNAVAILABLE | 503 | Signing service temporarily unavailable; retry later | |
CHAIN_RPC_UNAVAILABLE | 503 | Chain node temporarily unavailable; retry later | |
INTERNAL | 500 | Internal server error |
Retrying
- 5xx and network errors: safe to retry. For
POST /v1/withdrawsalways retry with the samebiz_id. - 4xx: fix the request first; an identical retry will fail again.
DUPLICATE_REQUESTmeans an earlier attempt succeeded — continue withmetadata.withdrawId. - New reasons may be added; fall back to the HTTP status for unknown ones.