Skip to main content
Every job returns the same output shape, no matter the type. A complete job carries one output object. Read output.data for a computed answer, output.file.url for the file to play or download, and output.files for the full list.
{
  "data": <job-type-specific JSON> | null,
  "file": <File> | null,
  "files": <File>[],
  "expiresAt": <unix ms> | null
}
output is present when status is complete. A failed job carries an error object instead. See Job lifecycle for status transitions.

Fields

data
object | null
The computed answer for jobs that return one, such as a probe result, detections, or a transcript. null for jobs that only write files. The shape is job-type-specific, so each type documents its own. See Per-type data shapes.
file
File | null
The headline result you play or download: a single output file, or a stream manifest (.m3u8 / .mpd, typed playlist). null for data-only jobs and for pure file sets with no single headline. Always one of files.
files
File[]
Every file the job produced, the complete list. A single-file job lists one. A stream lists the manifest plus segments. A set lists every member. [] for data-only jobs.
expiresAt
integer | null
Unix ms when the file URLs expire. Present when files is non-empty. Re-fetch the job with GET /jobs/{id} to mint fresh URLs.

Choosing file vs files

files is the complete list of everything a job wrote. Most jobs return a single output, but some return many: an image sequence, the segments of an HLS stream, or a resolution ladder. When a job can produce more than one file, read files. file is a shortcut for the common case. When you expect a single output, read output.file.url and you have the result, with no need to index into the list. For a single-output job, file is that one file, so it is the same entry as files[0]. That overlap is on purpose. It keeps the everyday case a one-liner while files stays the honest, complete manifest of what came out. A job with no single headline sets file to null. So a null file is also the signal that the result is a pure set of files or a data-only answer, not one file you play or download.
Expecting one output? Read output.file.url directly. Handling a job that can write many files (frames, HLS segments, a ladder)? Iterate output.files. Both always agree: file, when set, is one of files.

The File type

Each entry in file and files is the same shape:
{
  "url": "https://api.rendobar.com/dl/job_abc123?token=<token>",
  "path": "output.mp4",
  "type": "video",
  "size": 4194304,
  "meta": { "format": "mp4", "width": 1280, "height": 720, "durationMs": 30000 }
}
url
string
Signed download or serving URL. Expires at output.expiresAt.
path
string
The filename the job wrote, such as output.mp4.
type
string
Open enum: video, image, audio, captions, playlist, data, or other. Treat it as open. Tolerate values you don’t recognize, since new types can appear without a version bump.
size
integer
File size in bytes.
meta
object
Optional probed metadata: format, width, height, durationMs. Each field is present when known.

Invariants

Three rules hold for every job type. Code against them.
  • output.file is always one of output.files (or null). The headline is never a file missing from the full list.
  • output.expiresAt is present whenever output.files is non-empty. Data-only jobs leave both files empty and expiresAt null.
  • A complete job always has output.data or output.files (or both). It never returns an empty result.

How to consume

The read path is the same every time:
const { data: job } = await res.json();

// 1. The computed answer, for jobs that return one.
if (job.output.data) {
  console.log(job.output.data);
}

// 2. The thing to play or download.
if (job.output.file) {
  console.log(job.output.file.url);
}

// 3. The full list, for sets and streams.
for (const f of job.output.files) {
  console.log(f.path, f.type, f.size);
}
You never branch on a job-type discriminator to find the result. output.data, output.file, and output.files mean the same thing for ffmpeg, extract.metadata, caption.extract, and every other type.

Output patterns

Four patterns cover every job. The shape is identical. Which fields are populated depends on what the job produced.

Single file

One output file. file is that file, files lists one, data is null. The most common pattern for transform jobs (FFmpeg, transcode, watermark).
{
  "data": null,
  "file": {
    "url": "https://api.rendobar.com/dl/job_abc123?token=<token>",
    "path": "output.mp4",
    "type": "video",
    "size": 4194304,
    "meta": { "format": "mp4", "width": 1280, "height": 720, "durationMs": 30000 }
  },
  "files": [
    {
      "url": "https://api.rendobar.com/dl/job_abc123?token=<token>",
      "path": "output.mp4",
      "type": "video",
      "size": 4194304,
      "meta": { "format": "mp4", "width": 1280, "height": 720, "durationMs": 30000 }
    }
  ],
  "expiresAt": 1735689600000
}

