Search Documentation
Search across all documentation pages
Jobs

The Job object

A job represents a video transcoding operation. Each job takes an input video and produces one or more output renditions based on your specifications. Jobs support real-time progress tracking, delayed start with cost review, and streaming updates.

Base path: transcodely.v1.JobService Requires: X-Organization-ID header on all endpoints.


Attributes

AttributeTypeDescription
idstringUnique identifier. Prefixed with job_.
objectstringResource type discriminator. Always "job".
app_idstringParent app that owns the job. Prefixed with app_. Server-set.
input_urlstringInput video URL (when using direct URL mode).
input_originobject | nullInput origin reference (when using origin mode).
output_originobject | nullOutput origin reference.
statusenumCurrent job status. One of: pending, probing, awaiting_confirmation, processing, completed, failed, canceled, partial.
progressintegerOverall progress percentage (0–100).
priorityenumJob priority. One of: economy, standard, premium.
input_metadataobject | nullInput file metadata, populated after probing. See Input Metadata.
outputsarray of objectsOutput renditions. See The Output Object.
thumbnailsarray of objectsThumbnail specifications. See Thumbnails.
thumbnail_resultsarray of objectsGenerated thumbnail artifacts (url, mode, index), populated after the job completes.
total_estimated_costnumberEstimated cost in EUR. Present after probe completes.
total_actual_costnumberActual cost in EUR. Present after outputs complete.
error_codestringError code if failed.
error_messagestringError message if failed.
webhook_urlstringLegacy per-job webhook URL. Use webhook endpoints for signed event delivery.
metadataobjectCustom key-value metadata.
output_path_templatestring | nullJob-level output path template echoed from the request. null when not specified.
delayed_startbooleanWhether this job requires confirmation before encoding.
currencystringCurrency for cost fields (e.g., EUR).
executionobject | nullExecution timing and telemetry. See Execution Timing.
created_atstringISO 8601 timestamp.
updated_atstringISO 8601 timestamp.
probed_atstring | nullWhen probing completed.
started_atstring | nullWhen processing started.
completed_atstring | nullWhen job reached terminal state.
confirmed_atstring | nullWhen delayed start job was confirmed.
{
  "id": "job_a1b2c3d4e5f6",
  "object": "job",
  "app_id": "app_k1l2m3n4o5",
  "input_url": "gs://my-bucket/uploads/video.mp4",
  "input_origin": null,
  "output_origin": {
    "id": "ori_x9y8z7w6v5",
    "name": "Production GCS Bucket",
    "provider": "gcs",
    "path": "",
    "bucket": "acme-video-assets"
  },
  "status": "completed",
  "progress": 100,
  "priority": "standard",
  "input_metadata": {
    "format": "mp4",
    "duration_ms": 125000,
    "size_bytes": 132710400,
    "bit_rate": 8500000,
    "video": {
      "codec": "h264",
      "width": 1920,
      "height": 1080,
      "frame_rate": 30,
      "bit_rate": 8000000,
      "pixel_format": "yuv420p"
    },
    "audio": {
      "codec": "aac",
      "sample_rate": 48000,
      "channels": 2,
      "channel_layout": "stereo",
      "bit_rate": 128000
    }
  },
  "outputs": [
    {
      "id": "out_m1n2o3p4q5",
      "spec": {
        "type": "mp4",
        "video": [
          {
            "codec": "h264",
            "resolution": "1080p",
            "quality": "standard"
          }
        ]
      },
      "status": "completed",
      "progress": 100,
      "output_url": "gs://acme-video-assets/2025/02/28/output_h264_1080p.mp4",
      "output_size_bytes": 67108864
    }
  ],
  "total_estimated_cost": 0.85,
  "total_actual_cost": 0.82,
  "error_code": "",
  "error_message": "",
  "metadata": {
    "source": "upload-service",
    "user_id": "usr_a1b2c3d4e5"
  },
  "delayed_start": false,
  "currency": "EUR",
  "execution": {
    "probe_duration_ms": 1200,
    "encode_duration_ms": 45000,
    "total_duration_ms": 46200
  },
  "created_at": "2025-02-28T10:00:00Z",
  "updated_at": "2025-02-28T10:01:30Z",
  "probed_at": "2025-02-28T10:00:02Z",
  "started_at": "2025-02-28T10:00:03Z",
  "completed_at": "2025-02-28T10:01:30Z",
  "confirmed_at": null
}

