API reference
The public HTTP surface for AnonRouter integrations.
The production base URL for OpenAI-compatible clients is:
https://api.anonrouter.ai/v1That is the only URL ordinary tools such as OpenCode, SillyTavern, and OpenAI SDK clients need. The private ticket flow additionally uses:
https://control.anonrouter.ai/v1The control origin receives keys and content-free account or authorization requests. The confidential API origin receives inference content and attestation requests. The AnonRouter SDK keeps the two origins separate automatically.
Requests authenticate one of three ways, depending on the endpoint:
- Inference key (
ar_) inAuthorization: Bearerto issue tickets and, in compatibility mode, to call inference directly. - Management key (
arm_) inAuthorization: Bearerto read balance and usage. - Inference ticket in the
x-anonrouter-ticketheader to run a single ticketed request.
Some account and billing operations require an authenticated session and are performed from the dashboard rather than with an API key.
Inference
| Method | Endpoint | Origin | Credential | Description |
|---|---|---|---|---|
GET | /models | Control; API in compatibility mode | Inference or management key | List enabled models and capabilities |
GET | /catalog/models | Control | None | Public, cacheable catalog with privacy metadata |
GET | /models/uptime | Control | None | Passive success-rate and latency series |
POST | /inference/tickets | Control | Inference key | Issue a single-use inference ticket |
POST | /chat/completions | API | Ticket | Create a streaming or non-streaming chat completion |
POST | /embeddings | API | Ticket | Create vector embeddings |
POST | /images/generations | API | Ticket | Generate an image (when enabled) |
POST | /audio/speech | API | Ticket | Synthesize speech (when enabled) |
GET | /capabilities | Control | None | Report enabled media feature flags |
/models/uptime requires a ?model=<id> query parameter and answers 400 missing_model without one.
In compatibility mode, /chat/completions and
/embeddings accept an inference key directly instead of a ticket.
How the confidential origin decides which flow you are in
api.anonrouter.ai dispatches on the Authorization header. Send a ticket and
no bearer token and you are in the private ticket flow; send an ar_ bearer
token and you are in compatibility mode, which is why GET /v1/models answers
404 there without a credential and an OpenAI-shaped 401 invalid_api_key
with one. Control-plane routes are not served on that origin in either flow.
Attestation
| Method | Endpoint | Origin | Credential | Description |
|---|---|---|---|---|
GET | /gateway/attestation | API | None | Attest AnonRouter's own confidential plane (hop 1); requires ?nonce= of exactly 64 hex characters |
GET | /tee/attestation | Control | Inference key | Fetch provider enclave evidence for a model and provider (hop 2) |
POST | /tee/attestation | API | Attestation ticket | The same evidence without presenting a key to the content plane; send the ticket in x-anonrouter-ticket and the nonce in the JSON body |
GET | /tee/signature/:providerRequestId | Control | Inference key | Retrieve a per-request enclave receipt where the provider exposes one |
POST | /inference/attestation-tickets | Control | Inference key | Mint a model-bound ticket for the ticketed attestation call |
See TEE verification for what each document proves.
The routing, account, workspace, billing, and key-management endpoints below
are control-plane operations and use https://control.anonrouter.ai/v1 unless
the page says otherwise.
Routing
| Method | Endpoint | Credential | Description |
|---|---|---|---|
GET | /routing/effective | Inference key | List models the saved preferences allow |
GET | /routing/preferences | Session | Read saved routing preferences |
PUT | /routing/preferences | Session | Replace saved routing preferences |
POST | /routing/preview | Session | Preview a routing decision |
POST | /routing/eligible-models | None | List models eligible for draft preferences |
Account
| Method | Endpoint | Credential | Description |
|---|---|---|---|
GET | /balance | Management key | Read available and reserved balance |
GET | /usage | Management key | Read recent usage metadata |
Workspaces
| Method | Endpoint | Credential | Description |
|---|---|---|---|
GET | /workspaces | Session | List workspaces |
POST | /workspaces | Session | Create a workspace |
PATCH | /workspaces/:id | Session | Edit a workspace |
DELETE | /workspaces/:id | Session | Delete a workspace |
Connected Apps
Not enabled on the production deployment yet
AnonRouter Connect is operator-gated and is currently switched off in
production: the discovery document and every endpoint in this section answer
404 on the live deployment. The interface below is documented so an
integration can be written against it, not because it can be called today.
Connected Apps uses a focused OAuth 2.1 and OpenID Connect provider. Begin with
the discovery document at
https://control.anonrouter.ai/connect/.well-known/openid-configuration
instead of hard-coding the authorization, token, UserInfo, revocation, or JWKS
paths. See Connected Apps for the complete user and developer
flow.
The dashboard uses these session-authenticated management endpoints:
| Method | Endpoint | Description |
|---|---|---|
GET | /connect/grants | List the account's active and historical app grants |
DELETE | /connect/grants/:id | Disconnect one grant |
GET | /connect/apps | List enabled developer apps owned by the account |
POST | /connect/apps | Register an app and return its client secret once |
PATCH | /connect/apps/:id | Change app metadata; redirect changes revoke current grants |
POST | /connect/apps/:id/rotate-secret | Rotate the secret and revoke current grants |
DELETE | /connect/apps/:id | Disable the app and revoke current grants |
Billing
| Method | Endpoint | Credential | Description |
|---|---|---|---|
GET | /billing/catalog | None | Packages, limits, fee, payment terms, and whether card and crypto rails are currently enabled |
GET | /billing/orders | Session | List purchase orders |
GET | /billing/orders/:orderId | Session | Poll one order |
GET | /billing/receipts | Session | List receipts |
GET | /billing/receipts/:receiptNumber | Session | Fetch one receipt |
Response headers
Successful inference responses include:
x-anonrouter-selected-model: the chosenprovider/model.x-anonrouter-routing:autoorexact.x-ratelimit-limit-requests,x-ratelimit-remaining-requests,x-ratelimit-reset-requests, and the matching-tokensvariants.
Errors
Errors use an OpenAI-style envelope with a machine-readable type and a
request_id:
{
"error": {
"message": "Inference ticket is invalid or expired",
"type": "invalid_ticket",
"request_id": "req_..."
}
}Common cases:
| Status | type | Meaning |
|---|---|---|
401 | ticket_required | A ticket is required and none was sent |
401 | invalid_ticket | The ticket is invalid, expired, or already used |
403 | insufficient_scope | The credential lacks the required scope |
402 | insufficient_balance | Not enough prepaid balance |
404 | model_not_found | The model is unknown or not enabled |
409 | ticket_model_mismatch | The request model differs from the ticket |
409 | ticket_reasoning_mismatch | The reasoning selection differs from the ticket |
429 | rate_limited | Rate limit exceeded; see retry-after |
503 | media_disabled | Image or speech is not enabled on this deployment |
A 429 response also sets a retry-after header. During streaming, a mid-stream
provider failure is delivered as an inline SSE error frame rather than an HTTP
status, because the response headers have already been sent.