API keys
A caller key is how a request says who is spending. It looks like this:
1sk-aile-4f1a9c2e8b7d06315a4e9f2c8d1b7e30a6c5f4938e2d1b0a
sk-aile- followed by 48 hex characters. The prefix is deliberate: a key that
leaks into a log or a repository is recognisable to the scanners that look for
exactly this shape.
Minting one
In the dashboard, Calling → API keys, then Create key. A name, a spend limit with its reset period and an expiry are all optional. The full value is shown once, with both base URLs and a quickstart for your coding tools (more under Connect tools). Set up routing there opens the key's routing and brings you back to the secret.
The key is shown once
Only a hash is stored. If you lose it, revoke it and mint another; there is no way to recover the original.
Sending it
Two header spellings are accepted, because the two SDK families differ:
1Authorization: Bearer sk-aile-...
1x-api-key: sk-aile-...
Use whichever your SDK already sends. The Anthropic SDK sends only x-api-key;
OpenAI-shaped clients send Authorization. Both reach the same key.
A bare Bearer with nothing after it is not accepted as a key. Neither header
present is a 401 in your own SDK's dialect. See Errors.
Three optional headers label a request so you can group your spend later:
| Header | Value |
|---|---|
X-Aile-Tag | A short tag: letters, digits and . _ : / -, up to 64 characters. |
HTTP-Referer | Your app's URL. Only the hostname is kept. It is spoofable and display only. A hostname many accounts send may be listed on /stats. |
X-End-User | Your end user's id, on any key. Use an opaque id, not an email. |
What the key does and does not reach
The caller key stops at the relay. It names who is spending and what limits apply. It is never forwarded to a provider: the provider always sees the sharer's credential, never yours.
Pinning routing to a key
Some clients cannot set custom headers. For those, the same routing levers can be attached to the key itself, with its Routing button in Calling → API keys:
| Rule | Effect |
|---|---|
| Providers | |
| Provider | Only this provider serves the key, and model ids are sent to it as written. |
| Any provider (a hint, not a setting) | Write auto/ instead of a provider: auto/claude-sonnet-5 goes to the cheapest provider that lists it, then the next if that one fails; never a self-hosted model. Not on a key limited to one provider. A key that still has the older Let a bare model id use any provider on shows it until it is turned off. See Any provider. |
| Never these providers | A request naming one is a 400, and auto/ skips them. Off while a single provider is set. |
| Price | |
| Discount | Only sharers whose input and output prices are both at least this far below the higher of the model's published input and output rates, as x-aile-max-price: N% would with N = 100 − the discount. Models with no published price are refused. |
| Max discount | Skip sharers priced further below list than this, as x-aile-min-price: N% would with N = 100 − the max discount. Cannot sit below the discount. |
| Max cost per request | No request made with the key is charged more than this many dollars; a sharer quoting more is passed over. x-aile-max-cost can lower it for one request. See Capping the cost of a request. |
| Sharers | |
| Only these sharers | Every model the key calls is served only by these sellers, cheapest first. |
| Never these sharers | Every model the key calls skips these sellers; the next sharer serves. |
| Prefer speed over price | Chat requests try the fastest sharer first, price breaking a tie. It may bill a dearer quote. See Speed first. |
| Move sharers that keep failing to the back | A sharer that fails this key 3 times in 5 minutes is tried last for 10 minutes. See Sharers that keep failing. |
| Keep a conversation on one sharer | On by default: each conversation goes back to the account that served it, by the session id your client sends or, from its third turn, by the conversation itself. See Session affinity. |
| Sharer handle (Advanced) | Only this one seller. Replaced by Only these sharers when you list any. |
| Node id (Advanced) | Only this machine. |
| Privacy | |
| Allow self-hosted model | Untick to keep the key off self-hosted machines, which can read prompts. A local/ request is then a 400. |
| Only providers that do not train on prompts | As x-aile-data-collection: deny, for every request the key makes. |
These are the Rules tab, in its four groups; named routes are the Model routes tab. An older key
may also carry "verified accounts only" or a max $/Mtok: both still apply, and
show with Remove.
A header can narrow, never widen
If a key is pinned to claude and a request sends x-aile-provider: codex, the
request is refused rather than served. A request header may tighten a pinned
filter; it can never loosen one.
Named routes
A key can carry aliases that map a name you choose to a provider and model, with a
fallback chain. Requests then send your name in the model field:
1{ "model": "fast/summarise", "messages": [] }
Because a named route's slash separates your handle from your model, the name is exempt from the provider rule and taken verbatim. Each target in the route must name a provider (its own provider field, the key's provider pin, or a prefixed model). A name or model over 200 characters is refused. The key's provider, excluded providers, discount, max discount, cost cap, sharer lists, data-collection and self-hosted rules bind every target; a single sharer and node pin is per target. A route takes at most 10 targets. Which entry in the chain served is reported back:
1x-aile-combo-entry: 1
A route can also prefer speed or price over the key's choice, carry a daily budget for the whole route and for each target, and give a target its own lower cost cap. A key's routes can be exported to a file, imported, copied to another key, and dry-run to see which sharers a request would reach without sending it. See Calling & keys and Choosing a sharer.
Auto routes
An auto route is a named route with auto: true whose targets each carry a tier:
light, standard or heavy. Each request is served from the tier its shape picks.
You still name every model the route can reach, and Aile dials nothing else.
1{2 "name": "aile/auto",3 "auto": true,4 "entries": [5 { "tier": "light", "model": "openrouter/google/gemini-3.8-flash" },6 { "tier": "standard", "model": "cc/claude-sonnet-5-5" },7 { "tier": "standard", "model": "openrouter/anthropic/claude-sonnet-5.5" },8 { "tier": "heavy", "model": "cc/claude-opus-5-5", "maxPctOfList": 60 }9 ]10}
A tier can be the same model. A target may carry an effort (none, minimal,
low, medium, high, xhigh or max), so one model serves all three tiers:
1{2 "name": "aile/auto",3 "auto": true,4 "entries": [5 { "tier": "light", "model": "codex/gpt-6.1-terra", "effort": "low" },6 { "tier": "standard", "model": "codex/gpt-6.1-terra", "effort": "medium" },7 { "tier": "heavy", "model": "codex/gpt-6.1-terra", "effort": "high" }8 ]9}
Every target needs a tier, and the route needs at least one standard target. tier and
effort are refused on any other route, effort on a local/ target too, and an auto
route is always in order. The tier is read from the request's shape, never its text:
x-aile-auto-tierforces a tier, up or down.- High reasoning (
highor above, or a thinking budget of 16,000 tokens or more) or a prompt of 100,000 tokens or more goes heavy. - A small request goes light: no tools, images or other media, a prompt of at most 8,000 tokens, an output cap of at most 4,096, and reasoning no higher than low.
- Everything else goes standard.
Lower tiers are never tried, with one exception: a heavy request on a route with no heavy
target is served by standard. A tier with no target moves up, and so does one whose models
cannot hold the prompt or read its images. A request moves up wherever a route moves to its
next target: no sharer, 502, 503, or a target skipped before it is called (its daily
budget spent, your price limit). A 4xx or 402 that ends a target's attempts (an upstream
400, a payment required) is returned. A conversation
keeps the tier that last served it, so moving up lifts it too, and only the header lowers it.
Your own reasoning setting always wins: Aile writes a target's effort only when the request
set none, and on /v1/messages only one the Claude model takes. Prices, holds and your limits apply per target, as in any route, and the tier never
depends on your balance. This is unrelated to the auto/ prefix above, which picks a provider
for one model.
Four headers report it. x-aile-auto-tier is the tier chosen; x-aile-auto-reason is why
(header, reasoning, long-prompt, small, default or pinned, plus +window or
+vision when a model that could not take the prompt or the image moved it); x-aile-auto-escalated
is the tier that served, only when it is above the chosen one; x-aile-auto-effort is the
effort Aile wrote. The response model echoes the route name, and x-aile-model names the
model that served. See Headers.
To use one from Claude Code, set ANTHROPIC_MODEL and ANTHROPIC_DEFAULT_HAIKU_MODEL to
the route's name; for Codex, set model to it. aile setup --route <name> does both. You
build the route in Calling & keys.
Limits
A key can carry a spend limit, optionally resetting daily, weekly or monthly. When it is reached the key stops serving rather than drawing further on your balance. The limit is per key, so one runaway integration cannot spend what the rest of your account holds.
Revoking
Disable pauses a key until you enable it again; Revoke deletes it for good, keeping its usage history. Either stops it immediately; in-flight requests are not retroactively refunded, and nothing else on the account is affected. The stake key is rotated on the stake page instead.
Idempotency
An optional header makes a retry safe:
1Idempotency-Key: <your-unique-value>
It is hashed and scoped per caller. A replay of the same key returns 409 and does
not fail over to another sharer. A duplicate is not a reason to try somebody
else.