Statuses

StatusDescription
pendingQueued and waiting to be processed.
probingAnalyzing the input file.
awaiting_confirmationDelayed start job paused for cost review. Call Confirm to proceed.
processingActively transcoding.
completedAll outputs completed successfully.
failedJob failed with an error.
canceledCanceled by the user.
partialSome outputs completed, others failed.

Priorities

Priority affects worker selection and scheduling order only — it has no effect on cost. Pricing is driven by codec, resolution, framerate, and quality tier (see the quality field on each video variant).

PriorityDescription
economySmaller workers, slower encoding.
standardBalanced worker sizing and scheduling. Default.
premiumLargest workers and highest scheduling priority for the fastest encoding.

Create a job

Create a new transcoding job with one or more output renditions.

POST /transcodely.v1.JobService/Create

Parameters

ParameterTypeRequiredDescription
input_urlstringOne ofDirect URL to the input video. Supported schemes: gs://, s3://, https://. Use this or input_origin_id, not both.
input_origin_idstringOne ofOrigin ID for the input source. The origin must have read permission.
input_pathstringNoPath within the input origin. Required when using input_origin_id.
output_origin_idstringConditionalOrigin ID for outputs. Must have write permission. Required unless managed is true.
outputsarrayYesOutput specifications (1–10 outputs). See Output Specification.
priorityenumNoeconomy, standard, or premium. Default: standard.
thumbnailsarrayNoThumbnail specifications (max 5). See Thumbnails.
webhook_urlstringNoLegacy per-job webhook URL. Register a webhook endpoint for signed event delivery instead.
idempotency_keystringNoIdempotency key (max 128 chars). Duplicate requests return the existing job.
metadataobjectNoCustom key-value pairs (max 20 entries, keys max 64 chars, values max 1024 chars).
delayed_startbooleanNoIf true, pauses after probing for cost review. Default: false.
output_path_templatestringNoOutput path template. Variables: {job_id}, {output_id}, {date}, {format}, {codec}, {resolution}, {quality}.
managedbooleanNoWrite outputs to managed hosting storage and create a video record. When true, output_origin_id is not required. Default: false.
app_idstringNoTarget app (app_ prefix). API-key callers may omit it (their key’s app is used); portal/JWT callers pass it to create in a specific app, or omit to select the org’s first active app.

Output specification

Each output can be defined inline or reference a preset. For the full reference of all output fields, see Output Specification.

FieldTypeRequiredDescription
typeenumYes*mp4, webm, mkv, mov, hls, dash, or adaptive. *Required unless using preset.
videoarrayYes*Video variants (1–20). *Required unless using preset.
audioarrayNoAudio tracks for streaming outputs. Max 8 tracks.
hlsobjectNoHLS-specific configuration.
dashobjectNoDASH-specific configuration.
segmentsobjectNoSegment configuration for streaming types.
path_templatestringNoPer-output path template (overrides job-level template).
presetstringNoPreset ID (e.g., pst_abc123) or slug (e.g., web_1080p_standard).
subtitle_tracksarrayNoSubtitle track configuration (max 8). See Subtitles.
drmobjectNoDRM encryption configuration. Streaming outputs only. See DRM & Encryption.
content_awareobjectNoContent-aware encoding. See Content-Aware Encoding.
encoding_modestringNo"fixed" (default, static CRF) or "auto" (input-aware constrained CRF that caps each variant’s bitrate to the input’s quality ceiling).
disable_audiobooleanNoProduce a video-only output, dropping audio entirely. Cannot be combined with audio[] tracks.
effective_path_templatestringRead-onlyResolved path template the worker renders against, after composing job-level and per-output templates. Response-only; ignored on requests.

