nora

Error handling

The HTTP status codes, error envelopes, and retry semantics you'll encounter when integrating with the Nora API.

Nora uses conventional HTTP status codes and returns JSON error bodies on every non-2xx response. Branch on status first, then on the appropriate error envelope for actionable details.

Status codes

StatusMeaningWhat to do
200 / 201SuccessParse body.
400Bad request — validation failure, malformed bodyFix the payload. On intents endpoints, validationErrors names each failing field.
401Missing or invalid credentialsRefresh your X-API-Key configuration. Do not retry.
403Authenticated but not authorized (e.g., your org's permissions don't cover this operation in this instance)Do not retry; the key's org/instance is fixed and the condition is resource-side.
404Resource does not existOften means wrong env — a sk_test_ key can't see sk_live_ data and vice versa.
409Conflict — state precondition failed (e.g., duplicate cpf on parties, or an idempotency-key reused with a different body on intents)Read the latest resource state and decide whether to proceed.
422Semantic validation — payload parsed but business rules rejected itInspect the error envelope for a machine-readable code / error.
429Rate limitedRespect Retry-After. See Rate limits.
5xxServer errorSafe to retry with backoff. Keep the same idempotency-key on intent creates so the retry is deduped.

Response envelopes

The /v2 API has two envelope shapes, split by resource family.

Parties family (/v2/parties/*)

{
  "error": "Human-readable message",
  "code": "optional_machine_code"
}
  • error is the required field. Human-readable; safe to log; prefer your own UX copy for end users.
  • code is optional — when present, it's a machine-readable hint for branching.

Intents family (/v2/intents/*)

{
  "code": "machine_readable",
  "message": "Human-readable message",
  "validationErrors": [
    { "field": "amountCents", "message": "must be > 0" }
  ],
  "details": { }
}
  • code and message are always present on non-2xx responses.
  • validationErrors is a structured array of { field, message } items on 400 responses driven by structural validation.
  • details is optional and endpoint-specific.

Do not assume a unified error shape across /v2. Parse by endpoint family: if your HTTP client reached a /v2/intents/* URL, expect code + message; if it reached /v2/parties/*, expect error (and optionally code).

Branching on the error body

On parties endpoints, inspect response.error for display and optionally response.code to differentiate failure modes. On intents endpoints, inspect response.code for branching and response.validationErrors for per-field messages.

Machine-readable code values are not enumerated in the public OpenAPI spec. Common codes you may observe include validation failures (validation_failed or similar) and idempotency conflicts (idempotency_key_conflict or similar), but the full taxonomy is not part of the public contract. Branch on HTTP status first; use code / error for finer-grained UX only when it surfaces a specific failure you want to special-case.

Retry semantics

Not every error is retry-safe:

  • Safe to retry with the same idempotency key (intents creates only): 5xx, transport failures, connection resets. The server replays the original response.
  • Safe to retry with a new idempotency key: time-sensitive rebuilds — burn signing, where a stale-blockhash failure means you fetch a fresh payload, re-sign, and the new txSignature itself becomes the dedup key.
  • Do not retry, fix first: 400, 401, 403, 422.
  • Read first, then decide: 404, 409. These often mean the state you're acting on has moved — fetching the latest resource tells you what to do next.

Gotchas

  • 401 is not a "try again" signal. The credential itself is the problem; no retry will fix it. Check the X-API-Key value and whether it matches the environment you're calling.
  • 422 vs 400. 400 means the request was malformed (bad JSON, missing required field). 422 means the request parsed correctly but the business logic rejected it. On intents endpoints, branch on code; on parties endpoints, on code if present or error text.
  • Error bodies are NOT Nora's typed happy-path shape. If you only care about the typed response for 2xx, you still need a fallback path for errors — the envelope is separate and varies by family.
  • Don't consume the response body twice. If your HTTP client auto- parses non-ok responses, don't re-read the stream.

See also

On this page