On this page
Spend caps and key scoping
Limit what a key can spend and which models it can call, and see what a capped key returns.
Use separate keys for separate apps, environments or customers. Each key can have its own limits, so a leaked or buggy key can only do limited damage.
What you can set on a key
| Setting | Effect |
|---|---|
| Model allowlist | The key can call only the models you list. |
| Spend cap | The most the key can spend, in credits, for a reset period. |
| Expiry | After this date the key stops working. |
Set these in the dashboard when you create or edit a key. Revoke a key at any time. A revoked key stops working at once.
A key at its spend cap
When a key reaches its spend cap, requests with that key return 402 with the reason key_spend_cap_exceeded. The message is the same whichever cap was reached. To continue, raise the cap, wait for the cap period to reset, or use another key.
curl -i https://api.router.africa/v1/chat/completions \
-H "Authorization: Bearer $ROUTER_AFRICA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "openai/gpt-4o-mini", "messages": [{"role": "user", "content": "Hello"}]}'
# HTTP/2 402
# {"error":{"code":402,"message":"This API key has reached its spend limit. Raise the limit or use another key.","metadata":{"error_type":"payment_required","reason":"key_spend_cap_exceeded"}}}import os
import openai
from openai import OpenAI
client = OpenAI(base_url="https://api.router.africa/v1", api_key=os.environ["ROUTER_AFRICA_API_KEY"])
try:
client.chat.completions.create(
model="openai/gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
except openai.APIStatusError as e:
if e.status_code == 402 and e.body["metadata"]["reason"] == "key_spend_cap_exceeded":
print("This key is at its cap. Raise it or use another key.")
else:
raiseimport OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.router.africa/v1",
apiKey: process.env.ROUTER_AFRICA_API_KEY,
});
try {
await client.chat.completions.create({
model: "openai/gpt-4o-mini",
messages: [{ role: "user", content: "Hello" }],
});
} catch (err) {
if (err instanceof OpenAI.APIError && err.status === 402) {
console.log("This key may be at its cap. Raise it or use another key.");
} else {
throw err;
}
}A key and a model it can’t use
If the model doesn’t exist, is switched off, or isn’t allowed for the key, you get 404 with the reason model_not_found. The answer is the same in all three cases. Check the model id and the key’s allowed models.
Check a key’s limits
GET /v1/key (API reference) returns the key’s spend cap, its usage, its expiry and the workspace’s credit balance, all in credits.
curl https://api.router.africa/v1/key \
-H "Authorization: Bearer $ROUTER_AFRICA_API_KEY"import os
import httpx
r = httpx.get(
"https://api.router.africa/v1/key",
headers={"Authorization": f"Bearer {os.environ['ROUTER_AFRICA_API_KEY']}"},
)
print(r.json())const res = await fetch("https://api.router.africa/v1/key", {
headers: { Authorization: `Bearer ${process.env.ROUTER_AFRICA_API_KEY}` },
});
console.log(await res.json());The response has one data object:
| Field | Meaning |
|---|---|
name |
The key’s name. |
limit |
The key’s spend cap in credits, or null if it has none. |
limit_period |
How often the cap resets, or none. |
usage |
Credits used in the current cap period. |
limit_remaining |
Credits left under the cap, or null if there is no cap. |
expires_at |
When the key expires, as a date-time, or null. |
balance |
The workspace’s available credits: its balance minus credits held for running requests. |
Credit amounts are strings with eight decimal places and no currency code.
{
"data": {
"name": "production",
"limit": "500.00000000",
"limit_period": "monthly",
"usage": "120.50000000",
"limit_remaining": "379.50000000",
"expires_at": null,
"balance": "1250.00000000"
}
}