Skip to main content
Every error response from the Overten API follows a consistent JSON shape. The HTTP status code tells you the broad category of the problem, the error field gives you the exact machine-readable reason, and message is a human-readable string that is safe to surface directly to your end users — it never contains stack traces or internal implementation details.
{
  "success": false,
  "error": "<error_code>",
  "message": "<human_readable>"
}

HTTP status codes

The table below maps every status code the API returns to its category and the most common scenario that triggers it.
CodeCategoryTypical scenario
200SuccessSync result returned
201Resource createdFile uploaded, key minted, webhook subscribed
202Accepted (async)Task queued; poll /tasks/{id}
204No contentImage, key, or webhook deleted
302RedirectGET /runs/{id}/download
400Bad requestValidation or preflight error
401UnauthorizedBad or missing API key
402Payment requiredOut of credits
403ForbiddenKey valid but not permitted
404Not foundRun, file, or image doesn’t exist or belongs to another org
408TimeoutSync ceiling exceeded; response body tells you to retry async
409ConflictIdempotency key collision or invalid resource state
410GoneResource existed but was deleted or expired
413Payload too largeUpload exceeds tier limit
422ValidationField-level rejection on the request body
429Rate limitedSee the Retry-After header
500Server errorUnhandled exception on our side — gets paged automatically
501Not implementedEndpoint exists but the feature isn’t live yet
502Upstream errorA dependency (model provider, storage, or rendering pipeline) failed
503Service unavailableCapacity exhausted or scheduled maintenance

Error codes

Authentication

CodeWhen it occursHow to fix it
invalid_api_keyMissing, malformed, or revoked sk_live_* keyCheck your Authorization header; rotate the key if it may be compromised
forbiddenKey is valid but lacks permission — suspended org or wrong tierCheck org status via GET /verify

Billing

CodeWhen it occursHow to fix it
insufficient_creditsOrg balance is below the minimum required for the requested formatTop up via the dashboard or contact sales

Validation

CodeWhen it occursHow to fix it
invalid_requestMissing required field or bad enum valueFix the payload according to the error message
validation_errorField-level rejection on the request bodyThe message contains a JSON pointer to the exact failing field
preflight_failedLLM validator rejected the request due to missing assetsAttach the missing assets or rephrase the prompt
payload_too_largeUploaded file exceeds the tier limitCompress the file or upgrade your tier

Resources

CodeWhen it occursHow to fix it
not_foundRun, file, image, or webhook ID doesn’t exist or belongs to another orgCheck the ID spelling; confirm it was created under the same org
goneResource existed but passed the 30-day retention windowStart a new run
conflictIdempotency key reused with a different request body, or resource is in an invalid stateUse a different idempotency key, or wait for the resource to reach a terminal state

Runtime

CodeWhen it occursHow to fix it
sync_timeout_upgrade_asyncSync request hit the 300-second ceilingResubmit with async: true and poll /tasks/{id}
rate_limit_exceededExceeded the per-key, per-minute limit for your tierRetry after the number of seconds in the Retry-After header
internal_errorUnhandled server exceptionInclude the X-Request-Id header value in your support ticket
upstream_errorLLM provider, storage, or rendering pipeline outageRetry with exponential backoff
service_unavailableWorker pool saturated or scheduled maintenance windowRetry after 30–60 seconds
not_implementedEndpoint exists for shape compatibility but the feature isn’t available on your tier or deploymentContact support@overten.ai

Handling errors in code

Use the error field to branch your error-handling logic. Treat 5xx responses as transient and retry with exponential backoff. Treat 4xx responses (other than 408 and 429) as permanent — retrying without changing the request will not help.
import time
import requests

resp = requests.post(f"{API}/excel/generate", headers=headers, json=body)
if not resp.ok:
    err = resp.json()
    code = err.get("error", "unknown")
    msg = err.get("message", "")

    if code == "preflight_failed":
        # Fix the prompt or attach the missing assets before retrying
        print(f"Rejected: {msg}")
    elif code == "insufficient_credits":
        # Surface a billing prompt to the user
        redirect_to_billing()
    elif code == "rate_limit_exceeded":
        # Honor the Retry-After header
        retry_after = int(resp.headers.get("Retry-After", "30"))
        time.sleep(retry_after)
        # then retry the request
    elif resp.status_code >= 500:
        # Transient — retry with exponential backoff
        retry_with_backoff()
    else:
        # Permanent client error — do not retry without fixing the request
        raise RuntimeError(f"{code}: {msg}")

Debugging failed runs

Always capture the run_id and task_id from every response — whether the request succeeded or failed. Include both values in any support ticket you open; they let the Overten team look up the exact ledger and trace rows on our side without asking you for more information. For async tasks that reach a terminal failed state, the error field on GET /tasks/{task_id} carries the full structured failure:
{
  "task_id": "task_...",
  "status": "failed",
  "error": {
    "code": "internal_error",
    "message": "AgentLoopError: max_tool_calls=30 exceeded"
  },
  "credits_used": 0,
  "duration_ms": 45123
}
If you see internal_error in the code field, copy the X-Request-Id response header and include it in your support ticket. It maps directly to the server-side trace for that request.

Rate limits

Every response includes rate-limit headers so you can track your remaining budget without waiting for a 429.
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1713312345
When the API returns 429, it also includes a Retry-After header with the number of seconds to wait before retrying:
Retry-After: 42
Rate limits are enforced per API key, per minute, at the gateway layer — before any agent or pool work starts. Hitting a rate limit does not deduct any credits.
Limits by tier:
TierRequests per minuteConcurrent runs
free102
pro6010
enterprise60050
The X-RateLimit-Reset value is a Unix timestamp in seconds (UTC). Convert it to a sleep duration by subtracting the current time before passing it to your retry logic, or simply use the Retry-After header directly.