Skip to main content
GET
/
jobs
/
{id}
Get Job Status
curl --request GET \
  --url https://api.tornadoapi.io/jobs/{id} \
  --header 'x-api-key: <x-api-key>'
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
  "status": "Completed",
  "s3_url": "https://cdn.example.com/videos/video.mp4?X-Amz-Algorithm=...",
  "subtitle_url": null,
  "error": null,
  "step": "Finished",
  "title": "Rick Astley - Never Gonna Give You Up",
  "description": "The official video for Never Gonna Give You Up...",
  "release_date": "2009-10-25T00:00:00Z",
  "download_speed_mbps": 45.2,
  "upload_speed_mbps": 120.5,
  "download_duration_ms": 3200,
  "mux_duration_ms": 1500,
  "upload_duration_ms": 2100,
  "total_duration_ms": 8050,
  "file_size": 52428800,
  "native_video_codec": "avc1",
  "native_audio_codec": "mp4a",
  "download_strategy": "native",
  "download_retries": 1,
  "upload_retries": 0,
  "queue_wait_ms": 450,
  "requested_quality": "best",
  "actual_quality": "1080p",
  "created_at": 1705507200000,
  "finished_at": 1705507260000
}

Overview

Retrieves the current status of a download job. When completed, includes a presigned S3 URL for downloading the file.

Header Parameters

x-api-key
string
required
Your API key for authentication

Path Parameters

id
string
required
The job UUID returned from POST /jobs

Response

id
string
Job UUID
url
string
Original source URL
status
string
Job status: Pending, Processing, Completed, Failed, Warning, or Skipped
s3_url
string
Presigned download URL (only when Completed)
subtitle_url
string
Presigned URL for subtitles (if available)
error
string
Error message (when Failed, Warning, or Skipped)
error_type
string
Error classification (when Failed, Warning, or Skipped): error for technical failures (rate limits, bot detection, connection issues), warning for content issues (private video, members-only, geo-blocked, audio-only Spotify episodes)
step
string
Current processing step: Queued, Downloading, Muxing, Uploading, Finished
title
string
Video title (only present for completed jobs fetched from database)
description
string
Video/episode description from the source platform (only present for completed jobs)
release_date
string
Release or upload date. Spotify: exact publish date. YouTube: upload date (midnight UTC). ISO 8601 format.
folder
string
S3 folder prefix if provided at job creation
batch_id
string
Batch UUID if this job is part of a batch (Spotify show or YouTube playlist)
download_speed_mbps
number
Download speed in MB/s (only present for completed jobs)
upload_speed_mbps
number
Upload speed in MB/s (only present for completed jobs)
extract_duration_ms
integer
Metadata extraction duration in milliseconds (only present for completed jobs)
download_duration_ms
integer
Download stage duration in milliseconds (only present for completed jobs)
mux_duration_ms
integer
Mux (FFmpeg) stage duration in milliseconds (only present for completed jobs)
upload_duration_ms
integer
Upload stage duration in milliseconds (only present for completed jobs)
total_duration_ms
integer
Total pipeline duration from pop to completion in milliseconds (only present for completed jobs)
precheck_duration_ms
integer
YouTube API pre-check duration in milliseconds (only present when pre-check was performed)
io_wait_ms
integer
Time spent waiting for IO semaphore in milliseconds (only present for completed jobs)
cpu_wait_ms
integer
Time spent waiting for CPU semaphore in milliseconds (only present for completed jobs)
upload_wait_ms
integer
Time spent waiting for upload semaphore in milliseconds (only present for completed jobs)
subtitle_duration_ms
integer
Subtitle download duration in milliseconds (only present for completed jobs with subtitles)
file_move_ms
integer
File move duration in milliseconds (only present for completed jobs)
file_size
integer
File size in bytes (only present for completed jobs)
native_video_codec
string
Video codec of the source stream (e.g., "avc1", "vp9", "av01"). Only present for completed jobs.
native_audio_codec
string
Audio codec of the source stream (e.g., "mp4a", "opus"). Only present for completed jobs.
download_strategy
string
Download strategy used: native, ytdlp, cascade. Only present for completed jobs.
cascade_total_attempts
integer
Total download attempts across all strategies (only present for completed jobs)
download_retries
integer
Number of download retries attempted (only present for completed jobs)
upload_retries
integer
Number of upload retries attempted (only present for completed jobs)
queue_wait_ms
integer
Time spent waiting in queue in milliseconds (only present for completed jobs)
requested_quality
string
Quality requested by the user (only present for completed jobs)
actual_quality
string
Actual quality of the downloaded video (only present for completed jobs)
webhook_status
string
Webhook delivery status (only present when webhook_url was set)
created_at
integer
Creation timestamp in milliseconds since epoch
finished_at
integer
Completion timestamp in milliseconds since epoch (only present for completed jobs)

