Authentication
API keys, rate limits, and playback tokens: the three credential types the API uses.
API keys
Create and revoke API keys from Settings in your dashboard. A new key's plaintext value is shown exactly once, right after you create it. vdoX only stores its hash, so if you lose it, revoke it and create a new one, there's no way to view it again.
- Keys look like
vdx_followed by 40 hex characters (44 characters total). - Revoking a key is immediate and takes effect on its next use.
- Every key in a workspace can do everything the API supports; there are no scoped/read-only keys yet.
Send it in the standard bearer header on every request:
Authorization: Bearer vdx_4f2b9e1a7c6d3f805e2b91ac4d7e0f3b1a2c9d8eA missing header, the wrong scheme, or an unknown/revoked key all return the same 401, so a caller can't probe which one is wrong:
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key"
}
}Rate limits
Each workspace gets 60 requests per minute, shared across every API key in that workspace. Every authenticated response, success or error, carries an X-RateLimit-Remaining header showing how many requests are left in the current window.
Go over the limit and you get a 429 instead of the request running:
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded, try again later"
}
}Playback tokens
Playback tokens are a separate, short-lived credential: your backend mints one per viewer, per video, by calling POST /api/v1/videos/:id/playback-token with your API key. Unlike an API key, a playback token can only play the one video it was minted for, and only for a few minutes.
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2aWRlb0lkIjoiMDFBUlozTkRFS1RTVjRSUkZGUTY5RzVGQVYi...",
"expiresAt": "2026-07-13T09:05:00.000Z",
"manifestUrl": "https://api.vdox.example.com/videos/01ARZ3NDEKTSV4RRFFQ69G5FAV/hls/master.m3u8?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}expiresAt is 5 minutes (300 seconds) after minting by default. Mint a fresh token per view, don't try to reuse one across viewers or cache it long-term.
Errors
Every error response has the same shape: { error: { code, message } }. The full set of codes the API returns:
| Code | HTTP status | Meaning |
|---|---|---|
unauthorized | 401 | Missing, malformed, or revoked API key |
rate_limited | 429 | More than 60 requests in the last 60 seconds for this workspace |
invalid_request | 400 | Request body or query params failed validation |
invalid_file | 400 | Filename extension isn't one of mp4, mov, mkv, webm, m4v |
not_found | 404 | Video doesn't exist, or belongs to a different workspace |
not_ready | 409 | Video hasn't finished processing yet |
conflict | 409 | Video isn't in a state the request allows (e.g. cancelling one that's already ready) |
workspace_suspended | 403 | Workspace has been suspended by an admin, contact support |
quota_videos | 403 | Your plan's video limit is reached |
quota_storage | 403 | Your plan's storage limit is reached |
quota_upload_size | 403 | File exceeds the plan's max upload size |
quota_plays | 403 | Plan's monthly plays limit reached |
unsupported_file | 422 | The uploaded file was rejected during processing |
upstream_error | 502 | vdoX's processing service is temporarily unavailable, retry |
internal_error | 500 | Unexpected server error |