Authentication
Every API call carries a secret key in the Authorization header. Keys are scoped to what they may do, and can be limited by address, model and spend.
Send your key
Send the key as a bearer token on every request to https://api.vizoapi.com/v1. Requests without a valid key get HTTP 401.
cURL
curl https://api.vizoapi.com/v1/models \
-H "Authorization: Bearer $VIZO_API_KEY"Python
import os, requests
res = requests.get(
"https://api.vizoapi.com/v1/models",
headers={"Authorization": f"Bearer {os.environ['VIZO_API_KEY']}"},
timeout=30,
)Node.js
const res = await fetch("https://api.vizoapi.com/v1/models", {
headers: { Authorization: `Bearer ${process.env.VIZO_API_KEY}` },
});A key starts with va_01 followed by 64 characters. Store it without the word Bearer.
Important
Keep keys on your server. Never put a key in a web page, a mobile app, a public repository or a log. Anyone with the key can spend your Credits within its limits.
Key types
Create keys in the console under API keys. The full key is shown once, when you create it.
| Key | Belongs to | Use it for |
|---|---|---|
| Project key | One project | Models, generations and media assets of that project, and the organization's balance with balance:read |
| Billing key | The organization | Reading the balance and the ledger, read-only |
Generations, uploads and webhooks belong to the project of the key that created them. A project key cannot read another project's tasks.
Scopes
A key may call only the operations its scopes allow. Give each key the smallest set it needs. A call outside the key's scopes gets HTTP 403 with error.code scope_denied.
| Scope | Key | Allows |
|---|---|---|
models:read | Project | List models and get a model |
generations:create | Project | Create a generation and estimate a price |
generations:read | Project | Get a generation |
generations:list | Project | List generations, to find a task after a lost response |
assets:upload | Project | Start and complete an upload |
assets:reference | Project | Use an uploaded asset (ast_...) as a generation input |
assets:download | Project | Download an asset |
assets:delete | Project | Delete an asset |
usage:read | Both | Read usage and limits |
balance:read | Project | Get the balance |
billing:read | Billing | Get the balance and list ledger entries |
billing:export | Billing | Export billing records |
A server that only creates videos and downloads them needs models:read, generations:create, generations:read, generations:list and assets:download.
Restrict a key
Each project key can carry limits of its own. Set them when you create the key, or change them later in the console.
| Limit | What happens outside it |
|---|---|
| IP allowlist: up to 10 IPv4 or IPv6 addresses or CIDR ranges. Empty allows any address. | HTTP 403, error.code ip_not_allowed |
| Model allowlist: up to 200 model IDs. Empty allows every model, including models added later. | HTTP 403, error.code model_not_allowed |
| Daily and monthly spend limits in Credits. Days and months follow UTC. Credits held for open tasks count toward the limit. | The task closes as failed with error.code budget_exceeded; nothing is charged |
| Expiry date. | HTTP 401 invalid_credentials once the key has expired |
Spend limits are checked when a task is funded, so a create returns HTTP 202 first. Read the task to see a budget_exceeded closure, or receive it as a generation.failed webhook.
Rotate a key
Keys do not rotate in place. To replace one without downtime:
- Create a new key with the same scopes and limits.
- Deploy it to your servers and confirm requests succeed with it.
- Revoke the old key in the console. Revocation takes effect immediately.
Revoke a key at once if it may have been exposed. Tasks it already created keep running and stay readable with any key of the same project.
Authentication errors
| HTTP | error.code | Meaning | What to do |
|---|---|---|---|
| 401 | invalid_credentials | The key is missing, malformed, expired or revoked. | Check the header and the key in the console. |
| 403 | scope_denied | The key lacks the scope for this operation. | Add the scope or use another key. |
| 403 | ip_not_allowed | The request came from an address outside the key's IP allowlist. | Call from an allowed address or update the allowlist. |
| 403 | model_not_allowed | The key may not use this model. | Add the model to the key's model allowlist. |
| 429 | rate_limited | Too many requests with invalid keys from your address in one minute. | Fix the key, then wait the seconds in Retry-After. |