BatchRouter Docs

Submit a batch

Create a BatchRouter batch with POST /v1/batches — inline items or an uploaded file, a quote_id, an Idempotency-Key, routing, and privacy.

Creating a batch submits your work for asynchronous processing and reserves credits against a quote. You send POST /v1/batches with either inline items or a reference to an uploaded file, accept a quote_id, and pass an Idempotency-Key so retries are safe.

This is the deep version of step 3 of the quickstart. It assumes you already have an API key (see Authentication) and a quote (see Quotes and pricing).

Before you start

You need two things in hand:

  • An API key, sent as Authorization: Bearer br_live_…. Keep it server-side.
  • A quote_id (qlock_…) from POST /v1/quotes/model. The quote is free, pins your price estimate, and is required to reserve credits before dispatch.

Quotes are free; credits are charged at batch creation. If your workspace lacks credits you'll get a 402 — check GET /v1/auth/account and top up credits in the dashboard at https://batchrouter.com/app/billing.

Choose your input: inline items or a file

A batch's work comes from exactly one of two sources — they are mutually exclusive:

  • items — an inline array of batch items. Best for small-to-medium batches you assemble in memory.
  • input_file_id — a file_… id from a JSONL file you uploaded with POST /v1/files. Best for large batches or binary inputs. See JSONL format for the line shape and the file-based example below.

Send one or the other. Sending both — or neither — fails preflight with 400 and error.details.preflight.

The canonical item used across these docs:

{"customer_item_id":"item-1","operation":"responses","model":"gpt-5.4-mini","input":{"messages":[{"role":"user","content":"Summarize: BatchRouter routes batch-AI workloads across providers."}]}}

gpt-5.4-mini is a model id from the live catalog. List the models available to you now, with per-provider pricing and capacity, via GET /v1/catalog/models.

The Idempotency-Key header

POST /v1/batches requires an Idempotency-Key header — a unique string of 8–128 characters per logical submission. If a network error leaves you unsure whether the batch was created, retry with the same key: BatchRouter returns the original batch instead of creating a duplicate. Use a fresh key for each new batch (a UUID works well).

Request options

Beyond the input and quote_id, the body accepts these optional fields:

FieldValuesDefaultWhat it does
sla_tierstandard · flex · prioritystandardEvery batch has one 24h SLA. All three values are accepted for compatibility and treated as standard.
routing_modecheapest · sla_aware · public_only · edge_only · hybrid · privacy_constrainedcheapestHow BatchRouter selects a lane across providers.
privacy_tierstandard · confidential · restrictedstandardRoutes only to providers that declare the tier. confidential does not by itself require zero data retention (the router adds that check only under privacy_constrained); no built-in provider declares restricted.
webhook{ url, secret }—Per-batch completion callback; secret is 8+ chars and signs X-BatchRouter-Signature.
metadataobject—Arbitrary key/value pairs echoed back on the batch.

Set these consistently with the quote_id you're accepting. If you quoted with a given routing_mode and max_price, create with the same intent so the reserved estimate matches the routing decision.

Create a batch (inline items)

  1. Assemble your items and accept the quote.

  2. Send the request with an Idempotency-Key.

    curl -X POST https://api.batchrouter.com/v1/batches \
      -H "Authorization: Bearer $BATCHROUTER_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: $(uuidgen)" \
      -d '{
        "quote_id": "qlock_abc123",
        "sla_tier": "standard",
        "routing_mode": "cheapest",
        "privacy_tier": "standard",
        "items": [
          {
            "customer_item_id": "item-1",
            "operation": "responses",
            "model": "gpt-5.4-mini",
            "input": {
              "messages": [
                { "role": "user", "content": "Summarize: BatchRouter routes batch-AI workloads across providers." }
              ]
            }
          }
        ],
        "webhook": {
          "url": "https://example.com/hooks/batchrouter",
          "secret": "a-strong-shared-secret"
        },
        "metadata": { "project": "docs-demo" }
      }'
  3. Store batch.id (batch_…) and poll for completion. See Results.

Create a batch (file-based)

For large or binary inputs, upload a JSONL file first, then reference its file_id. Use input_file_id instead of items.

curl -X POST https://api.batchrouter.com/v1/batches \
  -H "Authorization: Bearer $BATCHROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "quote_id": "qlock_abc123",
    "input_file_id": "file_xyz789",
    "sla_tier": "standard",
    "routing_mode": "sla_aware"
  }'

The 202 response

A successful create returns 202 Accepted — the batch is queued for routing, not yet processed. The body wraps the batch summary (abridged here; the full batch object also carries sla_tier, routing_mode, pricing_estimate, file ids, and more):

{
  "batch": {
    "id": "batch_9f3c2a1b7e4d46c8a1b2c3d4e5f60718",
    "state": "priced",
    "counts": {
      "total": 1,
      "pending": 1,
      "running": 0,
      "completed": 0,
      "failed": 0,
      "canceled": 0
    },
    "created_at": "2026-06-18T10:00:00Z",
    "deadline_at": "2026-06-19T10:00:00Z"
  }
}
FieldMeaning
batch.idThe batch_… identifier you poll and fetch results with.
batch.stateThe lifecycle field. A new batch is priced, then advances queued → dispatching → running → finalizing → completed. See the status lifecycle.
batch.countsPer-item state counts: total, pending, running, completed, failed, and canceled. counts.total is the number of items accepted into the batch.
batch.created_atWhen the batch was created.
batch.deadline_atThe 24-hour SLA deadline by which the batch is expected to complete.

Replaying the same Idempotency-Key returns this same response rather than creating a second batch.

Errors

StatusCauseFix
400Preflight failed (bad JSONL, both/neither input, context window exceeded, unsafe webhook URL).Inspect error.details.preflight; see JSONL format.
401Missing or invalid key.Check your Authorization header — see Authentication.
402Insufficient credits.Check GET /v1/auth/account; top up credits in the dashboard at https://batchrouter.com/app/billing.
409Conflict (e.g. reused key on a different payload).Use a fresh Idempotency-Key for a new batch.

Next steps

On this page