DocsAPI referenceOperations
Upscale a video with AI
Upscales one video input to resolution (1080p, 1440p or 4k) with AI, keeping its frame rate (at most 60 fps), or doubling one of 30 fps or less with frame_rate: "smooth". The input must be at most 1920x1080 and smaller than the target. How it is enhanced is chosen from the input's size once it is read, and shown as the output's enhancement: under half the target on both sides the model adds detail (full); from half the target or more the result is a faithful enhancement close to a sharp resize (faithful). Free credits cannot pay for it, and each plan has its own targets and longest clip. The job reserves the estimate's credits_max. Its AI credits and base are billed, at the band of its output's frame rate, for the clip it made when it succeeds, or for what was processed when it is cancelled during processing; a failed job pays at most the data used. When no capacity is free in time, the job ends service_unavailable with nothing charged. Creates the same Job as POST /v1/jobs with an ai_upscale output; it has no ffmpeg command, and ai shows the clip's seconds, credits and expected wait once the input is read. A scoped API key needs the jobs:run scope (full keys may call it).
POST /v1/ai-upscale
Needs an API key: Authorization: Bearer $VIDEXO_API_KEY.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
idempotency-key | header | string, up to 255 characters | Makes retries safe for 24 hours. Up to 255 printable ASCII characters. One key space per account across every endpoint that creates a job. |
Body AiUpscaleRequest
| Name | Type | Description |
|---|---|---|
input required | string or object | An http or https URL, videxo://uploads/<upload_id>, { "url" } or { "upload_id" }. |
resolution required | one of 1080p, 1440p, 4k | The target: 1080p, 1440p or 4k. The input must be smaller. |
frame_rate | one of source, smooth | source (default) keeps the input's rate, at most 60 fps; smooth doubles a rate of 30 fps or less. |
trim | object | The part of the input to process, in seconds. |
audio | one of keep, remove | keep (default) puts the source's own sound back in sync; remove leaves the output silent. |
filename | string | The stored file name; .mp4 only. |
webhook_url | string, URL, up to 2,048 characters or null | An https URL that gets the job when it ends (M4). |
metadata | map of string to string, up to 500 characters | Your own string pairs, returned with the job and its webhook: at most 20 keys of up to 40 characters, values up to 500. |
Request
curl "$VIDEXO_API_URL/v1/ai-upscale" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "https://videxo.io/samples/talk.mp4",
"resolution": "1080p",
"trim": {
"start": 0,
"duration": 8
}
}'Copy failed. The text is selected; copy it with your keyboard.
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/ai-upscale`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"input": "https://videxo.io/samples/talk.mp4",
"resolution": "1080p",
"trim": {
"start": 0,
"duration": 8
}
}),
});
const job = await response.json();Copy failed. The text is selected; copy it with your keyboard.
Response
{
"id": "job_3k9x0c2mfq8w1n7r5t4b6v2z",
"state": "queued",
"kind": "operations",
"operation": "ai_upscale",
"spec": {
"inputs": {
"source": {
"url": "https://videxo.io/samples/talk.mp4"
}
},
"outputs": [
{
"name": "video",
"type": "ai_upscale",
"input": "source",
"filename": "upscaled.mp4",
"resolution": "1080p",
"frame_rate": "source",
"trim": {
"start": 0,
"duration": 8
},
"audio": "keep"
}
]
},
"command": null,
"input_files": null,
"output_files": null,
"ffmpeg_command": null,
"steps": [],
"notices": [],
"webhook_url": null,
"metadata": {},
"progress": null,
"error": null,
"outputs": [],
"ai": null,
"usage": null,
"created_at": "2026-11-04T12:00:00.000Z",
"started_at": null,
"finished_at": null
}Copy failed. The text is selected; copy it with your keyboard.
Responses
| Status | Body | When |
|---|---|---|
| 200 | Job | The job this Idempotency-Key made earlier (same endpoint and body). |
| 202 | Job | The job, queued. |
| 400 | Problem | invalid_request (with errors) or command_invalid (with problems) |
| 401 | Problem | authentication_failed (missing_api_key, invalid_api_key, api_key_revoked, api_key_expired) |
| 402 | Problem | out_of_credits, or out_of_credits (purchased_credits_only): free credits cannot pay for AI operations |
| 403 | Problem | permission_denied (account_disabled, token_scope); permission_denied (key_scope): a scoped API key without jobs:run |
| 404 | Problem | not_found (upload) |
| 409 | Problem | conflict (idempotency_key_reused) |
| 413 | Problem | limit_exceeded: request_body_size (the body is larger than 512 KB), media_resolution (the plan does not offer the target) or media_duration (trim.duration is longer than the plan allows) |
| 415 | Problem | invalid_request (not_json): the body is not sent as application/json |
| 429 | Problem | rate_limited, with Retry-After in seconds: requests over the limit, or waiting_jobs for an account at its limit of jobs waiting |
| 500 | Problem | internal_error |
| 503 | Problem | service_unavailable (temporary): AI upscale is not available right now, the account's free credits are still being granted, or a part of the service did not answer |