Overview
Webhooks allow you to receive HTTP notifications when jobs complete, eliminating the need for polling.Setup
Include awebhook_url in your job request:
Webhook Payload
When a job completes, Tornado sends aPOST 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
Whenenable_progress_webhook: true is set, you’ll receive updates at each processing stage:
To enable progress webhooks:
Webhook Behavior
Handling Webhooks
Node.js (Express)
Python (Flask)
Best Practices
Respond Quickly
Respond Quickly
Return a 2xx status promptly. The per-job outcome sender uses a 10-second request timeout; queue longer processing asynchronously.
Verify Source
Verify Source
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.Idempotency
Idempotency
Handle duplicate webhooks gracefully. Store the job_id and check for duplicates before processing.
Retry Logic
Retry Logic
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 thewebhook_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.