Authentication
The three auth headers, key format and lifecycle, and auth-related errors.
Every data-plane request (/v1/* and /v1beta/*) must carry an API key. To stay compatible with all three SDK families, the gateway checks three auth headers in order — any one of them works:
| Header | Format | Typical clients |
|---|---|---|
Authorization | Authorization: Bearer sk-sole-… (a bare key without the Bearer prefix is also accepted) | OpenAI SDK · Codex |
x-api-key | x-api-key: sk-sole-… | Anthropic SDK · Claude Code |
x-goog-api-key | x-goog-api-key: sk-sole-… | Google GenAI SDK |
Passing the key via URL query parameters (such as Google's ?key=) is not supported: query strings end up in access logs and browser history, which makes leaks likely. Always use a header.
Key format & lifecycle
Keys start with sk-sole-. The full key is shown only once at creation and the server stores only a hash — a lost key cannot be recovered, only replaced. Each key can be configured independently with:
- Enable/disable: switch a key off at any time without losing its usage history.
- Expiry date: useful for temporary integrations or handing keys to third parties.
- Spending limit: a USD cap, optionally resetting daily/weekly/monthly; once exhausted the key is rejected (HTTP 402).
- IP allowlist: restrict which source IPs may use the key; requests from other IPs are rejected (HTTP 403).
Auth-related errors
| Situation | HTTP | Message id |
|---|---|---|
| No key provided | 401 | key_missing |
| Key unknown or deleted | 401 | key_invalid |
| Key disabled | 403 | key_disabled |
| Key expired | 403 | key_expired |
| Source IP not in allowlist | 403 | key_ip_denied |
| Key spending limit reached | 402 | key_quota_exhausted |
| Account suspended | 403 | account_disabled |
Error bodies take the shape of whichever SDK format matches the request path, and messages are localized to the account's preferred language (or Accept-Language before authentication succeeds, defaulting to English). See Errors.
Security best practices
- Keep keys in environment variables or a secret manager — never in source code or config repos.
- Do not expose keys in client-side code such as browsers; if the frontend must call directly, use a dedicated key with a small quota and an IP allowlist.
- Split keys by workload so usage stays isolated and incidents are contained — disable only the affected key.
- Rotate keys periodically, and give temporary keys an expiry date and spending limit.