VideoVariant

Each variant defines a single video encode rendition. For the full reference including codec-specific options (H264Options, H265Options, VP9Options, AV1Options) and HDR configuration, see Video Variants.

FieldTypeRequiredDescription
codecenumYesh264, h265, vp9, or av1.
resolutionenumNo480p, 720p, 1080p, 1440p, 2160p, or 4320p.
qualityenumNoeconomy, standard, or premium.
framerateintegerNoTarget frame rate. 0 = keep original.
widthintegerNoCustom width in pixels (128–7680).
heightintegerNoCustom height in pixels (128–4320).
bitrateintegerNoTarget bitrate in kbps (100–240000).
h264objectNoH.264-specific options.
h265objectNoH.265-specific options.
vp9objectNoVP9-specific options.
av1objectNoAV1-specific options.
hdrobjectNoHDR configuration.

Returns

Returns a Job object.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Create 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{
    "input_url": "gs://my-bucket/uploads/video.mp4",
    "output_origin_id": "ori_x9y8z7w6v5",
    "outputs": [
      {
        "type": "mp4",
        "video": [
          {"codec": "h264", "resolution": "1080p", "quality": "standard"}
        ]
      }
    ],
    "priority": "standard"
  }'
const job = await client.jobs.create({
  inputUrl: "gs://my-bucket/uploads/video.mp4",
  outputOriginId: "ori_x9y8z7w6v5",
  outputs: [
    {
      type: OutputFormat.MP4,
      video: [
        {
          codec: VideoCodec.H264,
          resolution: Resolution.RESOLUTION_1080P,
          quality: QualityTier.STANDARD,
        },
      ],
    },
  ],
  priority: JobPriority.STANDARD,
});
job = client.jobs.create(
    input_url="gs://my-bucket/uploads/video.mp4",
    output_origin_id="ori_x9y8z7w6v5",
    outputs=[{
        "type": "mp4",
        "video": [{"codec": "h264", "resolution": "1080p", "quality": "standard"}],
    }],
    priority="standard",
)
job, err := client.Jobs.Create(ctx, &transcodely.JobCreateParams{
    InputUrl:       "gs://my-bucket/uploads/video.mp4",
    OutputOriginId: proto.String("ori_x9y8z7w6v5"),
    Outputs: []*transcodely.OutputSpec{{
        Type: transcodely.OutputFormatMP4,
        Video: []*transcodely.VideoVariant{{
            Codec:      transcodely.VideoCodecH264,
            Resolution: transcodely.Resolution1080P,
            Quality:    transcodely.QualityTierStandard,
        }},
    }},
    Priority: transcodely.JobPriorityStandard,
})
{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "input_url": "gs://my-bucket/uploads/video.mp4",
    "input_origin": null,
    "output_origin": {
      "id": "ori_x9y8z7w6v5",
      "name": "Production GCS Bucket",
      "provider": "gcs",
      "path": "",
      "bucket": "acme-video-assets"
    },
    "status": "pending",
    "progress": 0,
    "priority": "standard",
    "input_metadata": null,
    "outputs": [],
    "metadata": {},
    "delayed_start": false,
    "currency": "EUR",
    "execution": null,
    "created_at": "2025-02-28T10:00:00Z",
    "updated_at": "2025-02-28T10:00:00Z"
  }
}

When managed is true, the response also includes a top-level video_id — the ID of the created managed-hosting video record. It is omitted for origin-based jobs.

Example: Adaptive streaming job

