Errors
HTTP status codes and the error body format.
Body shape
API errors use a JSON message. Some responses also include a
stable machine-readable code:
{
"message": "human-readable explanation",
"code": "submission_not_started"
}The message is intended for logging and developer tooling, not for
end-user display. Clients may branch on code when it is present and must
tolerate it being absent. Network and server failures can use a
different body; clients should classify them by HTTP status.
Status codes
| Status | Meaning | Typical cause |
|---|---|---|
200 | Success. | Operation accepted; check the body for status. |
400 Bad Request | The request was malformed. | Invalid JSON; a required field is missing; a UUID field is not a strict, canonically-formatted UUID; an amount fails to parse. |
401 Unauthorized | API key missing or invalid. | X-API-Key header absent, or the value is not a known key. |
403 Forbidden | API key scope mismatch. | The request tries to act outside the shop the X-API-Key resolves to. |
404 Not Found | The referenced entity does not exist (or belongs to a different shop). | Unknown operation_id on confirm/state endpoints. Cross-shop lookups deliberately return 404 rather than leaking existence. |
409 Conflict | Another request currently owns the same state transition. | A receipt revision is already being finalized; retry the same idempotent request with backoff. |
412 Precondition Failed | The operation is not eligible for the action, or an idempotency key conflicts with the operation parameters. | Replacing a receipt before its review permits it; re-using merchant_operation_id with a different type, method, currency, amount, client, or payout destination. |
415 Unsupported Media Type | The uploaded receipt media type is not accepted. | Receipt is not PDF, JPEG, PNG, GIF, or WebP. |
429 Too Many Requests | A request or capacity limit was reached. | Wait for Retry-After when provided; otherwise retry with backoff. |
500 Internal Server Error | Unexpected server-side failure. | Generic sanitized catch-all; inspect/reconcile state before retrying a non-idempotent action. |
503 Service Unavailable | The service is temporarily unavailable or timed out. | Retry an idempotent request with backoff. |
For payout create, code=submission_not_started may accompany 404 Not Found
or 412 Precondition Failed only when the server proves that operation
submission never began. Other 404 and 412 responses omit this code.
An idempotency conflict returns 412, not 409.
A client-side request cancellation can return
400 Bad Request with "request canceled", not 5xx.
“Retryable transport error” does not make an arbitrary business action safe to
repeat. Create endpoints are protected by (shop, merchant_operation_id);
state reads are naturally safe. For confirmation or another state-changing
request, first determine whether the server accepted the previous request and
reuse the same operation identity.
What is NOT an error
A successful HTTP response (200) does not mean the operation is
completed. The operation may still be pending and reach a final
status later — see Status lifecycle.
The same applies to /v1/confirm_payment: a 200 only means the confirmation
request was accepted. Public confirmation always uses
confirmation_type=receipt, so a 200 means the gateway uploaded the receipt
and attached it to the operation for validation/review. A clean validation may
complete the payment automatically; suspicious, wrong-amount, or unavailable
validation moves an in-flight payment to manual_check for review. While
validation runs, its status is pending_confirmation. See
repeated and late uploads
for retries and receipts submitted after a terminal outcome.