Start
Authentication
Every call that spends or reads account data carries an API key as a bearer token. Keys are made on the account page, shown once, and scoped to what they may do.
Keys
- Create a key on your account page, under API keys. Name it after where it will live ("CI", "my agent") so you know which one to revoke later.
- The full key is shown once, when it is created. We keep only a hash of it, so it cannot be shown again; the account page lists keys by their first characters, like
ks_live_3fA9. - A key looks like
ks_live_followed by 43 random characters. An account can hold up to 20 live keys. - A key spends the account's credits exactly like the Generate button does. Treat it like a password: keep it in an environment variable or a secret store, never in a repository or a browser.
Sending the key
Put it in the Authorization header of every request:
Authorization: Bearer ks_live_YOUR_KEYA client that cannot set the Authorization header (Smithery, some MCP gateways) can send the same key, without the Bearer prefix, in X-Kinoseed-Key. It is checked exactly the same way. If both headers are sent they must carry the same key. A key is never read from the query string, because URLs end up in logs.
X-Kinoseed-Key: ks_live_YOUR_KEYOnly GET /models and GET /openapi.json are public. Any Authorization or X-Kinoseed-Key header at all is treated as an attempt to use a key: a malformed one is refused, never ignored.
Scopes
A key carries a set of scopes fixed when it is created. A call outside them answers 403 forbidden_scope. New keys get every scope but webhooks:manage unless you untick some. Give a key only what its job needs: an agent that only reads results needs jobs:read.
| Scope | Allows | Operations |
|---|---|---|
| images:generate | Generate images | POST /images |
| videos:generate | Generate videos | POST /videos |
| jobs:read | Read jobs | GET /jobsGET /jobs/{id} |
| jobs:write | Delete jobs | DELETE /jobs/{id} |
| files:write | Upload files | POST /files |
| credits:read | Read the credit balance | GET /credits |
| webhooks:manage | Manage webhooks | GET /webhooksPOST /webhooksDELETE /webhooks/{id}POST /webhooks/{id}/test |
POST /quote works with any live key, whatever its scopes: it never charges.
Rotation and revocation
- Revoke a key on the account page. It stops working on the next request; there is no grace period.
- To rotate, create the new key, deploy it, then revoke the old one. Two live keys at once is normal for the length of a deploy.
- If a key leaks, revoke it first and look second: a leaked key can spend the balance. The per-key rate limits (see Rate limits) slow a stranger down, they do not stop one.
The 401
A missing, malformed, unknown or revoked key answers 401 unauthorized with a bearer challenge, and details.reason says which: missing, invalid or revoked.
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="kinoseed"
Content-Type: application/json
{
"error": {
"code": "unauthorized",
"message": "This API key has been revoked.",
"details": {
"reason": "revoked"
}
}
}