nspay

Errors

HTTP status codes and the error body format.

Body shape

Every error response uses a single, stable shape:

{
  "message": "human-readable explanation"
}

The message is intended for logging and developer tooling, not for end-user display.

Status codes

StatusMeaningTypical cause
200Success.Operation accepted; check the body for status.
400 Bad RequestThe 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 UnauthorizedAPI key missing or invalid.X-API-Key header absent in strict mode, or the value is not a known key.
403 ForbiddenAPI key scope mismatch.The request tries to act outside the shop the X-API-Key resolves to.
404 Not FoundThe 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.
412 Precondition FailedThe operation is not in a state that allows the action, or merchant_operation_id collides with a different body.Confirming an operation that is already terminal or does not require external confirmation; re-using a merchant_operation_id with a different request body.
415 Unsupported Media TypeThe uploaded receipt media type is not accepted.Receipt is not PDF, JPEG, PNG, GIF, or WebP.
429 Too Many RequestsA downstream resource limit is currently exhausted.gRPC ResourceExhausted; retry with backoff.
500 Internal Server ErrorUnexpected server-side failure.Generic sanitized catch-all; inspect/reconcile state before retrying a non-idempotent action.
503 Service UnavailableA required downstream service timed out or is unavailable.gRPC Unavailable or DeadlineExceeded; retry an idempotent request with backoff.

Idempotency collisions on merchant_operation_id (same id reused with a different body) surface as 412 Precondition Failed with a message describing the conflict — the dispatcher's idempotency check is mapped from gRPC AlreadyExists to 412, not 409.

A client-side cancellation (the HTTP request context being cancelled before the gateway finishes the gRPC call) is surfaced as 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 leaves it pending for an operator. Upload failures return an error and the operation stays pending.

On this page