Stream

An HLS or DASH stream. file is the manifest, typed playlist. Point a player at file.url directly. files carries the manifest plus every segment.
{
  "data": null,
  "file": { "url": "https://api.rendobar.com/v/job_abc123/<token>/master.m3u8", "path": "master.m3u8", "type": "playlist", "size": 412 },
  "files": [
    { "url": "https://api.rendobar.com/v/job_abc123/<token>/master.m3u8", "path": "master.m3u8", "type": "playlist", "size": 412 },
    { "url": "https://api.rendobar.com/v/job_abc123/<token>/seg_000.ts", "path": "seg_000.ts", "type": "video", "size": 1048576 },
    { "url": "https://api.rendobar.com/v/job_abc123/<token>/seg_001.ts", "path": "seg_001.ts", "type": "video", "size": 1041203 }
  ],
  "expiresAt": 1735689600000
}

Set

An unordered set with no single headline, such as an image sequence, a -f segment split, or a resolution ladder. file is null. Read files for the list.
{
  "data": null,
  "file": null,
  "files": [
    { "url": "https://api.rendobar.com/v/job_abc123/<token>/frame_000.png", "path": "frame_000.png", "type": "image", "size": 204800 },
    { "url": "https://api.rendobar.com/v/job_abc123/<token>/frame_001.png", "path": "frame_001.png", "type": "image", "size": 205120 },
    { "url": "https://api.rendobar.com/v/job_abc123/<token>/frame_002.png", "path": "frame_002.png", "type": "image", "size": 203904 }
  ],
  "expiresAt": 1735689600000
}

Data-only

A job that computes an answer instead of writing files. data carries the result. file is null, files is empty, expiresAt is null.
{
  "data": {
    "width": 1280,
    "height": 720,
    "durationMs": 30000,
    "codec": "h264",
    "fps": 30,
    "bitrate": 2500000,
    "audioCodec": "aac",
    "audioChannels": 2,
    "audioSampleRate": 48000
  },
  "file": null,
  "files": [],
  "expiresAt": null
}

Per-type data shapes

output.data is the only part of the output that varies by job type. Transform jobs leave it null and return files. Analysis jobs return their result here and write no file. The rule of thumb:
  • Transform jobs (ffmpeg, transcode, watermark.*, caption.burn) return files with data: null.
  • Analysis jobs (moderation, detection, captions, transcript, OCR, metadata) return their result in data and usually write no file.
Status: Only ffmpeg is live today. The other job types below are documented but not yet callable. See each job type page for its availability banner.
Job typedata shapeFiles
ffmpegnullThe files your command wrote
extract.metadataProbe result (see below)None (data-only)
extract.scenesScene cut listNone (data-only)
extract.textRecognized text with positions and timestampsNone (data-only)
caption.extractTranscript with word timingsA captions file (.srt / .vtt)
compliance.moderateModeration labels with confidencesNone (data-only)
compliance.gdpr.detectDetected regions (faces, plates) with bounding boxesNone (data-only)
watermark.detectMatch result with confidenceNone (data-only)
transcode, watermark.apply, caption.burnnullThe transformed media

extract.metadata

output.data is the probe result. The job runs ffprobe, returns the result inline, and writes no file.
{
  "data": {
    "width": 1280,
    "height": 720,
    "durationMs": 30000,
    "codec": "h264",
    "fps": 30,
    "bitrate": 2500000,
    "audioCodec": "aac",
    "audioChannels": 2,
    "audioSampleRate": 48000
  },
  "file": null,
  "files": [],
  "expiresAt": null
}
FieldTypeMeaning
widthintegerFrame width in pixels
heightintegerFrame height in pixels
durationMsintegerDuration in milliseconds
codecstringVideo codec, such as h264
fpsnumberFrames per second
bitrateintegerOverall bitrate in bits per second
audioCodecstringAudio codec, present when the file has audio
audioChannelsintegerChannel count, present when the file has audio
audioSampleRateintegerSample rate in Hz, present when the file has audio

See also