Skip to main content

The envelope

Every non-2xx response has the same shape:
Three rules:
  1. error is a stable enum. Match on it in code. We never change a code without a major version bump.
  2. message is for humans. Show it in UIs. Wording may evolve; do not parse.
  3. trace_id is the support handshake. Quote it in any ticket — we resolve in one round trip.
Every response (success and error) also returns the trace id in the X-Exorde-Trace-Id header.

Authentication errors

Sample:

Authorisation errors

upgrade_required carries upgrade context so a UI can render a CTA without a second roundtrip:
topic_denied echoes which topics you do have:

Resource errors

Validation errors

Pydantic-style detail when validation_error:

Quota and rate-limit errors

rate_limited:
watchlist_limit_reached:
Full handling pattern: Rate limits.

Server-side errors

service_unavailable:

Subscription / webhook errors

Webhook delivery (server-to-you, not request errors): Verify the signature server-side before trusting the payload.

Common patterns

Match on error, not status

A 403 can be one of topic_denied, key_expired, key_revoked, upgrade_required, feature_disabled — all need different UX. Don’t hardcode “403 = upgrade prompt”; read error.

Always log trace_id

Distinguish “retry” from “act”

Encode this as a function:

Support handshake

When you email [email protected], include:
  1. The full error envelope (especially trace_id)
  2. The exact request URL and method
  3. Your client_id (from /v1/keys/current, not the api_key itself)
  4. Approximate UTC timestamp
We resolve from trace_id alone in most cases. The other fields are belt-and-braces.
Last reviewed: 2026-05-19. API version 1.2.8.