Errors
Every error response follows the same structure, making it easy to handle errors consistently across all endpoints.
Error format
{
"successful": false,
"request_id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"error": {
"code": "ERROR_CODE",
"message": "Human-readable description",
"details": { ... }
}
}
| Field | Type | Description |
|---|---|---|
successful | bool | Always false |
request_id | string | Unique request ID — include this when contacting support |
error.code | string | Machine-readable error code for programmatic handling |
error.message | string | Human-readable description |
error.details | object | Additional context (optional, varies by error) |
Always use error.code (not HTTP status code) to determine the specific error.
Multiple different errors can share the same HTTP status code.
Authentication errors
These errors can occur on any endpoint.
| HTTP | Code | Description |
|---|---|---|
| 401 | API_KEY_MISSING | X-Api-Key header is missing or empty |
| 403 | API_KEY_INVALID | API key is invalid or deactivated |
| 403 | OWNER_BLOCKED | Merchant account owner is blocked |
| 403 | MERCHANT_BLOCKED | Merchant account is banned |
| 403 | MERCHANT_NOT_ACTIVE | Merchant account is not yet activated |
Invoice errors
Returned by POST /api/v1/create-invoice and GET /api/v1/invoice/{invoice_id}.
| HTTP | Code | Description |
|---|---|---|
| 409 | DUPLICATE_EXTERNAL_ID | Invoice with this external_id already exists |
| 409 | PENDING_INVOICE_EXISTS | Customer already has a pending invoice |
| 403 | CUSTOMER_RATE_LIMIT | Too many unpaid invoices for this customer |
| 422 | CURRENCY_INVALID | Currency code not found or disabled |
| 503 | NO_AVAILABLE_REQUISITES | No payment requisites available at the moment |
| 503 | DEALS_SYSTEM_DISABLED | Payment system is temporarily disabled |
| 404 | INVOICE_NOT_FOUND | Invoice with the specified ID was not found |
CUSTOMER_RATE_LIMIT details
When rate limited, the details object includes information to help you handle the situation:
{
"error": {
"code": "CUSTOMER_RATE_LIMIT",
"message": "Customer created too many unpaid invoices",
"details": {
"window_minutes": 60,
"limit": 5,
"next_allowed_at": "2026-02-26T15:30:00+00:00",
"customer_id": "user_12345"
}
}
}
Wait until next_allowed_at before creating a new invoice for this customer.
Currency errors
Returned by GET /api/v1/currencies.
| HTTP | Code | Description |
|---|---|---|
| 503 | RATES_UNAVAILABLE | Exchange rate service is temporarily unavailable |
| 503 | RATES_INVALID | Exchange rate data is corrupted |
| 404 | RATE_NOT_FOUND | No rates available for any currency |
| 422 | RATE_INVALID | Invalid rate for a specific currency |
Withdrawal errors
Returned by GET /api/v1/withdrawals and GET /api/v1/withdrawals/{withdraw_uuid}.
| HTTP | Code | Description |
|---|---|---|
| 404 | WITHDRAWALS_NOT_FOUND | No withdrawals found for this merchant |
| 404 | WITHDRAWAL_NOT_FOUND | Withdrawal with the specified UUID not found |
Validation errors
Returned when the request body fails schema validation (invalid JSON, missing required fields, wrong types).
HTTP status: 400
Error code: VALIDATION_ERROR
{
"successful": false,
"request_id": "...",
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request payload",
"details": [
{
"loc": ["body", "amount"],
"code": "value_error.missing",
"message": "field required"
},
{
"loc": ["body", "currency_code"],
"code": "string_pattern_mismatch",
"message": "String should match pattern '^[A-Z]{3}$'"
}
]
}
}
Details fields
| Field | Type | Description |
|---|---|---|
loc | array | Path to the invalid field, e.g. ["body", "amount"] |
code | string | Pydantic validation error type |
message | string | Human-readable validation message |
Server errors
These indicate a problem on our side. They are rare but should be handled gracefully.
| HTTP | Code | Description |
|---|---|---|
| 500 | INTERNAL_ERROR | Unexpected server error |
| 503 | DB_UNAVAILABLE | Database is temporarily unavailable |
INTERNAL_ERROR details
{
"error": {
"code": "INTERNAL_ERROR",
"message": "Something went wrong",
"error_id": "f8e2a1b3"
}
}
The error_id is a short identifier that helps our team locate the issue in logs. Include it when contacting support.
Error handling recommendations
Implement error handling based on error.code, not HTTP status codes. This gives you the most specific information about what went wrong.
503******** errors (NO_AVAILABLE_REQUISITES, RATES_UNAVAILABLE, DEALS_SYSTEM_DISABLED, DB_UNAVAILABLE) are temporary. Retry the request after a short delay (5–30 seconds).
400,422**** errors (VALIDATION_ERROR, CURRENCY_INVALID) indicate a problem with your request. Fix the payload and retry.
401,403**** errors (auth errors, rate limits) require configuration changes or waiting. Do not retry immediately.
500******** errors (INTERNAL_ERROR) are unexpected. Log the error_id and contact support if they persist.
Last updated today
Built with Documentation.AI