The ODEN API uses standard HTTP status codes. A non-2xx response indicates that the request was not completed; the JSON response body contains diagnostic details.
Status codes catalog#
| HTTP Code | Error Code | Description | Corrective Action |
|---|---|---|---|
200 | ok | Success. Synthesized answer and citations populated. | Consume results. |
400 | invalid_request | Malformed JSON body, missing query, or query length over 500 characters. | Validate JSON syntax and check query length. |
401 | unauthorized | Bearer token missing, expired, or invalid. | Check Authorization: Bearer <key> header. |
403 | quota_exceeded | Monthly account search allocation exhausted. | Upgrade plan or purchase a top-up pack in dashboard. |
404 | not_found | Endpoint URL does not exist. | Ensure request is dispatched to POST /search. |
422 | unprocessable_entity | Semantic parsing failed on search parameters. | Inspect request payload types (e.g., depth, answer). |
429 | rate_limit_exceeded | Per-minute burst limit or concurrency cap reached. | Apply exponential backoff with jitter. |
500 | internal_error | Unexpected backend server error. | Retry with backoff. Report with trace_id if persistent. |
502 / 503 | gateway_error | Transient Cloudflare edge network or routing blip. | Retry automatically after short backoff. |
Error response shape#
When an error occurs, the endpoint responds with application/json containing a structured payload:
{
"error": "invalid_request",
"message": "query must be 500 characters or fewer",
"trace_id": "oden-mquycpae-p3thrk"
}
error— Machine-readable classification string.message— Human-readable description explaining the exact failure reason.trace_id— Unique distributed trace identifier. Always quote this string when submitting support requests.
Permanent vs transient errors#
Build robust client logic by distinguishing between permanent (client-side) and transient (server-side/network) errors:
- Permanent errors (400, 401, 403, 404, 422): Deterministic failures that will not succeed on retry. Immediately fail the calling pipeline, log the error, and notify the developer.
- Transient errors (429, 500, 502, 503, 504): Temporary conditions that typically resolve within seconds. Safe to retry using exponential backoff with jitter.
Production error handler#
Implement a clean Python exception handler that parses ODEN errors and handles retries conditionally:
import time, requests, logging
logger = logging.getLogger("oden_client")
class OdenApiError(Exception):
def __init__(self, status_code: int, error_code: str, message: str, trace_id: str):
self.status_code = status_code
self.error_code = error_code
self.trace_id = trace_id
super().__init__(f"ODEN [{status_code} - {error_code}] {message} (trace: {trace_id})")
def execute_search(url: str, headers: dict, payload: dict, max_retries: int = 3) -> dict:
for attempt in range(max_retries + 1):
resp = requests.post(url, headers=headers, json=payload, timeout=25)
if resp.ok:
return resp.json()
err_data = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
err_code = err_data.get("error", "unknown_error")
err_msg = err_data.get("message", resp.text)
trace_id = err_data.get("trace_id", resp.headers.get("x-trace-id", "unknown"))
# 1. Fatal client errors: abort immediately
if resp.status_code in (400, 401, 403, 404, 422):
logger.error(f"Fatal ODEN error {resp.status_code}: {err_msg} | trace: {trace_id}")
raise OdenApiError(resp.status_code, err_code, err_msg, trace_id)
# 2. Transient errors: backoff and retry
if resp.status_code in (429, 500, 502, 503):
if attempt == max_retries:
raise OdenApiError(resp.status_code, err_code, err_msg, trace_id)
sleep_sec = (2 ** attempt) + 0.5
logger.warning(f"ODEN transient error {resp.status_code}. Retrying in {sleep_sec}s... | trace: {trace_id}")
time.sleep(sleep_sec)
raise RuntimeError("Unexpected retry termination")
Observability & telemetry integration#
To maintain high visibility across production services:
- Correlate logs: Pass the returned
trace_idinto your OpenTelemetry spans, Datadog traces, or Sentry error events. - Alert on 401 and 403: Set up monitoring alerts for sudden spikes in 401 (auth failure) or 403 (quota depletion) so keys or billing can be addressed before users are impacted.
Next steps#
- Rate limits — the detail behind
429. - Authentication — the detail behind
401.