Package an HLS adaptive bitrate ladder — three H.264 renditions from 1080p down to 480p — in a single job.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Create 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{
    "input_url": "gs://my-bucket/uploads/video.mp4",
    "output_origin_id": "ori_x9y8z7w6v5",
    "outputs": [
      {
        "type": "hls",
        "video": [
          {"codec": "h264", "resolution": "1080p", "quality": "standard"},
          {"codec": "h264", "resolution": "720p", "quality": "standard"},
          {"codec": "h264", "resolution": "480p", "quality": "standard"}
        ],
        "segments": {"duration": 6}
      }
    ]
  }'
const job = await client.jobs.create({
  inputUrl: "gs://my-bucket/uploads/video.mp4",
  outputOriginId: "ori_x9y8z7w6v5",
  outputs: [
    {
      type: OutputFormat.HLS,
      video: [
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_1080P, quality: QualityTier.STANDARD },
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_720P, quality: QualityTier.STANDARD },
        { codec: VideoCodec.H264, resolution: Resolution.RESOLUTION_480P, quality: QualityTier.STANDARD },
      ],
      segments: { duration: 6 },
    },
  ],
});
job = client.jobs.create(
    input_url="gs://my-bucket/uploads/video.mp4",
    output_origin_id="ori_x9y8z7w6v5",
    outputs=[{
        "type": "hls",
        "video": [
            {"codec": "h264", "resolution": "1080p", "quality": "standard"},
            {"codec": "h264", "resolution": "720p", "quality": "standard"},
            {"codec": "h264", "resolution": "480p", "quality": "standard"},
        ],
        "segments": {"duration": 6},
    }],
)
job, err := client.Jobs.Create(ctx, &transcodely.JobCreateParams{
    InputUrl:       "gs://my-bucket/uploads/video.mp4",
    OutputOriginId: proto.String("ori_x9y8z7w6v5"),
    Outputs: []*transcodely.OutputSpec{{
        Type: transcodely.OutputFormatHLS,
        Video: []*transcodely.VideoVariant{
            {Codec: transcodely.VideoCodecH264, Resolution: transcodely.Resolution1080P, Quality: transcodely.QualityTierStandard},
            {Codec: transcodely.VideoCodecH264, Resolution: transcodely.Resolution720P, Quality: transcodely.QualityTierStandard},
            {Codec: transcodely.VideoCodecH264, Resolution: transcodely.Resolution480P, Quality: transcodely.QualityTierStandard},
        },
        Segments: &transcodely.SegmentConfig{Duration: proto.Int32(6)},
    }},
})

Retrieve a job

Retrieve a job by its ID.

POST /transcodely.v1.JobService/Get

Parameters

ParameterTypeRequiredDescription
idstringYesJob ID (e.g., job_a1b2c3d4e5f6).

Returns

Returns a Job object.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Get 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{"id": "job_a1b2c3d4e5f6"}'
const job = await client.jobs.get("job_a1b2c3d4e5f6");
job = client.jobs.get(id="job_a1b2c3d4e5f6")
job, err := client.Jobs.Get(ctx, "job_a1b2c3d4e5f6")
{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "object": "job",
    "app_id": "app_k1l2m3n4o5",
    "input_url": "gs://my-bucket/uploads/video.mp4",
    "input_origin": null,
    "output_origin": {
      "id": "ori_x9y8z7w6v5",
      "name": "Production GCS Bucket",
      "provider": "gcs",
      "path": "",
      "bucket": "acme-video-assets"
    },
    "status": "completed",
    "progress": 100,
    "priority": "standard",
    "input_metadata": {
      "format": "mp4",
      "duration_ms": 125000,
      "size_bytes": 132710400,
      "bit_rate": 8500000,
      "video": {
        "codec": "h264",
        "width": 1920,
        "height": 1080,
        "frame_rate": 30,
        "bit_rate": 8000000,
        "pixel_format": "yuv420p"
      },
      "audio": {
        "codec": "aac",
        "sample_rate": 48000,
        "channels": 2,
        "channel_layout": "stereo",
        "bit_rate": 128000
      }
    },
    "outputs": [
      {
        "id": "out_m1n2o3p4q5",
        "spec": {
          "type": "mp4",
          "video": [
            {
              "codec": "h264",
              "resolution": "1080p",
              "quality": "standard"
            }
          ]
        },
        "status": "completed",
        "progress": 100,
        "output_url": "gs://acme-video-assets/2025/02/28/output_h264_1080p.mp4",
        "output_size_bytes": 67108864
      }
    ],
    "total_estimated_cost": 0.85,
    "total_actual_cost": 0.82,
    "error_code": "",
    "error_message": "",
    "metadata": {
      "source": "upload-service",
      "user_id": "usr_a1b2c3d4e5"
    },
    "delayed_start": false,
    "currency": "EUR",
    "execution": {
      "probe_duration_ms": 1200,
      "encode_duration_ms": 45000,
      "total_duration_ms": 46200
    },
    "created_at": "2025-02-28T10:00:00Z",
    "updated_at": "2025-02-28T10:01:30Z",
    "probed_at": "2025-02-28T10:00:02Z",
    "started_at": "2025-02-28T10:00:03Z",
    "completed_at": "2025-02-28T10:01:30Z",
    "confirmed_at": null
  }
}

