POST /api/v1/batch
Submit a batch of jobs. All jobs are processed concurrently. A single batch.complete webhook fires when all jobs are done.
Endpoint
JSON only — file upload is not supported. Every job must use audio_url.
Body — two accepted shapes
Shape A: plain array
Shape B: object with webhook
Per-job fields
external_id is an arbitrary string (max 255 characters) used to map each job back to a track in your own system. It is echoed back in GET /api/v1/batch/{id}, GET /api/v1/jobs/{job_id}, and the job.complete webhook payload for each job.
Limits
- Minimum 1 job, maximum 20 jobs per request
- Rate limit check is pre-flight: if submitting N jobs would push any window over the limit, the entire batch is rejected with
429 before any jobs are created. See rate limit headers.
Response — 202 Accepted
GET /api/v1/batch/[id]
Poll for batch status and per-job results.
Endpoint
Batch status values
Per-job status
Each entry in jobs carries the same status and stage as
GET /jobs/{id}, derived identically — the two endpoints
never disagree about the same job.
processing is the normal state for several minutes after submission, and on a
large batch for considerably longer, since jobs queue behind one another. A
job in processing has not failed. failed is returned only when the
pipeline recorded a failure, and carries an error object saying which stage
and why.
Don’t treat “not yet complete” as failure. A 20-song batch can take 15 minutes
or more end to end, and individual jobs move through transcribing and
aligning on their own schedule. Wait for the batch to reach complete or
partial, or use the batch.complete webhook.
Response
downloads is only present on jobs where status === "complete" AND align_requested === true. Failed jobs and align=false jobs do not include it.
Examples
See the Batch Processing guide for patterns on handling partial failures and polling strategy.