Errors

Every error response uses a single envelope with a stable machine-readable code and a request id for support.

The error envelope

Error response
{
  "error": {
    "code": "not_found",
    "message": "The requested resource was not found.",
    "type": "not_found",
    "request_id": "9f2b4c1a-8e6d-4a3b-9c1f-7d2e5a8b3c4d"
  }
}
error.codestring

Stable, machine-readable error code. Branch on this, not on the message.

error.messagestring

Human-readable description of what went wrong.

error.typestring

High-level category such as authentication, validation, or not_found.

error.request_idstring

Correlates the error with server logs. Include it when contacting support.

Validation errors

422 responses additionally carry per-field messages under error.fields, keyed by field name:

422 Unprocessable Entity
{
  "error": {
    "code": "validation_failed",
    "message": "The given data was invalid.",
    "type": "validation",
    "request_id": "9f2b4c1a-8e6d-4a3b-9c1f-7d2e5a8b3c4d",
    "fields": {
      "schema_id": ["The schema id field is required."],
      "filename": ["The filename must not be greater than 255 characters."]
    }
  }
}

Status codes

StatusMeaning
401Missing, malformed, or revoked API key.
404Resource not found — including runs that belong to a different organization.
409The request conflicts with the run state, e.g. approving a review before it is ready.
422Validation failed. Check error.fields for details.
429Rate limit exceeded. Back off and retry.
500Unexpected server error. Retry with backoff; report the request_id if it persists.

Run-level failures

A request can succeed while the transformation itself later fails (for example, the AI provider rejects the call). Those failures don't surface as HTTP errors — they appear on the run as status: "failed" with an error object containing code, message, stage, and a retryable flag.

Failed transformation run
{
  "id": "9b2e1f6c-8e6d-4a3b-9c1f-7d2e5a8b3c4d",
  "status": "failed",
  "terminal": true,
  "stage": "review",
  "error": {
    "code": "provider_rate_limited",
    "message": "The configured provider rate limit was exceeded.",
    "stage": "review",
    "retryable": true
  },
  "download_url": null
}
When error.retryable is true, refreshing the review or re-creating the run with the same input is likely to succeed.