AI API authentication, keys, and scopes
Every /v1 endpoint is authenticated with a dashboard session cookie or a scoped API key. This page covers keys, scopes, workspace scoping, and errors.
Bearer API keys
All /v1 endpoints accept a dashboard session cookie or an API key:
Authorization: Bearer fi_live_<64-char-key>Keys are created in the dashboard (or with POST /v1/api-keys), hashed at rest (SHA-256), and the plaintext is shown exactly once. A revoked or expired key returns 401 unauthenticated.
Scopes
Keys carry scopes; the all scope grants everything. Grant the minimum scopes each service needs:
| generations.write | Create + cancel generations |
| generations.read | List/detail generations, model catalog |
| files.write | Upload URLs, upload completion, asset mutate/delete |
| assets.read | Asset list/detail/download |
| usage.read | Usage, credits, storage, wallet reads |
| wallet.write | Wallet deposits (top-ups) |
| webhooks.manage | Webhook endpoints + delivery history |
| all | Everything |
A request missing the required scope returns 403 forbidden. API keys cannot create or revoke other API keys — that is dashboard-only.
Workspace scoping
API keys belong to one workspace. Every request must target that workspace's id in the body or query (workspaceId); targeting any other workspace returns 403 forbidden. Team members share the workspace's keys, credits, and wallet.
Identity on records
Requests made with an API key are attributed to the key in usage reporting (GET /v1/api-keys/:id/usage and GET /v1/usage) and in generations.apiKeyId. Keys are stamped with lastUsedAt (throttled to once per minute).
Error envelope
Errors use a stable envelope so clients can branch on code, not messages:
{
"error": {
"code": "insufficient_credits",
"message": "...",
"requestId": "..."
}
}Common codes:
| 400 | validation_error |
| 401 | unauthenticated |
| 402/422 | insufficient_credits, plan_limit_reached, wallet_pending_minimum, wallet_insufficient_balance |
| 403 | forbidden |
| 404 | not_found |
| 409 | conflict |
| 429 | rate_limited |
| 500 | internal_error |
Tip
Rate limits are enforced per key with X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset response headers. See API reference for details.