Imageanonrouterdocs

Quickstart

Make your first ticketed chat completion with AnonRouter.

Before you begin

You need an AnonRouter inference API key. Create one in the dashboard, keep it on a trusted server, and load it from an environment variable. Inference keys are prefixed ar_ and are shown only once at creation.

Create an API key
export ANONROUTER_API_KEY="ar_..."
export ANONROUTER_API_URL="https://api.anonrouter.ai/v1"
export ANONROUTER_CONTROL_URL="https://control.anonrouter.ai/v1"

Do not expose API keys in browsers

The examples below are for trusted server-side environments. A browser client should call your own backend, which holds the key.

1. Request a single-use ticket

The ticket binds the request to its model and output limit. Issue a new ticket for every inference request. Tickets are valid for 30 seconds, so issue one and send the completion promptly.

TICKET=$(curl -s "$ANONROUTER_CONTROL_URL/inference/tickets" \
  -H "Authorization: Bearer $ANONROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "meta-llama/llama-3.3-70b",
    "max_completion_tokens": 256
  }' | jq -r .ticket)

The response contains an opaque ticket string plus the constraints it was bound to (model, max_output_tokens, operation, privacy_class, reasoning, and expires_in).

2. Send the completion

Present the ticket to the relay in the x-anonrouter-ticket header. The relay does not need your API key. The model and output limit must match the ticket.

curl "$ANONROUTER_API_URL/chat/completions" \
  -H "Content-Type: application/json" \
  -H "x-anonrouter-ticket: $TICKET" \
  -d '{
    "model": "meta-llama/llama-3.3-70b",
    "max_tokens": 256,
    "messages": [
      {
        "role": "user",
        "content": "Explain private model routing in one paragraph."
      }
    ]
  }'

The response is a standard OpenAI chat completion object. Two headers report the selection: x-anonrouter-selected-model and x-anonrouter-routing.

With the OpenAI SDK

The OpenAI SDKs work against the same base URL. Issue the ticket with a plain HTTP call, then pass it as an extra header on the completion. The SDK still sends your key as a bearer token, which the relay ignores in favor of the ticket.

import os
import httpx
from openai import OpenAI

api_url = os.environ.get("ANONROUTER_API_URL", "https://api.anonrouter.ai/v1").rstrip("/")
control_url = os.environ.get(
    "ANONROUTER_CONTROL_URL",
    "https://control.anonrouter.ai/v1",
).rstrip("/")
api_key = os.environ["ANONROUTER_API_KEY"]

ticket_response = httpx.post(
    f"{control_url}/inference/tickets",
    headers={"Authorization": f"Bearer {api_key}"},
    json={
        "model": "meta-llama/llama-3.3-70b",
        "max_completion_tokens": 256,
    },
)
ticket_response.raise_for_status()
ticket = ticket_response.json()["ticket"]

# The real key was used only for the content-free ticket request. The OpenAI
# client requires a non-empty api_key, so use a non-secret placeholder here.
client = OpenAI(api_key="ticket-only", base_url=api_url, max_retries=0)

completion = client.chat.completions.create(
    model="meta-llama/llama-3.3-70b",
    max_tokens=256,
    messages=[{"role": "user", "content": "Hello from AnonRouter"}],
    extra_headers={"x-anonrouter-ticket": ticket},
)

print(completion.choices[0].message.content)

Prefer a static key?

If your client cannot perform the ticket step, use a key with compatibility mode enabled and point the OpenAI SDK straight at https://api.anonrouter.ai/v1 with no ticket. New keys enable compatibility by default. Review the privacy tradeoff first.

Next steps

Or hand the whole thing to your agent

One prompt carries the entire setup. Give it to your agent, review what it configures, and you are done.

On this page