---
title: "Run one analysis route over up to 20 URLs in a single call"
method: POST
path: "/v1/batch"
tags: ["Batch"]
---

# Run one analysis route over up to 20 URLs in a single call

`POST /v1/batch`

## Request

- Base URL: `https://audiolab.tools`
- URL: `https://audiolab.tools/v1/batch`
- Auth: HTTP bearer

One route over up to 20 sources in a single call: same engine, same metering as
the single routes. Each item counts as one call plus its bytes, and a rate or
quota stop ends the loop and is reported on the item where it fired. Provide urls
and/or objectPaths, max 20 combined.

## Request body

- object
  - `urls` string[]: Public http(s) URLs to audio files.
  - `objectPaths` string[]: Storage objects minted via /api/upload-url under this key's key/<keyHash>/ namespace, for local files with no public URL. Readable for about an hour, so a second question about the same file needs no re-upload, then swept.
  - `endpoint` 'mixlab/analyze' | 'mixlab/check-target' | 'mixlab/timeseries' | 'mixlab/spectrum' | 'voicelab/qa' | 'voicelab/segments' | 'signallab' | 'signallab/index': Which analysis route to run for every URL.
  - `args` object: Optional route-specific extras (e.g. target, waveformPoints), applied to every URL.
  - `name` string: Optional session name; stored on every item's event (meta.batch) so history can group the run.

## Response `200`

Batch processed. Individual URLs can still have failed; check each item's `ok`.

- BatchResult
  - `endpoint` string, required: The analysis route that ran.
  - `count` integer, required: Processed items; shorter than the request when a rate or quota stop fired.
  - `batchId` string: Unique id for this run; every item's event carries it in meta.batch.
  - `name` string: The session name, when provided.
  - `summary` object: Aggregate over the results, so callers need not re-crunch 20 payloads.
    - `ok` integer
    - `failed` integer
    - `avgLufs` number
    - `loudest` object
      - `ref` string
      - `lufs` number
    - `quietest` object
      - `ref` string
      - `lufs` number
    - `overTruePeakCount` integer
    - `totalDurationSec` number
    - `passed` integer: check-target only.
    - `passRate` number: check-target only, 0..1.
    - `headline` string: One-line human/agent-readable overview.
  - `results` object[], required
    - `url` string, uri: Present for url items.
    - `objectPath` string: Present for objectPath items.
    - `ok` boolean, required
    - `data` object: On ok=true, the same shape as the corresponding single-call response (e.g. AnalysisResult for mixlab/analyze).
    - `error` string: On ok=false, why this URL failed (fetch, decode budget, rate or quota stop).

## Other responses

- `400`: Malformed request, a URL we could not use, or a parameter that is not valid. Codes: url_not_allowed, url_fetch_failed, invalid_json, missing_input, invalid_parameter, batch_too_large, upload_not_found.
- `401`: Invalid or revoked API key. /v1/batch and /v1/usage always need a key; the analysis routes also run without one, as a small keyless trial. Codes: invalid_api_key.
- `429`: Too many requests this minute. See Retry-After. Codes: rate_limited.
- `500`: Something went wrong on our side. The details are logged and never sent to you. Codes: storage_unavailable, analysis_error.

---

[API](https://skmtc.dev/audiolab/apis/audiolab-api.md) · [All operations](https://skmtc.dev/audiolab/apis/audiolab-api/llms.txt) · [OpenAPI document](https://skmtc.dev/audiolab/apis/audiolab-api/revisions/69ff81f4f4ba?raw)