Examples

curl -X GET "https://api.tornadoapi.io/jobs/550e8400-e29b-41d4-a716-446655440000" \
  -H "x-api-key: sk_your_api_key"

Status Values

StatusDescription
PendingJob is in queue, waiting to be processed
ProcessingJob is actively being downloaded/processed
CompletedJob finished successfully
FailedJob encountered a technical error
WarningJob failed due to a content issue (private video, members-only, geo-blocked, unavailable)
SkippedJob was skipped because the content cannot be processed (e.g. audio-only Spotify episodes with Widevine DRM)

Processing Steps

StepDescription
QueuedWaiting in queue
DownloadingDownloading video/audio streams
MuxingCombining streams with FFmpeg
UploadingUploading to S3
FinishedComplete

Polling Example

import requests
import time

def wait_for_job(job_id, api_key, timeout=600):
    start = time.time()

    while time.time() - start < timeout:
        response = requests.get(
            f"https://api.tornadoapi.io/jobs/{job_id}",
            headers={"x-api-key": api_key}
        )
        data = response.json()

        print(f"Status: {data['status']} - {data.get('step', 'N/A')}")

        if data["status"] == "Completed":
            return data["s3_url"]
        elif data["status"] == "Failed":
            raise Exception(f"Job failed: {data['error']}")
        elif data["status"] == "Skipped":
            print(f"Job skipped: {data['error']}")
            return None

        time.sleep(3)

    raise Exception("Timeout waiting for job")

Success Response

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://youtube.com/watch?v=dQw4w9WgXcQ",
  "status": "Completed",
  "s3_url": "https://cdn.example.com/videos/video.mp4?X-Amz-Algorithm=...",
  "subtitle_url": null,
  "error": null,
  "step": "Finished",
  "title": "Rick Astley - Never Gonna Give You Up",
  "description": "The official video for Never Gonna Give You Up...",
  "release_date": "2009-10-25T00:00:00Z",
  "download_speed_mbps": 45.2,
  "upload_speed_mbps": 120.5,
  "download_duration_ms": 3200,
  "mux_duration_ms": 1500,
  "upload_duration_ms": 2100,
  "total_duration_ms": 8050,
  "file_size": 52428800,
  "native_video_codec": "avc1",
  "native_audio_codec": "mp4a",
  "download_strategy": "native",
  "download_retries": 1,
  "upload_retries": 0,
  "queue_wait_ms": 450,
  "requested_quality": "best",
  "actual_quality": "1080p",
  "created_at": 1705507200000,
  "finished_at": 1705507260000
}

Error Responses

null
The presigned s3_url and subtitle_url are valid for 24 hours. Download the files before they expire.
Performance and metadata fields (title, description, release_date, folder, batch_id, download_speed_mbps, upload_speed_mbps, extract_duration_ms, download_duration_ms, mux_duration_ms, upload_duration_ms, total_duration_ms, precheck_duration_ms, io_wait_ms, cpu_wait_ms, upload_wait_ms, subtitle_duration_ms, file_move_ms, file_size, native_video_codec, native_audio_codec, download_strategy, cascade_total_attempts, download_retries, upload_retries, queue_wait_ms, requested_quality, actual_quality, webhook_status, finished_at) are only present for completed/failed jobs that have been persisted to the database. Active jobs (Pending/Processing) return only the base fields (id, url, status, s3_url, subtitle_url, error, error_type, step, created_at). Fields with no value are omitted from the response.
Completed jobs also echo back the original request parameters (format, video_codec, audio_codec, audio_bitrate, video_quality, filename, audio_only, download_subtitles, download_thumbnail, quality_preset, max_resolution, clip_start, clip_end, live_recording, live_from_start, max_duration, wait_for_video, enable_progress_webhook). These are omitted when null.