Properties
| Name | Type | Description |
|---|---|---|
| id | string | |
| status | object | |
| inputs | array | Array of processed input metadata, populated at enqueue from the media probe. |
| outputs | array | Output file records, populated on completion |
| output_format | string | Output format as submitted — the value is stored verbatim, so a job created with `jpg` or `MP4` reads back exactly that way (validation is case/alias-insensitive; canonical values are mp4, webm, mov, |
| job_type | string | Discriminator — transcode and transcribe jobs share this resource shape and both appear in `GET /v1/transcodes` listings (there is no job_type filter). Transcribe rows additionally carry `media_url`. |
| billable_minutes | number | Billable minutes, metered per second on input duration (a 19-second job bills 0.3167). Not an integer. |
| duration_seconds | number | While the job is pending/processing: the billable input span (sum of input durations after trim options such as `-ss`/`-t`). Once completed: replaced by the measured duration of the OUTPUT file, which |
| processing_time_seconds | numbernull | Wall-clock processing time measured by the toolkit; null until completed |
| queue_position | integernull | Jobs waiting in the job's toolkit lane at acceptance, this one included: the accepting worker's queue length right after this job was enqueued, so 1 means it was next in line. Set once at acceptance a |
| lane | stringnull | The processing lane the job runs in. Jobs with many large inputs (more than five 4K frames' worth of pixels in total) go to `heavy`, a service with more memory. Otherwise, inputs longer than two minut |
| started_at | stringnull | When the toolkit began executing the job. Set as soon as encoding starts, so null means the job is still waiting in its lane and non-null with status `processing` means it is encoding now. If that sta |
| error_message | stringnull | Populated when status is `failed`, and also on user cancellation (`canceled` jobs carry "Job canceled by user") — do not treat non-null error_message alone as job failure. |
| error_category | string | Machine classification derived from error_message (generated column). Only meaningful when status is `failed`; jobs with no error carry `unknown`, never null. `processing_limit` is reserved for a job |
| completed_at | stringnull | Set on successful completion only — failed jobs keep this null |
| metadata | object | Job metadata object. Caller-supplied metadata from the create request is echoed under `metadata.user` (JSON object, max 8 KB serialized). The object also carries internal keys written by the service ( |
| ffmpeg_options | object | Final FFmpeg options used (audit trail) |
| output_url | stringnull | Populated when status = completed |
| created_at | string | |
| updated_at | string | |
| user_id | string | Internal user identifier resolved from API key |
| input_url | string | [DEPRECATED] Use inputs array instead |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/ffmpeg-micro-com/json-schema/ffmpeg-micro-com-transcode-schema.json",
"title": "Transcode",
"x-generated": "2026-10-30",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/ffmpeg-micro-com-openapi.yaml#/components/schemas/Transcode",
"type": "object",
"required": [
"id",
"status",
"output_format",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"status": {
"$ref": "#/$defs/TranscodeStatus"
},
"inputs": {
"type": "array",
"description": "Array of processed input metadata, populated at enqueue from the media probe.\n",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "GCS URL of the (possibly re-hosted) input"
},
"filename": {
"type": "string"
},
"duration": {
"type": "number",
"description": "Seconds; 0 for still images"
},
"format": {
"type": "string"
},
"size_bytes": {
"description": "File size in bytes, as a decimal string the way the media probe reports it (`\"991017\"`; `\"0\"` when the probe gave no size). Older jobs may carry an integer. Parse it as a number before doing arithmetic.\n",
"oneOf": [
{
"type": "integer"
},
{
"type": "string",
"pattern": "^[0-9]+$"
}
]
},
"downloadUrl": {
"type": "string",
"description": "Short-lived signed HTTPS URL for the input"
},
"options": {
"type": "array",
"items": {
"type": "object"
},
"description": "Per-input FFmpeg options as submitted"
}
}
}
},
"outputs": {
"type": "array",
"description": "Output file records, populated on completion",
"items": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "gs:// URL of the output file"
},
"filename": {
"type": "string"
},
"size_bytes": {
"type": "integer"
},
"format": {
"type": "string"
}
}
}
},
"output_format": {
"type": "string",
"description": "Output format as submitted — the value is stored verbatim, so a job created with `jpg` or `MP4` reads back exactly that way (validation is case/alias-insensitive; canonical values are mp4, webm, mov, avi, mp3, m4a, aac, wav, ogg, opus, flac, jpeg, png, gif, webp). Rows with `job_type: transcribe` carry `srt`.\n"
},
"job_type": {
"type": "string",
"enum": [
"transcode",
"transcribe"
],
"description": "Discriminator — transcode and transcribe jobs share this resource shape and both appear in `GET /v1/transcodes` listings (there is no job_type filter). Transcribe rows additionally carry `media_url`.\n"
},
"billable_minutes": {
"type": "number",
"description": "Billable minutes, metered per second on input duration (a 19-second job bills 0.3167). Not an integer.\n"
},
"duration_seconds": {
"type": "number",
"description": "While the job is pending/processing: the billable input span (sum of input durations after trim options such as `-ss`/`-t`). Once completed: replaced by the measured duration of the OUTPUT file, which can differ from the input span (e.g. loops run longer). Billing always uses the input-side value.\n"
},
"processing_time_seconds": {
"type": [
"number",
"null"
],
"description": "Wall-clock processing time measured by the toolkit; null until completed"
},
"queue_position": {
"type": [
"integer",
"null"
],
"description": "Jobs waiting in the job's toolkit lane at acceptance, this one included: the accepting worker's queue length right after this job was enqueued, so 1 means it was next in line. Set once at acceptance and never updated: a rough \"how far back was I\", not a live counter. Once `started_at` is set the job is no longer waiting, whatever this says. Null on jobs accepted before the field existed, or when the toolkit's accept response carried no queue length.\n"
},
"lane": {
"type": [
"string",
"null"
],
"enum": [
"short",
"long",
"heavy",
null
],
"description": "The processing lane the job runs in. Jobs with many large inputs (more than five 4K frames' worth of pixels in total) go to `heavy`, a service with more memory. Otherwise, inputs longer than two minutes (by probed length or requested output span) go to `long`; everything else is `short`. Each lane is a separate service, so nothing in one can delay a job in another. Null on jobs accepted before lanes existed.\n"
},
"started_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "When the toolkit began executing the job. Set as soon as encoding starts, so null means the job is still waiting in its lane and non-null with status `processing` means it is encoding now. If that start signal was missed, it is filled from the completion or failure report. `started_at - created_at` is submission-to-start and includes the gateway's own download and probe before dispatch, so it is an upper bound on queue wait, not the wait itself.\n"
},
"error_message": {
"type": [
"string",
"null"
],
"description": "Populated when status is `failed`, and also on user cancellation (`canceled` jobs carry \"Job canceled by user\") — do not treat non-null error_message alone as job failure.\n"
},
"error_category": {
"type": "string",
"enum": [
"processing_limit",
"file_size",
"quota",
"upload",
"storage",
"validation",
"processing",
"transient",
"unknown"
],
"description": "Machine classification derived from error_message (generated column). Only meaningful when status is `failed`; jobs with no error carry `unknown`, never null. `processing_limit` is reserved for a job stopped at a per-job processing ceiling; no deployed release emits it yet (the ceiling ships separately).\n"
},
"completed_at": {
"type": [
"string",
"null"
],
"format": "date-time",
"description": "Set on successful completion only — failed jobs keep this null"
},
"metadata": {
"type": "object",
"description": "Job metadata object. Caller-supplied metadata from the create request is echoed under `metadata.user` (JSON object, max 8 KB serialized). The object also carries internal keys written by the service (e.g. preset details, request origin, download token for the anonymous \"Try It\" flow) — treat keys other than `user` as opaque and unstable.\n",
"properties": {
"user": {
"type": "object"
}
}
},
"ffmpeg_options": {
"type": "object",
"description": "Final FFmpeg options used (audit trail)",
"properties": {
"source": {
"type": "string",
"enum": [
"preset",
"raw_options",
"virtual_options",
"defaults"
],
"description": "How the options were derived. `raw_options`: the caller's `options`, sanitized. `virtual_options`: the caller's `options` included a virtual option (for example `@text-overlay`) that the gateway expanded. `preset`: a named preset. `defaults`: neither options nor a preset was given.\n"
},
"options": {
"type": "array",
"description": "The normalized option list handed to FFmpeg, in order.",
"items": {
"type": "object",
"required": [
"option"
],
"properties": {
"option": {
"type": "string",
"description": "FFmpeg flag (e.g. `-c:v`, `-crf`, `-f`)"
},
"argument": {
"oneOf": [
{
"type": "string"
},
{
"type": "number"
}
],
"description": "Flag value. Omitted (never null) for flag-only options (`-an`, `-vn`, `-shortest`) and whenever the caller sent null, so a bare flag serializes without one.\n"
}
}
}
},
"preset": {
"type": [
"object",
"null"
]
}
}
},
"output_url": {
"type": [
"string",
"null"
],
"description": "Populated when status = completed"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"user_id": {
"type": "string",
"description": "Internal user identifier resolved from API key"
},
"input_url": {
"type": "string",
"deprecated": true,
"description": "[DEPRECATED] Use inputs array instead"
}
},
"$defs": {
"TranscodeStatus": {
"type": "string",
"enum": [
"pending",
"processing",
"completed",
"failed",
"canceled"
],
"description": "Job lifecycle: `pending` (created, awaiting pickup) → `processing` → `completed` | `failed`; a user cancellation sets `canceled` (US spelling). Note there is no `queued` status — new jobs start as `pending`.\n"
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/ffmpeg-micro-com-transcode"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.