Errors
The TokenPay API returns a uniform error envelope for every non-2xx response. Parse the `error.code` field — not the message — to branch on failure type.
Error envelope
Every error response has this shape:
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "amount must be a positive decimal string"
}
}The envelope matches the ErrorResponse schema in the OpenAPI spec.
Code catalog
| Code | HTTP | When it fires |
|---|---|---|
| VALIDATION_ERROR | 400 | The request body or query string failed schema validation. The `message` field explains which field. |
| UNAUTHORIZED | 401 | The `Authorization` header is missing, malformed, or carries an invalid key. |
| API_KEY_EXPIRED | 401 | The presented API key has been rotated or revoked. Re-issue a new key from the dashboard. |
| FORBIDDEN | 403 | The key is valid but lacks scope for this route. Check the key's scope list. |
| IP_NOT_WHITELISTED | 403 | The request origin is not on the allowlist configured for this API key. |
| NOT_FOUND | 404 | No resource exists at the requested path, or you do not own the resource referenced in the URL. |
| CONFLICT | 409 | The requested state transition conflicts with the resource's current state (e.g. confirming an already-completed payment). |
| INSUFFICIENT_LIQUIDITY | 422 | No counterparty was available to match within the time window. Retry later or widen your fill parameters. |
| NOT_TH | 422 | Thailand-only route invoked for a non-TH merchant. Use a region-appropriate endpoint. |
| INTERNAL_ERROR | 500 | An unexpected server-side fault. Safe to retry idempotently; contact support if persistent. |
| INTERNAL | 500 | Reserved for catch-all faults where the failure category is not yet known. |
Retry behaviour
- 4xx — do not retry without changing the request. The failure is deterministic.
- 5xx — retry with exponential backoff. Use an idempotency key (see below) to prevent double-writes.
- 408 / 504 — treated as 5xx for retry purposes.
Idempotency
Every POST that creates a resource accepts an Idempotency-Key header (any unique string, max 64 chars). Replaying the request with the same key returns the original response rather than creating a duplicate resource. Keys are scoped per API key and retained for 24 hours.