Errors & Rate Limits

Error envelope, HTTP status codes, error codes by category, rate-limit headers, and retry guidance.

Errors

Error Envelope

REST endpoints return errors in a consistent format with a code, message, and optional hint, wrapped in a detail object. MCP tools use a different envelope — see below.

{ "detail": { "code": "DOCUMENT_FORMAT_UNSUPPORTED", "message": "The uploaded file format is not supported.", "hint": "Supported formats: PDF, DOCX, XLSX, TXT, CSV, JSON, HTML, MD" } }
FieldTypeDescription
codestringMachine-readable error code (e.g., DOCUMENT_FORMAT_UNSUPPORTED)
messagestringHuman-readable error description
hintstring?Optional hint for resolving the error

MCP Tool Errors

Tools called over MCP (for example connector_execute) don't carry HTTP status codes. They return a structured envelope with a retryable flag in place of hint:

{ "code": "SERVICE_RATE_LIMITED", "message": "Upstream service is rate limiting requests.", "retryable": true }

When retryable is true, the call may be retried after a short backoff; when false, retrying with the same arguments will fail again.

HTTP Status Codes

CodeDescription
200Success
201Created — resource successfully created
204No Content — successful deletion
400Bad Request — invalid parameters or body
401Unauthorized — missing or invalid token
403Forbidden — token lacks required scope
404Not Found — resource does not exist
409Conflict — resource already exists (idempotency)
422Unprocessable Entity — validation error
429Too Many Requests — rate limit exceeded
500Internal Server Error
504Gateway Timeout — request took too long

Error Codes by Category

Common error codes grouped by category. The complete, always-current set is browsable in the interactive API explorer.

CategoryCodes
AuthenticationAUTH_TOKEN_EXPIRED AUTH_TOKEN_INVALID AUTH_HEADER_MISSING AUTH_PERMISSION_DENIED AUTH_SCOPE_MISSING
DocumentsDOCUMENT_FORMAT_UNSUPPORTED DOCUMENT_SIZE_EXCEEDED DOCUMENT_PASSWORD_PROTECTED DOCUMENT_OCR_FAILED DOCUMENT_NOT_FOUND
LLMLLM_PROVIDER_UNAVAILABLE LLM_REQUEST_TIMEOUT LLM_PROVIDER_ERROR LLM_RATE_LIMITED
ToolsTOOL_VALIDATION_FAILED TOOL_NOT_FOUND TOOL_TIMEOUT TOOL_EXECUTION_FAILED
DataDATA_NOT_FOUND DATA_CONFLICT DATA_INVALID_PARAMETER DATA_QUOTA_EXCEEDED
ServiceSERVICE_UNAVAILABLE SERVICE_RATE_LIMITED SERVICE_CONNECTION_LOST SERVICE_CIRCUIT_OPEN

Error Handling Example

Recommended approach to handling API errors in Python.

import requests response = requests.post(url, headers=headers, json=body) if response.status_code >= 400: error = response.json().get("detail", {}) code = error.get("code", "UNKNOWN") message = error.get("message", "An error occurred") hint = error.get("hint") if response.status_code == 429: # Rate limited — retry after delay retry_after = response.headers.get("Retry-After", "60") print(f"Rate limited. Retry after {retry_after}s") elif response.status_code == 401: # Authentication error print(f"Auth error: {message}") else: print(f"Error [{code}]: {message}") if hint: print(f"Hint: {hint}")

Rate Limits

Rate Limit Headers

Every API response includes headers with current rate limit information.

HTTP/1.1 200 OK X-RateLimit-Limit: 60 X-RateLimit-Remaining: 58 X-RateLimit-Reset: 1711540800
HeaderDescription
X-RateLimit-LimitMaximum number of requests in the window
X-RateLimit-RemainingNumber of requests remaining
X-RateLimit-ResetUnix timestamp when the rate limit window resets
Retry-AfterSeconds to wait before retrying (only on 429)

Plan-Based Limits

Per-minute request limits depend on your subscription plan and are shared across the organization.

PlanRequests
Free10 req/min
Pro30 req/min
Max60 req/min

Only the per-minute limit is currently enforced.

Rate Limit Exceeded Response

When the rate limit is exceeded, the API returns a 429 status with retry timing information.

{ "detail": { "code": "SERVICE_RATE_LIMITED", "message": "Rate limit exceeded. Please retry after the reset time.", "hint": "Check X-RateLimit-Reset header for the reset timestamp." } }

Retry Logic

Implement exponential backoff when receiving 429 responses.

import time import requests def request_with_retry(url, headers, max_retries=3): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.status_code == 429: retry_after = int(response.headers.get("Retry-After", "60")) print(f"Rate limited. Retrying in {retry_after}s...") time.sleep(retry_after) continue return response raise Exception("Max retries exceeded")

Best Practices

  • Cache responses that don't change often (e.g., model list)
  • Use exponential backoff for retries
  • Monitor X-RateLimit-Remaining headers to anticipate limit exhaustion
  • For bulk operations, use batch endpoints instead of multiple individual requests
Was this page helpful?