API keys
Create and revoke keys in the dashboard under API Keys. Each secret is a single string:- Prefix:
rk_ - Then 64 hexadecimal characters (256 bits)
Passing your API key
- X-API-Key header
OpenAI and Anthropic SDKs send
Authorization: Bearer by default; routing.run treats that the same as X-API-Key for rk_ secrets.Managing API keys over HTTP
POST/v1/user/key, GET /v1/user/key, and DELETE /v1/user/key/ require Authorization: Bearer <access JWT> — the HS256 access token from the routing.run auth flow (POST /auth/login/verify, OAuth completion, or POST /auth/refresh), not an rk_ inference key. The access token payload includes sub (user id) and plan.
If the header is missing or does not start with
Bearer , the handler raises RateLimitError today, which returns HTTP 429 with body Authentication required and X-Error-Code: RATE_LIMIT_ERROR. Treat that as “missing user session” until the API distinguishes it from real rate limits.Create an API key
Response includes the full secret once inkey (same rk_ + 64 hex format):
List your API keys
Returns{"data": [ ... ]} with id, key_prefix, name, plan_tier, created_at, last_used_at — never the full secret.
Revoke an API key
KEY_ID is the id from list or create. Success body: {"message":"API key revoked"}. Unknown id → 404 with plain-text body and X-Error-Code: NOT_FOUND.
Plan tiers
Your workspace plan tier decides whichroute/… IDs you may call and how many requests and credits you have. Exact numbers live in the dashboard (they can change as plans update).
| Tier | Model access | Where to see limits |
|---|---|---|
| Free | Free-tier models in Models | Dashboard usage and daily cap |
| Lite | Free + Lite models | Same |
| Premium | Adds Premium models | Same |
| Max | Full catalog including Max-only models | Same |
tier field on each object in GET /v1/models comes from routing config for the resolved plan.
Error responses
Most application errors useExceptionHandlerMiddleware: the response body is plain text (the message string), and the machine code is in the X-Error-Code header. There is no JSON {"error":{...}} wrapper for these in the current API.
Example (daily cap):
401from auth middleware when no credentials:{"message":"Authentication required"}or invalid JWT:{"message":"Invalid or expired token"}.429from IP rate-limit middleware:{"message":"Rate limit exceeded. Please try again later.", "retry_after": …}plusRetry-AfterandX-RateLimit-*headers.- POST
/v1/chat/completionsstreaming errors: SSEdata: {"error":{"message":"…","type":"api_error"}}. - GET
/v1/models/unknown id:{"error":"Model not found"}. - Some image error paths:
{"error":{"message":"…","type":"api_error"}}or{"error":"Model not found"}.
/v1/chat/completions, POST /v1/messages, …) validate the rk_ key in the handler: wrong key → 401 plain text Invalid API key with X-Error-Code: AUTHENTICATION_ERROR.
Never share your API key publicly or commit it to version control.
Common X-Error-Code values (plain-text body)
| Status | X-Error-Code | Typical body text |
|---|---|---|
| 401 | AUTHENTICATION_ERROR | Invalid API key / Authentication failed |
| 402 | INSUFFICIENT_CREDITS | Insufficient credits for this request |
| 403 | MODEL_NOT_ALLOWED | Model '…' is not available on your plan |
| 429 | DAILY_REQUEST_LIMIT_EXCEEDED | Daily request limit exceeded |
| 429 | RATE_LIMIT_ERROR | IP limit or (misleading today) missing Bearer on /v1/user/key* |
| 502 | PROVIDER_ERROR | Upstream-specific message |
| 504 | PROVIDER_TIMEOUT | Timeout message |
| 503 | CIRCUIT_BREAKER_OPEN | Circuit breaker open for an upstream |
| 400 | INVALID_MODEL | Invalid model: '…' |