Every request to the Tokens API authentication layer needs one platform key, sent in a header. This page covers the base URLs, the headers we accept, the key format, and what each authentication error means.
Base URLs#
Tokens exposes two surfaces on the same host. Which one you use depends on the client, not the model.
| Client style | Base URL | Typical tools |
|---|---|---|
| OpenAI-compatible | https://tokens.bd/v1 | OpenAI SDKs, Cursor, Cline, Aider, OpenCode, Codex CLI |
| Anthropic-compatible | https://tokens.bd | Anthropic SDKs, Claude Code (they append /v1/messages themselves) |
If a tool asks for an "API base" or "base URL" and is OpenAI-flavored, include /v1. If it is Anthropic-flavored, leave /v1 off, because the SDK adds it. Getting this wrong is the most common cause of a 404 on the first request.
Tools that need to discover the endpoints can read them from a public, unauthenticated config endpoint:
curl https://tokens.bd/api/gateway/config{
"openaiBaseUrl": "https://tokens.bd/v1",
"anthropicBaseUrl": "https://tokens.bd"
}Send your API key in a header#
We accept the key in either of two headers. Use whichever your client sends by default.
| Header | Format | Sent by |
|---|---|---|
Authorization | Bearer tok_live_your_key | OpenAI SDKs, Claude Code with ANTHROPIC_AUTH_TOKEN, most tools |
x-api-key | tok_live_your_key | Anthropic SDKs |
If both are present, the Authorization: Bearer header wins. An Authorization header with any scheme other than Bearer is ignored, and the gateway then looks for x-api-key.
curl https://tokens.bd/v1/models \
-H "Authorization: Bearer $TOKENS_API_KEY"curl https://tokens.bd/v1/models \
-H "x-api-key: $TOKENS_API_KEY"Key format#
Keys look like tok_live_ followed by 48 hexadecimal characters. The full secret is shown once, when you create the key in the dashboard. We store only a hash, so a lost key cannot be recovered; create a new one instead. Key creation, spend caps, allowed-model lists and rotation are covered in API keys.
Keep the key in an environment variable#
All examples in these docs read the key from TOKENS_API_KEY:
export TOKENS_API_KEY="tok_live_your_key"On Windows PowerShell:
$env:TOKENS_API_KEY = "tok_live_your_key"Then read it in code rather than pasting it:
import os
from openai import OpenAI
client = OpenAI(
base_url="https://tokens.bd/v1",
api_key=os.environ["TOKENS_API_KEY"],
)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://tokens.bd/v1",
apiKey: process.env.TOKENS_API_KEY,
});Do not commit keys
A key in a committed .env, config file or notebook is a leaked key. Add those files to .gitignore. If a key does leak, rotate it in the dashboard; the old secret stops working immediately.
Server-side only: no browser calls#
The API does not send CORS headers on its responses, so fetch from a web page will fail in the browser even with a valid key. This is deliberate: a key shipped to a browser is readable by anyone who opens dev tools. Call Tokens from your backend, a serverless function, a CLI, or a coding agent, and have your frontend talk to that.
What 401 and 403 mean#
Authentication failures return the standard error body with a machine-readable code:
{
"error": {
"message": "Invalid API key.",
"type": "authentication_error",
"code": "invalid_api_key",
"param": null,
"request_id": "8f0c7a4e-2b1d-4c55-9a51-3f7e2d9b6c10"
}
}| Status | Code | Meaning | Fix |
|---|---|---|---|
| 401 | missing_api_key | No Authorization: Bearer or x-api-key header arrived | Check the env var is set in the shell that runs the tool |
| 401 | invalid_api_key | The key does not match any key we issued | Check for truncation or stray quotes; copy the key again or create a new one |
| 403 | key_inactive | The key was revoked or rotated | Use the current secret or create a new key |
| 403 | key_expired | The key had an expiry date that has passed | Create a new key |
| 403 | account_suspended | The account is suspended | Contact support |
| 403 | model_not_allowed_on_key | The key has an allowed-models list that excludes this model | Use a listed model or a different key |
| 403 | monthly_spend_cap_exceeded | The key reached its monthly spend cap | Wait for the next month or use another key |
| 403 | tier_permission_denied | Your plan does not include this model and you have no wallet balance | See plans and wallet |
A 401 or 403 with code upstream_auth_error is different: it means the gateway's own credentials for an upstream provider were refused, not yours. Your key is fine; retry later or try another model, and include the request id if you contact support.
The full list of codes, including billing and rate-limit errors, is in errors. To confirm a key works end to end, the quickstart has a one-line test request.