Errors
Every error response is an RFC 7807 problem document. The HTTP status tells you the broad category; the body tells you exactly what happened.
The shape
{ "type": "https://errors.paylera.io/payments/requires_action", "title": "Payment requires customer action", "status": 200, "detail": "The payment method requires 3DS authentication.", "instance": "/v1/invoices/inv_…/pay", "problem": "payment.requires_action", "trace_id": "01H8MZP…", "errors": [ … ], "next_action": { … }}| Field | Meaning |
|---|---|
type | A stable URL identifying the problem class. May be dereferenced for documentation. |
title | A short human-readable summary. |
status | The HTTP status code. |
detail | A human-readable explanation specific to this occurrence. May vary across calls. |
instance | The URL path of the request. |
problem | A stable string discriminator your code branches on. Use this, not type or title. |
trace_id | The request’s trace ID. Include in support tickets. |
errors | Optional array of field-level validation errors. |
next_action | Optional structured payload pointing at the resolution (used by some 200 responses, not just errors). |
Status codes
| Code | When |
|---|---|
| 200 | Success. May still carry a structured next_action (e.g., requires_action). |
| 201 | Resource created. |
| 202 | Accepted; will complete asynchronously. |
| 204 | Success, no body. |
| 400 | Malformed request. |
| 401 | Authentication failed. |
| 403 | Authenticated, but not allowed (scope, AAL, ownership). |
| 404 | Resource doesn’t exist (or isn’t visible to your tenant). |
| 409 | Conflict — usually a state-machine violation. |
| 410 | Gone — resource existed but was permanently removed. |
| 422 | Validation failed. See errors[]. |
| 429 | Rate limited. See Retry-After. |
| 500 | An unexpected error on our side. |
| 503 | Temporary unavailability — typically a downstream provider. |
Branch on problem, not status
status tells you broadly. problem tells you exactly. Two 422s with
different problems mean different things:
{ "status": 422, "problem": "subscription.commitment_active" }{ "status": 422, "problem": "subscription.proration_invalid_currency" }Use problem in switch statements; use status for fallback / metric
labels.
Field-level errors
For 422s with multiple invalid inputs:
{ "status": 422, "problem": "validation.failed", "errors": [ { "field": "billing_address.country", "code": "country.invalid", "message": "Must be ISO-3166 alpha-2." }, { "field": "name", "code": "required", "message": "Required." } ]}Render message to the user; key off code for client-side handling
(showing inline validation, focus management).
Idempotent replays
Replays of an idempotent request return the original response verbatim — including 4xx errors. If your first call returned a 422, the retry returns the same 422. If you want a different outcome, send a new idempotency key.
Trace IDs
Every response includes trace_id. Include it when you contact
support; we can pull the request’s full trace from observability with
that single ID.
Common errors by category
problem | When |
|---|---|
auth.* | Authentication failures. See Authentication. |
idempotency.required | A money-moving / resource-creating route was called without Idempotency-Key. |
idempotency.body_mismatch | The same key was sent with a different body. |
validation.failed | One or more fields invalid. See errors[]. |
subscription.* | FSM transition not allowed; see Status reference. |
invoice.locked | Mutation attempted on a non-draft invoice. |
payment.requires_action | 3DS / SCA needed. See next_action. |
payment.declined | Provider declined the charge; see last_error. |
wallet.insufficient_funds | Wallet balance below requested amount. |
fx.stale_rate | FX rate older than the staleness threshold. |
tax.engine_unavailable | Tax engine returned an error; finalisation rolled back. |
rate_limit.exceeded | Too many requests; back off per Retry-After. |
The full list lives in the Error code reference.
What you should log
For every error response your client sees:
- HTTP status
problemtrace_id- The endpoint and method
This combination is searchable end-to-end. Body payloads may contain PII; redact before logging.