Skip to content
Create a key

Paste a key to use it in the examples on these pages. The key stays in this browser tab. These pages never send it anywhere.

Separate the voices of a video

separate_audioPOST/v1/audio-separationsBeta

Starts splitting the sound of a video into its voices or everything else, and returns the tool run that makes the audio file.

Beta. This endpoint is supported and can gain new fields. If a change would break your code, we tell you before it takes effect and list it in the changelog.

About

Call this to get the voices of a video without the music and noise (keep vocals), or the music and noise without the voices (keep instrumental). The result is an MP3 file. The video must have sound and be at most 60 minutes long, and a video whose file was deleted to free up storage cannot be separated: these are checked before anything is used. The call answers 202 at once with the run, queued, and a Location to follow; read it with get_tool_run (GET /v1/tool-runs/{toolRunId}) (with ?wait= to hold the request) until it is done, then download the file from its downloadUrl. A separation takes a few minutes. Always send an Idempotency-Key, the same one on every retry: a retry of the same request returns the same run and never uses a second tool run.

Example use

A creator who wants to reuse the music of a video, without the voices, starts a separation with keep instrumental. It follows the run with get_tool_run (GET /v1/tool-runs/{toolRunId}) until the MP3 is ready to download.

Endpoint

Code
POST https://api.gpt-video.com/v1/audio-separations
  • Scope spend.
  • Rate limit 10 requests a minute for each key and 20 for each account, shared by every spend call. See rate limits.
  • Idempotency-Key is required.
  • It starts work that runs on its own. The answer comes back before the work is done.

Parameters

Headers

NameTypeRequiredDescription
Idempotency-KeystringRequiredThis operation spends, so the key is required. Create it once, before the request, and send the same key on every retry. From 1 to 255 visible characters, such as a UUID. See idempotency.

Body

NameTypeRequiredDescription
sourceAssetIdstringRequiredThe video whose sound to separate, as complete_upload (POST /v1/uploads/{uploadId}/complete) or list_assets (GET /v1/assets) returned it. It starts with ast_. Matches ^ast_n?[0-9a-f]{20}$.
keepstringRequiredvocals keeps the voices, instrumental keeps everything else. One of vocals, instrumental.

Send only the fields listed here. Any other field is refused with UNKNOWN_PARAMETER.

Request

Keep the voices of a video.

Request example
# Create the key once. Send this same key again if you retry this request.
IDEMPOTENCY_KEY=$(uuidgen)
curl -X POST "https://api.gpt-video.com/v1/audio-separations" \
  -H "Authorization: Bearer $GPT_VIDEO_API_KEY" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
    "keep": "vocals"
  }'
