Token Factory exposes several surfaces — the public /v1 API, the Playground proxy, API-key management, and quota/status routes — and they don't all use the same error shape today. This page covers the public /v1 contract and notes per-surface differences inline.
#On the public /v1 API
The public /v1 gateway returns the OpenAI-style nested envelope:
The HTTP status code is the primary signal — pivot off that, not off the message text. The error.code is a stable machine-readable string; error.message is human-readable and may change.
Other surfaces use different shapes. If you're parsing errors programmatically, branch by surface — don't assume one envelope.
| Surface | Envelope shape | Status range |
|---|---|---|
/v1/chat/completions | { error: { type, code, message, param } } (OpenAI-shape) | 4xx, 5xx |
/v1/embeddings | Same OpenAI-shape envelope | 4xx, 5xx |
/v1/models | Same OpenAI-shape envelope | 4xx, 5xx |
| API key management routes | { code, error, ... } (nested with a stable string code) | 4xx, 5xx |
| Playground proxy routes | { code, message, details } (upstream errors classified) | 4xx, 5xx |
| Quota and status routes | Gateway-shaped | 4xx, 5xx |
#At a glance
| Status | Cause | What to do |
|---|---|---|
400 Bad Request | Malformed JSON or missing required parameter | Read the error string, fix the request shape |
401 Unauthorized | Missing or invalid API key | Check Authorization header; see Authentication |
403 Forbidden | Key revoked, or feature not enabled for your workspace | Verify the key in the dashboard; contact admin |
404 Not Found | Unknown model, unknown endpoint | Check the model value against the dashboard catalog |
408 Request Timeout | Request took too long to read or upstream worker timed out | Retry with a shorter prompt or honor Retry-After |
409 Conflict | Resource-state conflict (e.g. rotating an API key that's already pending rotation, or modifying a workspace setting that another admin just changed) | Read the error string; refresh state and retry |
422 Unprocessable Entity | Validation failed (e.g. invalid value range) | Read the error string for the offending field |
429 Too Many Requests | Rate limit or quota exceeded | Back off, then retry; see Tokens, pricing & quotas |
500 Internal Server Error | Unhandled server error | Retry with exponential backoff and jitter; if persistent, file a support ticket |
502 Bad Gateway | Upstream proxy issue | Retry with exponential backoff and jitter |
503 Service Unavailable | No healthy upstream for this model right now | Retry; if persistent, the model is degraded — pick an alternate from the catalog |
#401 Unauthorized
Causes: header missing, header malformed, key revoked, key from a different workspace.
- Confirm the header is present and shaped
Authorization: Bearer sk-.... - Confirm the key starts with
sk-and matches the masked prefix in the dashboard. - If the key was rotated recently, your service may still have the old value cached — restart the worker.
#429 Too Many Requests
You hit either a per-minute rate limit or your workspace quota.
- The response includes
Retry-After(seconds) — honor it. - Implement exponential backoff with jitter — start at 1s ±50%, double each retry (1s, 2s, 4s, 8s, 16s ±50% per step), capped at 30s. Jitter prevents thundering-herd retries when a transient upstream failure clears.
- For sustained 429s, request a quota increase or shift load to a smaller, cheaper model in the catalog.
See Tokens, pricing & quotas for the full quota model.
#503 No healthy upstream
A specific model is temporarily without a healthy replica. The error message will look like:
- Retry — most 503s resolve within seconds.
- Fall back to another model of similar capability from the Model Library — use the same capability chips to find peers.
- Check status — persistent 503 on a single model is a model-availability issue, not a platform issue.
A minimal fallback chain in Python:
#SSL
CERTIFICATE_VERIFY_FAILED on the Python openai SDK (and most TLS-using clients) means your runtime can't verify the server's certificate chain. The cause is almost always a corporate proxy or VPN intercepting TLS with its own root CA. The CA needs to be installed in the trust store your runtime uses.
#Python
Use certifi's bundle plus your corporate root.
Both must be set: requests reads REQUESTS_CA_BUNDLE; standard-library urllib/http.client reads SSL_CERT_FILE.
If you control the bundle file, append your corp root to certifi's bundle rather than replacing it:
#Node.js
#curl
requests.get(..., verify=False), curl -k, NODE_TLS_REJECT_UNAUTHORIZED=0 all silence the symptom but leave you wide open to MITM. Install the root CA correctly instead.