Skip to main content

Overview

Webhooks allow you to receive HTTP notifications when jobs complete, eliminating the need for polling.

Setup

Include a webhook_url in your job request:

Webhook Payload

When a job completes, Tornado sends a POST request to your webhook_url with a JSON payload. Here’s what your server will receive:

Job Started (Processing)

Sent when a worker picks up the job and begins processing:

Single Job Completion

s3_url/subtitle_url/thumbnail_url are generated the same way (and with the same 24h validity) as the s3_url field returned by GET /jobs/{id} — added 2026-07-08 so you don’t need a second API call just to get something downloadable. key/subtitle_key/thumbnail_key are unchanged and still sent, for backwards compatibility.

Job Failed

Sent when a job fails due to a technical error (bot detection, rate limit, connection issues). Not sent for content warnings (private/members-only/geo-blocked videos) — those are handled silently.

Job Skipped

Sent when a job is skipped because the content cannot be processed. This happens for audio-only Spotify episodes that are protected by Widevine DRM and have no video stream available. Skipped jobs are classified as warnings, not errors — they represent content limitations, not technical failures.
Batch completion accounts for completed, failed and skipped episodes. Skipped episodes have a separate counter; do not treat them as successful downloads.

Batch Completion

When all episodes in a batch are done:

Progress Webhooks

When enable_progress_webhook: true is set, you’ll receive updates at each processing stage:
Progress stages and percentages: To enable progress webhooks:

Webhook Behavior

Handling Webhooks

Node.js (Express)

Python (Flask)

Best Practices

Return a 2xx status promptly. The per-job outcome sender uses a 10-second request timeout; queue longer processing asynchronously.
When webhook signing is enabled for your key, verify X-Tornado-Signature against the exact raw request body before processing. Do not treat a missing signature as verified. See the signing contract for your configured webhook family.
Handle duplicate webhooks gracefully. Store the job_id and check for duplicates before processing.
Per-job outcome notifications use three total attempts by default (the initial attempt plus up to two retries). Transport errors, HTTP 5xx, 408 and 429 are retryable; other HTTP errors are not retried by this path. The attempt budget is configurable. Batch and organization-level notifications have separate delivery paths. Ensure your handler tolerates duplicates.

Testing Webhooks

Use a service like webhook.site or ngrok to test webhooks locally:

Delivery families and signing

This page describes the webhook_url supplied with a media job or batch. Its event types use names such as job_completed and batch_completed. Endpoints configured for an organization in the dashboard use their own event contract; do not rename one family’s events to match another. When enabled, the media-job signature header has the form t=<unix-seconds>,v1=<hex-hmac>. Verification must use the raw bytes received and reject timestamps outside your accepted replay window. Per-job outcome retries are signed at send time, so a repeated delivery can carry a new timestamp and signature. Inspect webhook_status, webhook_attempts and webhook_last_error on the job where available. A completed media job does not prove that your webhook endpoint accepted its notification.