Errors
Error response shape and common merchant API codes.
All merchant API errors use the same JSON shape:
{
"error": {
"code": "INVALID_AMOUNT",
"message": "Human-readable message"
}
}Use error.code for programmatic handling. message is for logs and debugging.
HTTP status
| Status | Typical meaning |
|---|---|
400 | Validation / bad request |
401 | Missing or invalid API key |
403 | Not allowed (e.g. live not approved) |
404 | Resource not found |
409 | Conflict (e.g. idempotency mismatch) |
429 | API key rate limit exceeded |
500 | Unexpected server error |
Common codes
Auth
| Code | Status | When |
|---|---|---|
UNAUTHORIZED | 401 | Missing Bearer / session |
INVALID_API_KEY | 401 | Invalid or revoked API key |
RATE_LIMITED | 429 | API key over 100 requests/minute |
Invoices
| Code | Status | When |
|---|---|---|
INVALID_AMOUNT | 400 | Amount not a positive decimal string (max 6 decimal places) |
INVALID_METADATA | 400 | Metadata is not a JSON object |
INVALID_NETWORK | 400 | networkId missing/invalid or unknown |
INVALID_TOKEN | 400 | token not USDC or USDT |
NETWORK_NOT_ENABLED | 400 | Network exists but not enabled for this merchant/environment |
TOKEN_NOT_SUPPORTED_ON_NETWORK | 400 | Token not enabled on the requested network |
NO_AVAILABLE_PAYMENT_METHOD | 400 | Constraints leave no valid chain/token |
ENVIRONMENT_NOT_ALLOWED | 400 | API key request included environment (omit it) |
INVALID_ENVIRONMENT | 400 | Session body environment not test or live |
IDEMPOTENCY_KEY_REQUIRED | 400 | Missing Idempotency-Key on create |
INVALID_IDEMPOTENCY_KEY | 400 | Key longer than 255 characters |
IDEMPOTENCY_CONFLICT | 409 | Same key, different body |
LIVE_NOT_APPROVED | 403 | Live invoice / live key before go-live approval |
MERCHANT_SUSPENDED | 403 | Merchant account is suspended |
NO_ENABLED_CHAINS | 400 | No networks enabled for that environment |
CHAIN_NOT_CONFIGURED | 400 | Vault/RPC not ready for enabled chains |
INVOICE_NOT_FOUND | 404 | Unknown or other-merchant invoice |
MERCHANT_NOT_FOUND | 404 | Merchant profile missing |
Webhooks
| Code | Status | When |
|---|---|---|
INVALID_ENVIRONMENT | 400 | Env missing/mismatched |
INVALID_WEBHOOK_URL | 400 | Bad URL or live URL not public HTTPS |
INVALID_WEBHOOK_SECRET | 400 | Secret length out of range |
WEBHOOK_SECRET_REQUIRED | 400 | First create without secret |
INVALID_CUSTOM_HEADERS | 400 | Bad headers / reserved names |
WEBHOOK_NOT_CONFIGURED | 404 | No endpoint for that environment |
DELIVERY_NOT_FOUND | 404 | Unknown delivery id |
Idempotency reminder
POST /v1/invoices requires Idempotency-Key.
- Same merchant + key + same body → original invoice (HTTP 200)
- Same key + different body →
IDEMPOTENCY_CONFLICT(409)
Generate a fresh key per distinct create attempt (UUID is fine).
Rate limits
Phase 1 default: 100 requests/minute per API key. Treat 429 as retry-with-backoff if you encounter it.