Browse documentation

Reference

Errors

How the API signals failure: HTTP status codes on REST, an errors array on GraphQL, and RFC error bodies on OAuth.

View as Markdown

Payer uses conventional HTTP status codes and returns a JSON body describing what went wrong. The exact shape depends on the surface you're calling.

REST status codes

The Checkout API and other REST endpoints return these:

StatusMeaningTypical cause
200OKThe request succeeded.
400Bad requestAn action isn't valid for the resource's state — e.g. cancelling a paid session.
401UnauthorizedMissing, malformed or unknown token.
403ForbiddenThe token lacks the required scope, or a PAT sent an X-Active-Merchant header.
404Not foundNo resource with that id for this account.
409ConflictAn Idempotency-Key is still in flight, or was reused mid-request.
422UnprocessableA field failed validation, or an Idempotency-Key was reused with a different body.
429Too many requestsThe credential's per-minute rate limit was exceeded.

A simple error carries a message:

403 Forbidden
{
  "message": "Forbidden",
  "error": "This credential does not have the required scope: checkout:write"
}

Validation errors

Field validation failures return 422 with a Laravel-style errors map — one array of messages per offending field:

422 Unprocessable
{
  "message": "The amount field is required. (and 1 more error)",
  "errors": {
    "amount": ["The amount field is required."],
    "reference": ["The reference has already been taken."]
  }
}

GraphQL errors

GraphQL always responds 200 at the HTTP layer. Failures appear in a top-level errors array, and the affected field in data is null:

GraphQL error
{
  "data": { "balance": null },
  "errors": [
    {
      "message": "This credential does not have the required scope: balances:read",
      "extensions": { "category": "authorization" }
    }
  ]
}

OAuth errors

The OAuth token and revoke endpoints follow RFC 6749 — a machine-readable error with a human error_description:

OAuth error
{
  "error": "invalid_grant",
  "error_description": "The authorization code is invalid or has expired."
}

Handling errors well

  • Retry writes with the same `Idempotency-Key`. A 5xx or a network blip is safe to retry — the original response is replayed, not repeated. See Idempotency.
  • Back off on `429`. Limits are per credential; spread load or split work across keys rather than hammering one.
  • Read `errors`, not just the field. On GraphQL a partial response can carry both data and errors.