# Error Handling

> API error formats, stable query codes, and recovery guidance


import { CodeBlock } from "@/components/docs";

Every API response includes an `X-Request-ID` header so support can trace a failure without exposing internal details. Query API and direct route errors also include that value as `requestId` in their JSON body. Framework-generated RPC errors may expose it only in the header.

## Error response

<CodeBlock
  language="json"
  code={`{
  "success": false,
  "error": "Human-readable error message",
  "code": "ERROR_CODE",
  "requestId": "req_abc123def456"
}`}
/>

Some validation failures also include `details` with the affected field and a suggested correction:

<CodeBlock
  language="json"
  code={`{
  "success": false,
  "error": "Unknown query type: summary. Did you mean 'summary_metrics'?",
  "code": "VALIDATION_ERROR",
  "requestId": "req_abc123def456",
  "details": [
    {
      "field": "parameters[0]",
      "message": "Unknown query type: summary",
      "suggestion": "Did you mean 'summary_metrics'?"
    }
  ]
}`}
/>

## Query API codes

These are the stable codes returned by `/v1/query` and its subroutes:

| Code | HTTP status | Meaning | Recovery |
|------|-------------|---------|----------|
| `AUTH_REQUIRED` | 401 | The protected operation has no valid API key or session | Add authentication and retry |
| `ACCESS_DENIED` | 403 | Authentication succeeded but cannot access the requested resource | Check the key's organization, resource access, and scopes |
| `MISSING_PROJECT_ID` | 400 | No website, link, monitor, or organization identifier was supplied | Add the identifier required by the query type |
| `VALIDATION_ERROR` | 400 | The body, date range, filter, or query type is invalid | Correct the reported fields and retry |
| `COMPILATION_ERROR` | 400 | The query could not be compiled | Correct the query definition |
| `FEATURE_UNAVAILABLE` | 402 | The selected plan does not include the requested query capability | Change plan or remove that query type |
| `RATE_LIMITED` | 429 | The request limit was reached | Wait for `Retry-After`, then retry |
| `INTERNAL_SERVER_ERROR` | 500 | An unexpected server error occurred | Retry; if it continues, contact support with the request ID |
| `SERVICE_UNAVAILABLE` | 503 | API key admission infrastructure is temporarily unavailable | Wait for `Retry-After` (5 seconds), then retry |

Other API families can define additional codes. Treat `code` as the programmatic value and keep a fallback for unfamiliar codes.

## Authentication response

Protected endpoints return a JSON error when the API key is missing or invalid:

<CodeBlock
  language="http"
  code={`HTTP/1.1 401 Unauthorized
X-Request-ID: req_abc123def456
WWW-Authenticate: Bearer realm="databuddy"`}
/>

## Rate-limit response

<CodeBlock
  language="json"
  code={`{
  "success": false,
  "error": "Rate limit exceeded",
  "code": "RATE_LIMITED",
  "requestId": "req_abc123def456",
  "limit": 120,
  "remaining": 0,
  "reset": 1735732810000,
  "retryAfter": 8
}`}
/>

`reset` is a Unix timestamp in milliseconds. `retryAfter` and the `Retry-After` header are seconds.

## Partial query results

A valid multi-parameter query can contain a failure for one parameter while other parameters succeed:

<CodeBlock
  language="json"
  code={`{
  "success": true,
  "requestId": "req_abc123def456",
  "data": [
    { "parameter": "summary_metrics", "success": true, "data": [] },
    {
      "parameter": "top_pages",
      "success": false,
      "error": "Query execution failed",
      "data": []
    }
  ]
}`}
/>

Check both the top-level `success` value and each result's `success` value.

## Recovery checklist

1. Record `code`, HTTP status, and `requestId`.
2. For `401` and `403`, verify authentication, scopes, organization, and resource access.
3. For `400`, correct the documented field instead of retrying unchanged.
4. For `429`, wait for `Retry-After`; add jitter when many workers share a key.
5. For `5xx`, retry with bounded exponential backoff. Contact support with the request ID if the failure continues.
