DocsAPI referenceJobs
Create a job
Takes a command body (command, input_files, output_files) or an operations body (inputs, outputs), checks it and queues the job. With an Idempotency-Key, a retry with the same body within 24 hours answers 200 with the job it made, and a different body or endpoint answers 409.
POST /v1/jobs
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 JobRequest
Send the fields of one of these bodies, never both. Each has its own required fields.
CreateJobRequest
The command body: an ffmpeg command with its input_files and output_files (docs: command rules).
| Name | Type | Description |
|---|---|---|
input_files required | map of string to string, URL, up to 4,096 characters or string | Input aliases (in_ and a name) to http/https URLs or videxo://uploads/<upload_id>. |
output_files required | map of string to string, up to 105 characters | Output aliases (out_ and a name) to file names. |
command required | string, up to 65,536 characters | ffmpeg arguments without ffmpeg, naming files only by {{alias}}. |
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. |
OperationsJobRequest
The operations body: named inputs and a list of outputs, each an output type with options or a preset.
| Name | Type | Description |
|---|---|---|
inputs required | map of string to string or object | Input names to sources. A name becomes the alias in_<name>. |
outputs required | array of Output | |
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/jobs" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": {
"talk": "https://videxo.io/samples/talk.mp4"
},
"outputs": [
{
"name": "web",
"preset": "web-720p"
},
{
"name": "poster",
"preset": "poster"
}
],
"metadata": {
"order": "1234"
}
}'Copy failed. The text is selected; copy it with your keyboard.
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/jobs`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"inputs": {
"talk": "https://videxo.io/samples/talk.mp4"
},
"outputs": [
{
"name": "web",
"preset": "web-720p"
},
{
"name": "poster",
"preset": "poster"
}
],
"metadata": {
"order": "1234"
}
}),
});
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": null,
"spec": {
"inputs": {
"talk": {
"url": "https://videxo.io/samples/talk.mp4"
}
},
"outputs": [
{
"name": "web",
"type": "video",
"preset": "web-720p",
"input": "talk",
"filename": "web.mp4",
"format": "mp4",
"resize": {
"width": 1280,
"height": 720,
"fit": "contain",
"enlarge": false
},
"video": {
"codec": "h264",
"crf": 23,
"encoder_preset": "veryfast",
"pixel_format": "yuv420p",
"faststart": true
},
"audio": {
"codec": "aac",
"bitrate": "128k"
}
},
{
"name": "poster",
"type": "image",
"preset": "poster",
"input": "talk",
"filename": "poster.jpg",
"format": "jpg",
"resize": {
"width": 1280,
"height": 720,
"fit": "contain",
"enlarge": false
},
"at": "auto",
"quality": "high"
}
]
},
"command": "-i {{in_talk}} -map 0:v:0 -vf \"scale='min(iw,1280)':'min(ih,720)':force_original_aspect_ratio=decrease:force_divisible_by=2\" -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -map 0:a:0? -c:a aac -b:a 128k -movflags +faststart {{out_web}} -map 0:v:0 -vf \"thumbnail=300,scale='min(iw,1280)':'min(ih,720)':force_original_aspect_ratio=decrease:force_divisible_by=2\" -frames:v 1 -q:v 2 {{out_poster}}",
"input_files": {
"in_talk": "https://videxo.io/samples/talk.mp4"
},
"output_files": {
"out_web": "web.mp4",
"out_poster": "poster.jpg"
},
"ffmpeg_command": "ffmpeg -i https://videxo.io/samples/talk.mp4 -map 0:v:0 -vf 'scale='\\''min(iw,1280)'\\'':'\\''min(ih,720)'\\'':force_original_aspect_ratio=decrease:force_divisible_by=2' -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -map '0:a:0?' -c:a aac -b:a 128k -movflags +faststart web.mp4 -map 0:v:0 -vf 'thumbnail=300,scale='\\''min(iw,1280)'\\'':'\\''min(ih,720)'\\'':force_original_aspect_ratio=decrease:force_divisible_by=2' -frames:v 1 -q:v 2 poster.jpg",
"steps": [
{
"tool": "ffmpeg",
"inputs": [
"talk"
],
"outputs": [
"web",
"poster"
],
"command": "ffmpeg -i https://videxo.io/samples/talk.mp4 -map 0:v:0 -vf 'scale='\\''min(iw,1280)'\\'':'\\''min(ih,720)'\\'':force_original_aspect_ratio=decrease:force_divisible_by=2' -c:v libx264 -preset veryfast -crf 23 -pix_fmt yuv420p -map '0:a:0?' -c:a aac -b:a 128k -movflags +faststart web.mp4 -map 0:v:0 -vf 'thumbnail=300,scale='\\''min(iw,1280)'\\'':'\\''min(ih,720)'\\'':force_original_aspect_ratio=decrease:force_divisible_by=2' -frames:v 1 -q:v 2 poster.jpg"
}
],
"webhook_url": null,
"metadata": {
"order": "1234"
},
"progress": null,
"error": null,
"outputs": [],
"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 | usage_cap_reached or out_of_credits |
| 403 | Problem | permission_denied (account_disabled, token_scope) |
| 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 |
| 415 | Problem | invalid_request (not_json): the body is not sent as application/json |
| 429 | Problem | rate_limited, with Retry-After in seconds |
| 500 | Problem | internal_error |
| 503 | Problem | service_unavailable (temporary): the account's free credits are still being granted, or a part of the service did not answer |