On this page
- One or more uploads in state
ready. See Upload audio. - Credit for the longest input at $0.50 a minute. The quote below tells you before you commit.
Get a quote
/v1/jobs/quoteThe same arithmetic the submission does, on the same server-measured durations. Nothing is reserved. reasons[] carries every refusal the submission would raise, as sentences, so a half-ready set still gets a price and an explanation.
| Field | Type | Meaning |
|---|---|---|
| type | string | separation or dominant_separation. |
| inputs | string[] | Upload ids, in order. |
{
"type": "separation",
"inputs": ["upl_9f2c7a41d0e8"],
"billable_seconds": 612.4,
"total_duration_seconds": 612.4,
"estimated_cost_usd": 5.1,
"balance_usd": 20.0,
"sufficient_credit": true,
"can_submit": true,
"reasons": []
}
// Not submittable yet: every refusal comes back as a sentence, not an error.
{ "sufficient_credit": false, "can_submit": false,
"reasons": ["These uploads have not finished: upl_4a81be03c5f7",
"This job costs more than your balance. Add credit in the console."] }curl -X POST https://dueta.ai/v1/jobs/quote \
-H "Authorization: Bearer $DUETA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"type": "separation", "inputs": ["upl_9f2c7a41d0e8"]}'Run Duplex separation
/v1/jobs/separationOne recording in which two people talk over each other; two clean speaker tracks out. The whole chain runs inside this one job. Every step is on by default; switch one off in pipeline. Answers 201 with the job.
| Field | Type | Meaning |
|---|---|---|
| inputs | string[1] | Exactly one upload id. |
| pipeline | object | Optional. Step name to true or false; a missing key keeps its default. |
| callback_url | string | Optional. See Receive callbacks. |
| pipeline key | Default | Turn it off when |
|---|---|---|
| vocal_separation | true | Strips music and background before separating. Turn it off when the recording is already dry speech: a studio double-ender, a headset call, a meeting-room capture with nothing playing. |
| enhancement | true | Denoises each separated speaker track. Turn it off on already-clean studio material, where denoising can only risk softening a voice that had nothing wrong with it. |
| super_resolution | true | Writes 48 kHz output instead of 16 kHz. Turn it off when your pipeline consumes 16 kHz and would only resample the extra bandwidth away, as most ASR, telephony and VoIP paths do. |
| scoring | true | Estimates SI-SDR and reports it per track. Turn it off when you never read the number, such as an automated pipeline that keeps whatever comes back. |
A job configured for super_resolution writes 48 kHz output; a job configured without it writes 16 kHz. Multipart submission with files=@conversation.wav and one form field per toggle still works; it creates the upload for you.
curl -X POST https://dueta.ai/v1/jobs/separation \
-H "Authorization: Bearer $DUETA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": ["upl_9f2c7a41d0e8"],
"pipeline": {"super_resolution": false}}'
# -> 201, the job. Omit "pipeline" to run every step.Run Dominant separation
/v1/jobs/dominant-separationOne close-mic recording per speaker, 2 to 10 of them, made in the same room at the same time. Each comes back holding only its own speaker, plus one ambience track for the room. There is no pipeline on this product. Order matters: the first upload is the timeline the rest are aligned against.
| Field | Type | Meaning |
|---|---|---|
| inputs | string[2..10] | Upload ids, one per microphone, in alignment order. |
| callback_url | string | Optional. |
# 2-10 upload ids, one per microphone. The FIRST is the timeline the
# others are aligned against.
curl -X POST https://dueta.ai/v1/jobs/dominant-separation \
-H "Authorization: Bearer $DUETA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": ["upl_9f2c7a41d0e8", "upl_4a81be03c5f7"]}'Read the job back
/v1/jobs/{id}The creation response and every later read are the same shape. The price is frozen at creation: estimated_cost_usd is what you will be billed on success, whatever the worker reports.
{
"id": "0f9c1a7e-4b21-4d5a-9d0e-2c8b6a1f3e77",
"type": "separation",
"status": "queued",
"stage": "queued",
"progress": 0,
"eta_seconds": null,
"queue_position": 2,
"worker_alive": true,
"heartbeat_age_seconds": 3.2,
"pipeline": { "vocal_separation": true, "enhancement": true,
"super_resolution": false, "scoring": true },
"inputs": [
{ "index": 0, "upload_id": "upl_9f2c7a41d0e8", "filename": "conversation.wav",
"duration_seconds": 612.4, "stem": "conversation-00", "sample_rate": 48000,
"channels": 2, "state": "ready", "checksum_sha256": "b1946ac9..." }
],
"steps": [
{ "name": "vocal_separation", "state": "pending", "progress": 0 },
{ "name": "separation", "state": "pending", "progress": 0 },
{ "name": "enhancement", "state": "pending", "progress": 0 },
{ "name": "super_resolution", "state": "skipped", "progress": 0 },
{ "name": "si_sdr", "state": "pending", "progress": 0 }
],
"estimated_cost_seconds": 612.4,
"estimated_cost_usd": 5.1,
"billed_seconds": null,
"billed_usd": null,
"callback_secret": null,
"error": null,
"result": null,
"created_at": "2026-08-28T09:21:44Z",
"started_at": null,
"finished_at": null
}| Field | Type | Meaning |
|---|---|---|
| id | string | The job id used by every later route. |
| status | string | queued at creation. Lifecycle in Track a job. |
| inputs[] | object[] | One record per recording, naming its upload_id and reading its measurements through. |
| pipeline | object | The toggles this job runs, all four keys. Empty on a Dominant job. |
| estimated_cost_seconds | float | The longest input's duration: what the job is billed on. |
| estimated_cost_usd | float | Held now, charged on success, released on failure or cancel. |
| callback_secret | string | Only on the creation response, and only when a callback_url was sent. |
curl -H "Authorization: Bearer $DUETA_API_KEY" https://dueta.ai/v1/jobs/$JOB_ID |
jq '{status, stage, progress, queue_position, estimated_cost_usd, pipeline}'Cases
- 402
- Insufficient credit. No job exists and nothing was charged; the uploads are untouched. Top up and submit the same ids.
- 404
- An id in inputs is not one of your uploads.
- 409
- An input is not ready, or your email is unverified where verification is required.
- 400 count
separationtakes exactly 1 file;dominant-separationtakes 2 to 10.- 400 duration
- All inputs added together exceed the 2-hour cap. The quote reports the same sentence in
reasons[]first. - 400 take
- Dominant inputs must be one take: the longest may be at most 2× the shortest.
- 400 body
- Send
inputs;pipelinemust map step names to booleans. - 415
- A multipart part is video.
- 429
- 5 jobs already queued or running, 20 submissions in the last minute, or 20 unbilled (failed or canceled) jobs in the last hour.
Retry-Aftersays when to ask again. - 503
- The job queue could not be reached. Retry with backoff; nothing was held.
- Billing
- Billed on the longest input, never the sum. Billed equals quoted. A failed or canceled job is never charged. Accounts that have bought credit queue ahead of free ones.