List jobs

List jobs with optional status filtering and pagination.

POST /transcodely.v1.JobService/List

Parameters

ParameterTypeRequiredDescription
statusenumNoFilter by status: pending, probing, processing, completed, failed, canceled, partial, awaiting_confirmation.
paginationobjectNolimit (default 20, max 100), plus cursor or offset (alternatives) for paging.
app_idstringNoFilter to a specific app (app_ prefix). API-key callers may omit it (their key’s app is used); portal/JWT callers pass it to list a specific app, or omit to return jobs across all apps in the org.

Returns

Returns a list of Job objects and pagination metadata.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/List 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{"status": "processing", "pagination": {"limit": 20}}'
const { items, nextCursor } = await client.jobs.list({
  status: JobStatus.PROCESSING,
  pagination: { limit: 20 },
});
response = client.jobs.list(status="processing", pagination={"limit": 20})
status := transcodely.JobStatusProcessing
iter := client.Jobs.List(ctx, &transcodely.JobListParams{
    Status:     &status,
    Pagination: &transcodely.PaginationRequest{Limit: 20},
})
defer iter.Close()

for iter.Next() {
    job := iter.Current()
    fmt.Printf("%s %s\n", job.GetId(), job.GetStatus())
}
if err := iter.Err(); err != nil {
    log.Fatal(err)
}
{
  "jobs": [
    {
      "id": "job_a1b2c3d4e5f6",
      "input_url": "gs://my-bucket/uploads/video.mp4",
      "status": "processing",
      "progress": 45,
      "priority": "standard",
      "created_at": "2025-02-28T10:00:00Z",
      "updated_at": "2025-02-28T10:02:00Z"
    },
    {
      "id": "job_b2c3d4e5f6g7",
      "input_url": "gs://my-bucket/uploads/interview.mov",
      "status": "processing",
      "progress": 78,
      "priority": "premium",
      "created_at": "2025-02-28T09:45:00Z",
      "updated_at": "2025-02-28T10:02:00Z"
    }
  ],
  "pagination": {
    "next_cursor": "eyJpZCI6ImpvYl9iMmMzZDRlNWY2ZzcifQ",
    "total_count": 42
  }
}

Cancel a job

Cancel a pending or running job. Completed outputs are preserved, in-progress outputs are stopped.

POST /transcodely.v1.JobService/Cancel

Parameters

ParameterTypeRequiredDescription
idstringYesJob ID.

Returns

