Quickstart
From an empty account to a billed response, in four steps.
Every call goes to https://api.routehook.ai/v1, carries an API key in the Authorization header and draws against a prepaid balance. If your code already talks to an OpenAI-compatible endpoint, the integration is two lines: the base URL and the key.
Four steps
- 01Create an account and add credits
There is no free tier and no trial balance. A key with nothing behind it answers
402 insufficient_creditson its first call. The smallest top-up is $5, and credits spend across every live model. - 02Mint a key
Keys are created in the dashboard and shown once. Copy it straight into a secret manager or an environment variable. Choose live or test at creation; a key's environment cannot be changed afterwards.
- 03Make the call
Point an OpenAI client at the base URL, or send the JSON yourself.
modeltakes a slug fromGET /v1/models. - 04Read what it cost
The response headers report what the call cost and how it went.
GET /v1/creditsshows the balance after it.
Set the key
export ROUTEHOOK_API_KEY="sk_live_..."
The one-line switch
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.routehook.ai/v1",
apiKey: process.env.ROUTEHOOK_API_KEY,
});
const completion = await client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "Name three uses for a gateway." }],
});
console.log(completion.choices[0].message.content);
The model field is a slug
model is a catalogue slug (openai/gpt-4o-mini, anthropic/claude-sonnet-4) not a bare vendor model name. GET /v1/models lists every slug with its category, status and rate, and needs no key, so a model picker can read it straight from a browser. A slug nothing can serve right now answers 409 model_unavailable rather than quietly routing somewhere else.
The same call, without an SDK
curl https://api.routehook.ai/v1/chat/completions \
-H "Authorization: Bearer $ROUTEHOOK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4o-mini",
"messages": [{ "role": "user", "content": "Name three uses for a gateway." }]
}'
What the call cost, and how it went
The body is OpenAI's, so the charge is not in it. That goes in the response headers, and -i on the request above shows them. They matter because a retry is otherwise invisible: a request that failed over reads as an ordinary 200, and these headers are the only place that shows. None of them names the host that answered, which upstream serves a call is not something this API reports.
| HEADER | EXAMPLE | WHAT IT REPORTS |
|---|---|---|
| X-Routehook-Request-Id | req_7c41d9be | The id of this call. Quote it in a support report; pass it to GET /v1/generation. |
| X-Routehook-Attempts | 1 | How many attempts it took before one answered. |
| X-Routehook-Fallback | false | true when the first choice could not serve it and the chain fell through. |
| X-Routehook-Cost | 0.000103 | USD charged for this call. Absent on a stream. The charge is not known when the headers are written. |
| X-Routehook-Upstream-Latency-Ms | 812 | How long the upstream leg took, excluding our own routing. |
HTTP/1.1 200 OK
Content-Type: application/json
X-Routehook-Request-Id: req_7c41d9be
X-Routehook-Attempts: 1
X-Routehook-Fallback: false
X-Routehook-Cost: 0.000103
X-Routehook-Upstream-Latency-Ms: 812
Watch the balance move
One route reports the money side of the account. balance is settled cash, held is what requests in flight have reserved against it, and available is what the next request may spend, which is why a call can be refused while the balance still looks healthy.
GET/v1/creditsAvailable
Read the account balance, the amount held by requests in flight and what is left to spend.
curl https://api.routehook.ai/v1/credits \
-H "Authorization: Bearer $ROUTEHOOK_API_KEY"
{
"data": {
"total_credits": 250.0,
"total_usage": 128.44,
"balance": 121.56,
"held": 0.42,
"available": 121.14,
"credit_limit": 0,
"currency": "USD"
}
}
Let an agent wire it up
Working in Claude Code, Codex or Gemini CLI? Paste the command below. It points the agent at /llms.txt: the whole integration written for a machine: base URL, auth header, where model slugs come from, every error code and which of them are worth retrying.
Read https://routehook.ai/llms.txt and wire this project up to
Routehook exactly as it specifies. Use my ROUTEHOOK_API_KEY from the
environment, pick a model slug from GET /v1/models rather than guessing one,
and only add retry logic for 429 and 503.