// Create the key once. Send this same key again if you retry this request.
const idempotencyKey = crypto.randomUUID();
const res = await fetch("https://api.gpt-video.com/v1/audio-separations", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.GPT_VIDEO_API_KEY}`,
    "Idempotency-Key": idempotencyKey,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
    "keep": "vocals"
  }),
});
const data = await res.json();
console.log(data);
import os
import uuid

import requests

# Create the key once. Send this same key again if you retry this request.
idempotency_key = str(uuid.uuid4())
r = requests.post(
    "https://api.gpt-video.com/v1/audio-separations",
    headers={
        "Authorization": f"Bearer {os.environ['GPT_VIDEO_API_KEY']}",
        "Idempotency-Key": idempotency_key,
    },
    json={
        "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
        "keep": "vocals"
    },
)
data = r.json()
print(data)
{
  "method": "tools/call",
  "params": {
    "name": "separate_audio",
    "arguments": {
      "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
      "keep": "vocals",
      "confirm": true,
      "idempotencyKey": "REPLACE-WITH-A-NEW-UUID-FOR-THIS-CALL"
    }
  }
}

Response

A successful call answers HTTP 202. Returns a Tool run object in toolRun.

Fields to check

NameTypeDescription
toolRun.idstringThe tool run id. It starts with run_.
toolRun.statusstringqueued and running are still working; done and failed are final.
toolRun.file.downloadUrlstring or nullA link to download the file, on a read of a finished run; null otherwise.
toolRun.file.downloadUrlExpiresAtstring or nullAn ISO 8601 time in UTC.
toolRun.jobIdstring or nullThe job that carries out the run, to follow with get_job (GET /v1/jobs/{jobId}); null once it is gone.
paidWithstring or nullWho paid for this request: plan is the credits or the daily allowance of the account's plan, api_bonus is the API bonus. null when this request paid nothing, because the same work was already running. A retry with the same Idempotency-Key says who paid the first time.

Response example

  • Location: https://api.gpt-video.com/v1/tool-runs/run_5e8a1c3f7d2b4096a1e4
HTTP 202
{
  "toolRun": {
    "id": "run_5e8a1c3f7d2b4096a1e4",
    "tool": "audio_separation",
    "status": "queued",
    "progress": 0,
    "errorMessage": null,
    "file": null,
    "ideas": null,
    "jobId": "job_2c7f9e1a4d6b48035f9e",
    "createdAt": "2026-09-01T11:00:00.000Z",
    "finishedAt": null,
    "voiceover": null,
    "separation": {
      "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
      "keep": "vocals"
    },
    "brainstorm": null
  },
  "paidWith": "plan"
}
All response fields
NameTypeRequiredDescription
toolRunTool run objectRequiredDescribed in Tool run object.
paidWithstring or nullRequiredWho paid for this request: plan is the credits or the daily allowance of the account's plan, api_bonus is the API bonus. null when this request paid nothing, because the same work was already running. A retry with the same Idempotency-Key says who paid the first time. One of plan, api_bonus.
More examples

A video with no sound

POST /v1/audio-separations

Request body
{
  "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
  "keep": "vocals"
}
HTTP 409
{
  "error": {
    "code": "CONFLICT",
    "message": "This video has no sound to separate.",
    "requestId": "req_8d1f4b7e0a3c6e9b2d5f8a17"
  }
}

A video that is too long

POST /v1/audio-separations

Request body
{
  "sourceAssetId": "ast_3f9a1c7e5b2d4086a1c4",
  "keep": "instrumental"
}
HTTP 409
{
  "error": {
    "code": "CONFLICT",
    "message": "Audio separation works on videos up to 60 minutes long. Cut the video first, or upload a shorter one.",
    "requestId": "req_1b5e9c3a7f0d2e6b8a4c1f59"
  }
}

A video that does not exist

POST /v1/audio-separations

Request body
{
  "sourceAssetId": "ast_0b1e5c9d3a7f40628e2d",
  "keep": "vocals"
}
HTTP 404
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Asset ast_0b1e5c9d3a7f40628e2d not found",
    "hint": "Check the id. An id that belongs to another account is not found either.",
    "requestId": "req_5c9a3e7b1d4f8a2c6e0b3d71"
  }
}

Errors

CodeStatusWhenWhat to do
INSUFFICIENT_CREDITS402See the error reference.Stop and tell the user.
PLAN_REQUIRED402See the error reference.Stop and tell the user.
NOT_FOUND404A video that does not existChange the request, then send it again.
CONFLICT409A video with no soundRead the resource again, then decide. Do not send the same request again.
DAILY_LIMIT_REACHED429See the error reference.Stop until the limit resets at 00:00 UTC.

Every call can also answer these errors. VALIDATION_FAILED, UNKNOWN_PARAMETER, IDEMPOTENCY_KEY_REQUIRED, UNAUTHORIZED, SCOPE_MISSING, IDEMPOTENCY_IN_PROGRESS, PAYLOAD_TOO_LARGE, IDEMPOTENCY_KEY_REUSED, RATE_LIMITED, INTERNAL, UNAVAILABLE.

Cost

Uses one tool run of the plan's daily allowance, which resets at 00:00 UTC. When the API bonus pays, it also uses one bonus credit. Nothing is returned if the run fails.

  • Paid by the API bonus, it uses 1 bonus credit.
  • When the API bonus pays, an account can run 10 tools a day.
  • See API pricing for who pays first.

Questions

What happens if my request times out and I send it again?

Send it again with the same Idempotency-Key. You get the same run back and no second tool run is used from the daily allowance. A new key starts a new run.

Is anything used when the video cannot be separated?

No. A video with no sound, longer than 60 minutes or whose file was deleted answers CONFLICT before the run starts, and no tool run is used.

View as Markdown