DocsAPI referenceClient tokens
Mint a client token for an app or a web page
A short-lived token for one end user's action, with a narrow grant: uploads, reading the jobs you name, or both. Call it from your server; the token is shown once. With continues, the token refreshes a chain and is no wider than its newest token.
POST /v1/client-tokens
Needs an API key: Authorization: Bearer $VIDEXO_API_KEY.
Body CreateClientTokenRequest
| Name | Type | Description |
|---|---|---|
ttl_seconds | integer, 60 to 21600 | Lifetime in seconds, 60 to 21600 (6 hours); 900 by default. Default 900. |
subject | string | Your own opaque id of the end user (never an email): stored, shown in your logs and used to revoke their tokens at once. |
allowed_origins | array of string, up to 256 characters | Up to 5 exact browser origins; a request from another origin is refused. Leave out for native apps and any origin. |
continues | string | Any token of the same subject's chain, to refresh it: the new token keeps the chain's uploads count and read job ids, and is no wider than the chain's newest token. |
uploads | ClientUploadsGrant | |
jobs | ClientJobsGrant |
Request
bash
curl -X POST "$VIDEXO_API_URL/v1/client-tokens" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"subject": "user_8f2c",
"uploads": {
"max_count": 1,
"max_size_bytes": 50000000,
"content_types": [
"video/*"
]
}
}'Copy failed. The text is selected; copy it with your keyboard.
JavaScript
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/client-tokens`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"subject": "user_8f2c",
"uploads": {
"max_count": 1,
"max_size_bytes": 50000000,
"content_types": [
"video/*"
]
}
}),
});
const minted = await response.json();Copy failed. The text is selected; copy it with your keyboard.
Response
201 JSON
{
"id": "ct_4m8x2k9q0c3v7n1r5t6b2z8w",
"token": "vdx_ct_AWdK3xA...",
"chain_id": "ct_4m8x2k9q0c3v7n1r5t6b2z8w",
"expires_at": "2026-11-04T12:15:00.000Z",
"grant": {
"subject": "user_8f2c",
"allowed_origins": null,
"uploads": {
"max_count": 1,
"max_size_bytes": 50000000,
"content_types": [
"video/*"
]
},
"jobs": null
}
}Copy failed. The text is selected; copy it with your keyboard.
Responses
| Status | Body | When |
|---|---|---|
| 201 | ClientToken | The token, once. Hand token and id to the app. |
| 400 | Problem | invalid_request: a field, a limit past the plan, or a continuation wider than its chain |
| 401 | Problem | authentication_failed (missing_api_key, invalid_api_key, api_key_revoked, api_key_expired) |
| 403 | Problem | permission_denied (account_disabled, token_scope) |
| 404 | Problem | not_found (job): an id in jobs.read is not one of your jobs |
| 413 | Problem | limit_exceeded (request_body_size) |
| 429 | Problem | rate_limited, with Retry-After in seconds |
| 503 | Problem | service_unavailable (temporary): other continuations of the chain kept landing first; mint again |