anonrouterdocs

API reference

The public HTTP surface for AnonRouter integrations.

The production base URL for OpenAI-compatible clients is:

https://api.anonrouter.ai/v1

That 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/v1

The 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_) in Authorization: Bearer to issue tickets and, in compatibility mode, to call inference directly.
  • Management key (arm_) in Authorization: Bearer to read balance and usage.
  • Inference ticket in the x-anonrouter-ticket header 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

MethodEndpointOriginCredentialDescription
GET/modelsControl; API in compatibility modeInference or management keyList enabled models and capabilities
GET/catalog/modelsControlNonePublic, cacheable catalog with privacy metadata
GET/models/uptimeControlNonePassive success-rate and latency series
POST/inference/ticketsControlInference keyIssue a single-use inference ticket
POST/chat/completionsAPITicketCreate a streaming or non-streaming chat completion
POST/embeddingsAPITicketCreate vector embeddings
POST/images/generationsAPITicketGenerate an image (when enabled)
POST/audio/speechAPITicketSynthesize speech (when enabled)
GET/capabilitiesControlNoneReport 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

MethodEndpointOriginCredentialDescription
GET/gateway/attestationAPINoneAttest AnonRouter's own confidential plane (hop 1); requires ?nonce= of exactly 64 hex characters
GET/tee/attestationControlInference keyFetch provider enclave evidence for a model and provider (hop 2)
POST/tee/attestationAPIAttestation ticketThe 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/:providerRequestIdControlInference keyRetrieve a per-request enclave receipt where the provider exposes one
POST/inference/attestation-ticketsControlInference keyMint 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

MethodEndpointCredentialDescription
GET/routing/effectiveInference keyList models the saved preferences allow
GET/routing/preferencesSessionRead saved routing preferences
PUT/routing/preferencesSessionReplace saved routing preferences
POST/routing/previewSessionPreview a routing decision
POST/routing/eligible-modelsNoneList models eligible for draft preferences

Account

MethodEndpointCredentialDescription
GET/balanceManagement keyRead available and reserved balance
GET/usageManagement keyRead recent usage metadata

Workspaces

MethodEndpointCredentialDescription
GET/workspacesSessionList workspaces
POST/workspacesSessionCreate a workspace
PATCH/workspaces/:idSessionEdit a workspace
DELETE/workspaces/:idSessionDelete 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:

MethodEndpointDescription
GET/connect/grantsList the account's active and historical app grants
DELETE/connect/grants/:idDisconnect one grant
GET/connect/appsList enabled developer apps owned by the account
POST/connect/appsRegister an app and return its client secret once
PATCH/connect/apps/:idChange app metadata; redirect changes revoke current grants
POST/connect/apps/:id/rotate-secretRotate the secret and revoke current grants
DELETE/connect/apps/:idDisable the app and revoke current grants

Billing

MethodEndpointCredentialDescription
GET/billing/catalogNonePackages, limits, fee, payment terms, and whether card and crypto rails are currently enabled
GET/billing/ordersSessionList purchase orders
GET/billing/orders/:orderIdSessionPoll one order
GET/billing/receiptsSessionList receipts
GET/billing/receipts/:receiptNumberSessionFetch one receipt

Response headers

Successful inference responses include:

  • x-anonrouter-selected-model: the chosen provider/model.
  • x-anonrouter-routing: auto or exact.
  • x-ratelimit-limit-requests, x-ratelimit-remaining-requests, x-ratelimit-reset-requests, and the matching -tokens variants.

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:

StatustypeMeaning
401ticket_requiredA ticket is required and none was sent
401invalid_ticketThe ticket is invalid, expired, or already used
403insufficient_scopeThe credential lacks the required scope
402insufficient_balanceNot enough prepaid balance
404model_not_foundThe model is unknown or not enabled
409ticket_model_mismatchThe request model differs from the ticket
409ticket_reasoning_mismatchThe reasoning selection differs from the ticket
429rate_limitedRate limit exceeded; see retry-after
503media_disabledImage 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.

On this page