Error catalog
Every error response has the same envelope:
{
"error": {
"code": "INVALID_INPUT",
"message": "human-readable explanation",
"request_id": "uuid-for-support"
}
} The code field is stable and machine-readable. The message is for humans and may change between releases. Log request_id and include it in any support request.
Error codes
| Code | HTTP | Common cause | Fix |
|---|---|---|---|
INVALID_INPUT | 400 | Missing required field, value out of range, bad format (e.g. non-numeric amount). | Read the message; it names the offending field. |
IDEMPOTENCY_REQUIRED | 400 | Idempotency-Key header absent or empty on a creation endpoint. | Add Idempotency-Key: <uuid> to the request. |
IDEMPOTENCY_KEY_REUSED_DIFFERENT_BODY | 422 | Same key submitted with a different request body than the original. | Generate a new UUID for the new request. |
INVALID_DESTINATION | 400 | Payout/refund destination address format doesn't match the chain. | Verify the address is valid for the specified chain. |
MEMO_NOT_ALLOWED | 400 | destination_memo supplied for a chain that doesn't use memos (EVM, Tron, etc.). | Remove destination_memo; it’s only valid for TON/XRP/Stellar. |
UNAUTHORIZED | 401 | Missing, expired, or malformed API key. | Pass a valid Authorization: Bearer sspay_sec_test_demo_xxxxxxx header. |
MISSING_SCOPE | 403 | The API key exists but lacks the scope required by this endpoint (e.g. invoices.write). | Create a new API key in the cabinet with the required scope. |
FORBIDDEN | 403 | IP not in the key's allowlist, or resource belongs to a different merchant. | Check the key's IP allowlist in the cabinet. |
IP_RATE_LIMITED | 429 | Too many requests from this IP in the current window (public checkout only, 30 req/min). | Back off and retry. |
RATE_LIMITED | 429 | General rate limit hit. | Implement exponential backoff. |
NOT_FOUND | 404 | Generic not-found (route, resource). | Check the path and ID. |
INVOICE_NOT_FOUND | 404 | No invoice with that public ID for your merchant account. | Verify the invoice ID belongs to your account. |
PAYOUT_NOT_FOUND | 404 | No payout with that ID for your merchant account. | Verify the payout ID. |
REFUND_NOT_FOUND | 404 | No refund with that ID for your merchant account. | Verify the refund ID. |
WEBHOOK_NOT_FOUND | 404 | Webhook subscription not found. | Check the webhook ID in the cabinet. |
MERCHANT_NOT_FOUND | 404 | API key references a merchant that no longer exists. | Contact support. |
DUPLICATE | 409 | Duplicate order_id: another invoice already uses this identifier. | Use a unique order_id per invoice. |
INVOICE_NOT_CANCELLABLE | 409 | Invoice is not in awaiting_deposit state. | Only open invoices can be cancelled. |
INVOICE_NOT_REFUNDABLE | 409 | Invoice is not in a paid state, or has already been fully refunded. | Check the invoice status before requesting a refund. |
REFUND_EXCEEDS_NET | 400 | Requested refund amount exceeds the net amount available (paid minus previous refunds). | Reduce the refund amount. |
INSUFFICIENT_BALANCE | 400 | Payout amount exceeds your available balance for that asset. | Check your balance at GET /api/v1/merchant/balance. |
DAILY_CAP_EXCEEDED | 403 | Payout would exceed your 24-hour withdrawal cap for this asset. | Wait until the cap resets, or contact support to raise the limit. |
PAY_IN_ASSET_NOT_ALLOWED | 400 | The currency+chain combination isn't enabled for your merchant account. | Check the asset list in your merchant settings. |
ASSET_NOT_ALLOWED | 400 | Asset not supported for payout on this chain. | Use a supported asset/chain pair. |
CHAIN_DISABLED | 503 | This network is temporarily unavailable. | Try another chain, or retry later. |
POOL_EXHAUSTED | 503 | Temporarily unable to start a new payment. Retry shortly. | Retry after a short delay (seconds to minutes). |
PAYOUTS_DISABLED | 503 | Payouts are temporarily unavailable. | Check the status page or retry later. |
LOCK_UNAVAILABLE | 503 | The service is busy. Retry with exponential backoff. | Retry with exponential backoff. |
INTERNAL | 500 | Unexpected server error. | Retry once; if it persists, include request_id in a support ticket. |
CONFIG_MISSING | 500 | Temporary server-side configuration error. | Contact support with the request_id. |