Authentication¶
All API requests are authenticated with an API key that you create on the API Keys page of your dashboard.
API Key Format¶
Keys are shown with an sk- prefix. The prefix is optional when you send the key — both sk-abc123 and abc123 are accepted — but keep it, since OpenAI SDKs expect it.
Sending Your Key¶
The standard form is a Bearer token:
A bare value without the Bearer word also works: Authorization: sk-YOUR_API_KEY.
Example¶
Provider-native headers¶
If you use an SDK that speaks a provider's own protocol, send the key the way that SDK does — the same key works:
| Header / parameter | Used by | Accepted on |
|---|---|---|
Authorization: Bearer sk-… |
OpenAI-compatible SDKs | all endpoints |
x-api-key: sk-… |
Anthropic SDKs | /v1/messages, /v1/models |
x-goog-api-key: sk-… or ?key=sk-… |
Google Gemini SDKs | /v1beta/models…, /v1/models/… |
Sec-WebSocket-Protocol: openai-insecure-api-key.sk-… |
Realtime WebSocket clients | /v1/realtime |
Key Settings¶
When you create a key you can configure:
| Setting | Description |
|---|---|
| Name | A label for the key (max 50 characters), e.g. "production", "staging". |
| Quota | Spend limit for this key, in credits. Can be set to unlimited, in which case the key draws on your account balance. |
| Model access | Optional allow-list. If enabled, the key may only call the listed models. |
| Expiration | Optional expiry timestamp. A key with no expiry never expires. |
| IP allow-list | Optional list of IP addresses or CIDR ranges. Requests from any other address are rejected. |
| Group | Optional rate/price group the key is pinned to. If empty, your account's group is used. |
One key per application
Separate keys for development, staging and production let you track usage and revoke access independently.
Retrieving a Key Later¶
The key is masked in listings, but it is not lost — you can reveal the full value again from the API Keys page at any time (single key, or several at once). Retrieval is rate limited, so treat it as recovery, not as a routine part of your deploy.
Site Binding¶
Prices are a property of the site you send the request to, not of your account. A key belongs to the site it was created on and only works there — which is also why a key issued on one site would not give you that site's prices anywhere else. Sending it to a different host returns:
{
"error": {
"message": "this API key is not valid on this domain (request id: 20260812...)",
"type": "new_api_error",
"code": "access_denied"
}
}
Every error message carries the request id — quote it when you contact support.
If you see this, you are pointing at the wrong base URL — create a key on the site you are calling, or fix base_url.
Rate Limits¶
| Limit | Default | Applies to |
|---|---|---|
| Per-IP API limit | 360 requests / 180 seconds | all API endpoints |
| Per-user model-request limit | disabled by default; when enabled, 1000 successful requests per minute | model calls (/v1/chat/completions and friends) |
| Sensitive actions (e.g. revealing a key) | 20 requests / 20 minutes | dashboard actions |
There is no tokens-per-minute (TPM) limit. Operators can change every value above, so treat these as defaults rather than guarantees. On 429 Too Many Requests, back off and retry with exponential delay.
Error Responses¶
Errors use the OpenAI shape: {"error": {"message": …, "type": "new_api_error", "code": …}}.
| Status | Meaning |
|---|---|
401 |
API key missing, malformed, disabled, expired, or its own quota is used up |
403 |
Key used on a different site than it was created on (access_denied), requested model not in the key's allow-list, request IP outside the key's allow-list, or the account is banned |
402 |
Insufficient balance to start the request |
429 |
Rate limit exceeded |
500 |
Internal error — retry, and quote the request id if it persists |