Skip to main content
POST
/
jobs
Create Job
curl --request POST \
  --url https://api.tornadoapi.io/jobs \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <x-api-key>' \
  --data '
{
  "url": "<string>",
  "format": "<string>",
  "video_codec": "<string>",
  "audio_codec": "<string>",
  "audio_bitrate": "<string>",
  "video_quality": 123,
  "filename": "<string>",
  "folder": "<string>",
  "webhook_url": "<string>",
  "audio_only": true,
  "download_subtitles": true,
  "download_thumbnail": true,
  "quality_preset": "<string>",
  "max_resolution": "<string>",
  "clip_start": "<string>",
  "clip_end": "<string>",
  "live_recording": true,
  "live_from_start": true,
  "max_duration": 123,
  "wait_for_video": true,
  "enable_progress_webhook": true,
  "storage": {},
  "paused": true
}
'
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000"
}

Overview

Creates a new download job. For single videos, returns a job_id. For Spotify shows, automatically creates a batch and returns a batch_id with all episode job IDs.

Header Parameters

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

Request

url
string
required
The video or show URL to download
format
string
Output container format. Video: mp4, mkv, webm, mov. Audio: m4a, mp3, ogg, opus. Default: mp4 (or m4a when audio_only is true)
video_codec
string
Video codec: copy (no re-encode), h264, h265, vp9. Default: copy
audio_codec
string
Audio codec: copy (no re-encode), aac, opus, mp3. Default: copy with automatic fallback to aac if incompatible
audio_bitrate
string
Audio bitrate when transcoding: 64k, 128k, 192k, 256k, 320k. Default: 192k
video_quality
integer
Video quality CRF (0-51, lower = better quality). Only used when video_codec is not copy. Default: 23
filename
string
Custom filename (without extension). Max 255 characters. Cannot contain .., /, \, or null bytes.
folder
string
S3 folder prefix for organizing files. Max 200 characters. Cannot contain .., start with / or \, or be empty/whitespace-only.
webhook_url
string
URL to receive completion notification via POST request.
audio_only
boolean
default:"false"
Extract audio track only. Outputs m4a (native AAC, no re-encoding) by default. Set format to mp3, ogg, or opus for other audio formats. Supports audio_codec and audio_bitrate for transcoding control.
download_subtitles
boolean
default:"false"
Download subtitles if available. Returns subtitle URL in job response.
download_thumbnail
boolean
default:"false"
Download video thumbnail. Returns thumbnail URL in job response.
quality_preset
string
Quality preset that overrides video_quality. Options: highest, high, medium, low, lowest.
max_resolution
string
Maximum video resolution. Options: best (default), 2160 (4K), 1440, 1080, 720, 480, 360. Works correctly for both horizontal and vertical (Shorts) videos by checking the shorter dimension.
clip_start
string
Start timestamp for video clipping. Format: HH:MM:SS, MM:SS, or seconds (e.g., 00:01:30 or 90).
clip_end
string
End timestamp for video clipping. Format: HH:MM:SS, MM:SS, or seconds (e.g., 00:05:00 or 300). Must be greater than clip_start.
live_recording
boolean
default:"false"
Enable live stream recording mode. Auto-detected for live URLs.
live_from_start
boolean
default:"false"
For live streams: record from the beginning (VOD mode) instead of the live point.
max_duration
integer
Maximum recording duration in seconds. Recommended for live streams as a safety cap. Example: 7200 for 2 hours.
wait_for_video
boolean
default:"false"
Wait for scheduled/upcoming streams to start before downloading.
enable_progress_webhook
boolean
default:"false"
Enable progress webhooks during processing. Sends updates at each stage: downloading, muxing, uploading.
storage
object
Inline storage credentials. Required for marketplace users (RapidAPI, Apify, Zyla). Optional for direct API users (overrides pre-configured storage). Supports 4 providers via the provider field. See Inline Storage examples below.
paused
boolean
default:"false"
For Spotify show batches only. Creates the batch in paused mode: jobs are not enqueued for processing immediately. Use PATCH /batch/{id}/jobs to rename episodes, then POST /batch/{id}/start to launch.

