Authentication & API keys
Key types and prefixes, where to create them, scopes, rate limits, rotation, and what each auth error means.
Sending the key
Authorization: Bearer sk_stav_live_...
x-api-key: sk_stav_live_... also works, because that is how the Anthropic SDK sends its key. If both headers are present, Authorization wins.
Base URL for every surface: https://api.stav.ai/v1.
Key types
| Prefix | Type | Environment |
|---|---|---|
sk_stav_live_ | Workspace key | Production |
sk_stav_test_ | Workspace key | Test |
sk_stav_user_live_ | Personal key | Production |
sk_stav_user_test_ | Personal key | Test |
- Workspace keys belong to the workspace. Owners and admins create them.
- Personal keys belong to one member. They are available when a workspace admin has enabled them under Your workspace → Govern → Key policies, which can also require approval (Your workspace → Govern → Approvals).
- Both kinds are billed to the workspace wallet at catalogue price.
- The environment is part of the key, not the URL. Live and test keys call the same host.
Create both in Your workspace → Connect → API keys. A key is shown once and stored only as a hash — if you lose it, rotate it.
Verify a key
curl https://api.stav.ai/v1/auth/validate \
-H "Authorization: Bearer $STAV_API_KEY"
{
"valid": true,
"team_id": "…",
"team_name": "Acme AS",
"api_key_id": "…",
"api_key_name": "prod-backend",
"api_key_prefix": "sk_stav_live_",
"environment": "PRODUCTION",
"scopes": ["inference:chat", "inference:models"]
}
No tokens, no cost. scopes is null when the key has no scope restrictions.
Scopes
| Scope | Grants |
|---|---|
inference:chat | POST /v1/chat/completions, POST /v1/responses |
inference:messages | POST /v1/messages, POST /v1/messages/count_tokens |
inference:embeddings | POST /v1/embeddings |
inference:audio | POST /v1/audio/transcriptions |
inference:models | GET /v1/models, GET /v1/models/{id} |
A key with no scopes has full access. Scopes restrict; they do not grant. Set them if you want least privilege.
A call outside the key's scopes:
{
"error": {
"message": "This API key does not have the 'inference:embeddings' scope.",
"type": "permission_error",
"code": "insufficient_scope"
}
}
Many IDE and agent tools fill their model picker from GET /v1/models. A key with only inference:chat completes requests but returns 403 on that list — add inference:models.
Other key settings
- Expiry — a key past
expires_atreturnsexpired_api_key. - IP allowlist — a request from any other address returns
403 ip_not_allowed.
Rate limits
Per key, requests per minute, over a sliding 60-second window:
- Production keys: 300 rpm by default
- Test keys: 30 rpm by default
- A per-key override replaces the default
When exceeded:
HTTP 429
Retry-After: 3
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785667200
{
"error": {
"message": "Rate limit exceeded. Retry after 2.4 seconds.",
"type": "rate_limit_error",
"code": "rate_limit_exceeded"
}
}
Wait for Retry-After. Only this per-key limit sends the X-RateLimit-* headers; a 429 without them came from elsewhere. See Errors.
Auth errors
| Code | Status | Cause |
|---|---|---|
missing_api_key | 401 | No Authorization: Bearer and no x-api-key, or an empty token |
invalid_api_key | 401 | Not an sk_stav_ key, unknown, or revoked |
expired_api_key | 401 | Past its expiry, or a rotated key past its grace period |
insufficient_scope | 403 | Key lacks the scope for this endpoint |
ip_not_allowed | 403 | Caller IP not on the key's allowlist |
model_not_permitted | 403 | Your workspace's configuration does not allow that model |
rate_limit_exceeded | 429 | See above |
The 401s carry WWW-Authenticate: Bearer.
Rotation
Rotating a key issues a new one and keeps the old one working for a grace period (7 days by default). After that the old key returns expired_api_key.
- Rotate the key under Your workspace → Connect → API keys and copy the new key.
- Deploy it.
- Check Your workspace → Monitor → Request log until the old key has no traffic.
- Let the grace period end, or revoke the old key.
If a key leaks
Revoke it under Your workspace → Connect → API keys. Then filter Your workspace → Monitor → Request log by that key to see every call it made, with model, tokens and cost.
Good practice
- One key per application. Attribution and revocation are per key.
- Use a test key in CI.
- Scope keys that ship inside tools:
inference:chat+inference:modelscovers most agent integrations.