Errors

Structured. Predictable. Useful.

Every error has a stable type, a human message, a request ID, and a link back here. What we never do: hide behind 500s, return HTML, or count failed upstream calls against your quota.

The envelope

Gateway-originated errors (auth, quota, upstream failure) all use this shape. Errors that originate upstream are forwarded with their original body untouched.

{
  "error": {
    "type": "quota_exceeded",
    "message": "Monthly request limit reached. Upgrade your plan or wait until 2026-06-01.",
    "request_id": "req_2y4Zp7H8...",
    "docs_url": "https://souslab.site/docs/errors#quota_exceeded"
  }
}
200 OK · 38 ms

Status codes

StatusTypeMeaningCounts toward quota?
400bad_requestMalformed query or path. Fix your call.Yes
401unauthenticatedMissing or malformed Authorization header.No
403key_revokedThe API key was revoked.No
429quota_exceededYou hit the monthly cap. Reset is in the response body.No
502upstream_errorUpstream returned 5xx. We forwarded it; not your fault.No
503upstream_timeoutUpstream took >30s. Retry with backoff.No

When to retry

  • 429: wait until X-RateLimit-Reset. Don't hammer. Consider upgrading.
  • 502 / 503: exponential backoff. The failed call did not count against your quota.
  • 4xx (other): fix the request. Retrying won't help.
  • 5xx from us: safe to retry once. If it persists, ping hello@souslab.site with the X-Request-Id.