Single Job Response

job_id
string
UUID of the created job
Response
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000"
}

Batch Response (Spotify Shows)

When the URL is a Spotify show, a batch is created automatically:
batch_id
string
UUID of the batch job
total_episodes
integer
Number of episodes in the show
paused
boolean
Whether the batch was created in paused mode
episodes
array
List of episode details with job IDs, URLs, titles, descriptions, and release dates
episode_jobs
array
List of job IDs for each episode (legacy field)
Response (default mode)
{
  "batch_id": "550e8400-e29b-41d4-a716-446655440001",
  "total_episodes": 142,
  "paused": false,
  "episodes": [
    {
      "job_id": "uuid-1",
      "url": "https://open.spotify.com/episode/abc",
      "title": "Episode 1 - Introduction",
      "description": "In this episode we cover...",
      "release_date": "2024-01-15"
    },
    {
      "job_id": "uuid-2",
      "url": "https://open.spotify.com/episode/def",
      "title": "Episode 2 - Deep Dive",
      "description": "A deep dive into...",
      "release_date": "2024-01-22"
    }
  ],
  "episode_jobs": ["uuid-1", "uuid-2"]
}
Response (paused mode)
{
  "batch_id": "550e8400-e29b-41d4-a716-446655440001",
  "total_episodes": 142,
  "paused": true,
  "episodes": [
    {
      "job_id": "uuid-1",
      "url": "https://open.spotify.com/episode/abc",
      "title": "Episode 1 - Introduction"
    },
    {
      "job_id": "uuid-2",
      "url": "https://open.spotify.com/episode/def",
      "title": "Episode 2 - Deep Dive"
    }
  ],
  "episode_jobs": ["uuid-1", "uuid-2"]
}

Examples

curl -X POST "https://api.tornadoapi.io/jobs" \
  -H "x-api-key: sk_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "format": "mp4",
    "filename": "my-video"
  }'

Inline Storage

The storage field lets you provide cloud storage credentials directly in the request. This is required for marketplace users and optional for direct API users.
Inline storage credentials take priority over pre-configured storage, are validated before the job is accepted, and are never stored or logged.

Provider Fields

FieldTypeRequiredDescription
providerstringYesMust be "s3"
endpointstringYesS3 endpoint URL (e.g., https://s3.us-east-1.amazonaws.com, https://ACCOUNT.r2.cloudflarestorage.com)
bucketstringYesBucket name
regionstringYesAWS region (e.g., us-east-1) or auto for R2
access_keystringYesAccess key ID
secret_keystringYesSecret access key
folder_prefixstringNoFolder prefix (e.g., downloads/2024/)
base_folderstringNoTop-level folder (default: videos)

Success Response

{
  "job_id": "550e8400-e29b-41d4-a716-446655440000"
}

Batch Response (YouTube Playlists)

When the URL is a YouTube playlist, a batch is created automatically:
batch_id
string
UUID of the batch job
total_videos
integer
Number of videos in the playlist
video_jobs
array
List of job IDs for each video

Error Responses

{
  "error": "Folder name too long (max 200 characters)"
}

Notes

The 429 Too Many Requests and 503 Service Unavailable responses include a Retry-After header indicating how many seconds to wait before retrying.
Codec auto-correction: Incompatible codec/format combinations are automatically corrected to ensure valid output:
  • webm + h264 → video codec changed to vp9
  • webm + aac → audio codec changed to opus
  • ogg/opus + aac → audio codec changed to opus
  • mp3 + aac → audio codec changed to mp3
  • Setting audio_bitrate without audio_codec → audio codec defaults to aac
Invalid format values are silently replaced with mp4.