Returns the Job object with status: "canceled".

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Cancel 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{"id": "job_a1b2c3d4e5f6"}'
const job = await client.jobs.cancel("job_a1b2c3d4e5f6");
job = client.jobs.cancel(id="job_a1b2c3d4e5f6")
job, err := client.Jobs.Cancel(ctx, "job_a1b2c3d4e5f6")
{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "input_url": "gs://my-bucket/uploads/video.mp4",
    "status": "canceled",
    "progress": 45,
    "priority": "standard",
    "created_at": "2025-02-28T10:00:00Z",
    "updated_at": "2025-02-28T10:05:00Z",
    "completed_at": "2025-02-28T10:05:00Z"
  }
}

Confirm a job

Confirm a delayed start job to begin encoding. Only valid when the job is in awaiting_confirmation status.

POST /transcodely.v1.JobService/Confirm

Parameters

ParameterTypeRequiredDescription
idstringYesJob ID.

Returns

Returns the Job object with status transitioning to processing.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Confirm 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{"id": "job_a1b2c3d4e5f6"}'
const job = await client.jobs.confirm("job_a1b2c3d4e5f6");
job = client.jobs.confirm(id="job_a1b2c3d4e5f6")
job, err := client.Jobs.Confirm(ctx, "job_a1b2c3d4e5f6")
{
  "job": {
    "id": "job_a1b2c3d4e5f6",
    "input_url": "gs://my-bucket/uploads/video.mp4",
    "status": "processing",
    "progress": 0,
    "priority": "standard",
    "delayed_start": true,
    "created_at": "2025-02-28T10:00:00Z",
    "updated_at": "2025-02-28T10:05:00Z",
    "confirmed_at": "2025-02-28T10:05:00Z"
  }
}

Watch a job

Stream real-time updates for a job. The server sends the current state immediately, then pushes updates as status or progress changes. The stream closes when the job reaches a terminal state.

This is a server-streaming RPC.

POST /transcodely.v1.JobService/Watch

Parameters

ParameterTypeRequiredDescription
idstringYesJob ID.

Stream events

Each message in the stream contains the current Job object, an event type, and a server timestamp.

EventDescription
snapshotInitial state sent on connection.
progressProgress percentage changed (debounced 200ms).
status_changeJob status transitioned.
completedTerminal state reached. Stream closes after this.
heartbeatKeepalive every 3 seconds.

Returns

Newline-delimited JSON stream of job state updates.

curl -X POST https://api.transcodely.com/transcodely.v1.JobService/Watch 
  -H "Authorization: Bearer ak_abc123" 
  -H "X-Organization-ID: org_f6g7h8i9j0" 
  -H "Content-Type: application/json" 
  -d '{"id": "job_a1b2c3d4e5f6"}'
for await (const event of client.jobs.watch("job_a1b2c3d4e5f6")) {
  console.log(`${event.event}: ${event.job?.progress}%`);
  if (event.event === WatchEventType.COMPLETED) break;
}
from transcodely import WatchEventType

for event in client.jobs.watch(id="job_a1b2c3d4e5f6"):
    print(f"{WatchEventType.Name(event.event)}: {event.job.progress}%")
    if event.event == WatchEventType.WATCH_EVENT_TYPE_COMPLETED:
        break
stream := client.Jobs.Watch(ctx, "job_a1b2c3d4e5f6")
defer stream.Close()
for stream.Next() {
    event := stream.Current()
    fmt.Printf("%s: %d%%\n", event.GetEvent(), event.GetJob().GetProgress())
    if event.GetEvent() == transcodely.WatchEventCompleted {
        break
    }
}
if err := stream.Err(); err != nil {
    log.Fatal(err)
}
{"result": {"job": {"id": "job_a1b2c3d4e5f6", "status": "processing", "progress": 45}, "event": "snapshot", "server_time": "2025-02-28T10:05:00Z"}}
{"result": {"job": {"id": "job_a1b2c3d4e5f6", "status": "processing", "progress": 85}, "event": "progress", "server_time": "2025-02-28T10:05:30Z"}}
{"result": {"job": {"id": "job_a1b2c3d4e5f6", "status": "completed", "progress": 100}, "event": "completed", "server_time": "2025-02-28T10:05:45Z"}}