Quickstart
Upload, create a job, wait for results, download. Get your first separated tracks in about five minutes.
Before you start
You need an API key from the dashboard. Send it on every request as the x-api-key header. See Authentication.
1. Upload your media
Uploading starts at POST /assets. The server looks at fileSize and tells you whether to do a single-shot upload (files up to 100 MiB) or a resumable multipart upload (files over 100 MiB). Either way you get back an assetId. The maximum file size is 6 GB; a larger fileSize is rejected with 413 FILE_TOO_LARGE. See Audio formats for supported source files and output format values.
# 1. Create an asset — start the upload
curl -X POST "https://api.netflix.developers.gaudiolab.io/v1/assets" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{ "fileName": "movie_reel_01.wav", "fileSize": 18400000 }'
# Response (small file → single-shot upload):
# {
# "assetId": "as_7f3a9c",
# "status": "awaiting_upload",
# "upload": { "mode": "single", "url": "https://upload..." }
# }# 2. Upload the bytes to the pre-signed URL
curl -X PUT "https://upload..." \
--upload-file movie_reel_01.wav2. Create a job
A single POST /jobs can request several tracks at once. Reference each model by its family-prefixed alias (for example dme_dialogue_v1). DME models take an optional processing tier rather than a strict quality rank. Supported tiers are model-specific and listed on the Models page; compare premium and standard on representative samples when the choice matters. Non-DME models each produce one track. Use the alias prefix to choose the family, for example stem_vocal_v1 for multi-stem vocal separation or karaoke_vocal_v1 for the karaoke-style vocal/accompaniment split. You can mix families in one job.
# Create a job — mix DME tracks and stems in one request
curl -X POST "https://api.netflix.developers.gaudiolab.io/v1/jobs" \
-H "x-api-key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"assetId": "as_7f3a9c",
"targets": [
{ "model": "dme_dialogue_v1", "tier": "premium", "formats": ["wav"] },
{ "model": "dme_music_v1", "tier": "standard", "formats": ["wav"] },
{ "model": "dme_effects_v1", "formats": ["wav"] },
{ "model": "karaoke_vocal_v1", "formats": ["wav"] },
{ "model": "stem_bass_v1", "formats": ["wav"] }
],
"webhookUrl": "https://my.app/hooks/separation"
}'
# tier is optional; supported tiers are listed per DME model in GET /models.
# Standard can be preferable for some material.
# Non-DME aliases each produce one track; request several aliases for several tracks.
# Response: { "jobId": "job_91b2e0", "status": "processing", "targets": [...] }3. Collect the results
In production, set a webhookUrl to be notified as each target finishes. If you poll instead, call GET /jobs/{jobId} about every 10 seconds until the status is completed or failed.
# 4. Poll for results (if you're not using a webhook; ~every 10s)
curl "https://api.netflix.developers.gaudiolab.io/v1/jobs/job_91b2e0" \
-H "x-api-key: $API_KEY"
# When complete:
# {
# "jobId": "job_91b2e0",
# "status": "completed",
# "linksExpireAt": "2026-06-10T12:00:00Z",
# "targets": [
# { "model": "dme_dialogue_v1", "status": "completed",
# "output": { "dialogue": { "wav": "https://cdn/.../dialogue.wav" } } }
# ]
# }Download links expire
Output links are valid for 48 hours. Re-fetching the job refreshes them, but we recommend downloading and storing the files in your own storage as soon as a target completes.
Full example (Python)
import os, time, requests
BASE = "https://api.netflix.developers.gaudiolab.io/v1"
HEADERS = {"x-api-key": os.environ["API_KEY"]}
# 1) Create the asset
size = os.path.getsize("movie.wav")
asset = requests.post(f"{BASE}/assets", headers=HEADERS,
json={"fileName": "movie.wav", "fileSize": size}).json()
# 2) Upload the bytes (single mode shown)
with open("movie.wav", "rb") as f:
requests.put(asset["upload"]["url"], data=f)
# 3) Create the job
job = requests.post(f"{BASE}/jobs", headers=HEADERS, json={
"assetId": asset["assetId"],
"targets": [
{"model": "dme_dialogue_v1", "tier": "premium", "formats": ["wav"]},
{"model": "dme_music_v1", "tier": "standard", "formats": ["wav"]},
{"model": "karaoke_vocal_v1", "formats": ["wav"]},
{"model": "stem_bass_v1", "formats": ["wav"]},
],
}).json()
# 4) Poll until done
while True:
result = requests.get(f"{BASE}/jobs/{job['jobId']}", headers=HEADERS).json()
if result["status"] in ("completed", "failed"):
break
time.sleep(10)
for t in result["targets"]:
print(t["model"], t["status"], t.get("output"))