Manage & monitor batches
Once you’ve submitted a batch you keep a single batch_id (bat_…) for its whole life. This guide
covers the endpoints you use to track, inspect, and manage that batch after creation: listing your
batches, polling status, drilling into per-item results, cancelling or retrying, auditing webhook
deliveries, and pulling the finalized billing receipt.
All endpoints are under https://api.batchrouter.com/v1 and require
Authorization: Bearer br_live_…. For the complete request and response schemas, see the
interactive API reference.
List your batches
Section titled “List your batches”GET /v1/batches returns a paginated list of batches in the authenticated workspace, newest first.
Filter with status, page with cursor, and size with limit (1–100, default 20).
Each entry is a BatchSummary: id, status, item_count, created_at, sla_deadline,
quote_id, routing_mode, and sla_tier. The response also carries next_cursor (pass it back as
cursor to page) and workspace_total_count.
curl https://api.batchrouter.com/v1/batches?status=processing&limit=20 \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch( "https://api.batchrouter.com/v1/batches?status=processing&limit=20", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` } },);const { data, next_cursor } = await res.json();import os, requests
res = requests.get( "https://api.batchrouter.com/v1/batches", params={"status": "processing", "limit": 20}, headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)data = res.json()["data"]To walk every page, keep calling with cursor=<next_cursor> until next_cursor is null.
Get batch status
Section titled “Get batch status”GET /v1/batches/{batchId} returns the full BatchDetail for one batch: everything in the summary
plus error, completed_at, lane_statuses (per-lane status for the internal provider/model
executions running under your single batch_id), and an optional embedded billing_receipt.
Poll this endpoint until status reaches a terminal value. The lifecycle runs
pending → queued → routing → dispatched → processing → completing → completed; the terminal
failure states are failed, cancelled, and expired. See the
status lifecycle reference for what each state means.
curl https://api.batchrouter.com/v1/batches/bat_123 \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/batches/bat_123", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const batch = await res.json();console.log(batch.status, batch.sla_deadline);import os, requests
res = requests.get( "https://api.batchrouter.com/v1/batches/bat_123", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)batch = res.json()print(batch["status"], batch["sla_deadline"])Prefer event-driven delivery over tight polling. Configure a webhook so BatchRouter notifies you the moment a batch completes, and poll only as a fallback.
Inspect per-item status
Section titled “Inspect per-item status”GET /v1/batches/{batchId}/items returns per-item status, errors, and output previews — useful when
a batch is partially complete or some items failed and you want to know exactly which ones.
Filter with status (pending, processing, completed, failed), and page with cursor and
limit (1–500, default 100). Each item carries customer_item_id (the id you assigned on submit),
status, and sequence_number.
curl "https://api.batchrouter.com/v1/batches/bat_123/items?status=failed&limit=100" \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch( "https://api.batchrouter.com/v1/batches/bat_123/items?status=failed&limit=100", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` } },);const { items, next_cursor } = await res.json();import os, requests
res = requests.get( "https://api.batchrouter.com/v1/batches/bat_123/items", params={"status": "failed", "limit": 100}, headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)items = res.json()["items"]Cancel a batch
Section titled “Cancel a batch”POST /v1/batches/{batchId}/cancel requests cancellation and returns the updated BatchDetail. You
can include an optional reason (up to 500 characters) in the JSON body.
Retry a failed batch
Section titled “Retry a failed batch”POST /v1/batches/{batchId}/retry Beta re-queues a batch for
another dispatch attempt. It is only available when status is failed or expired; calling it on
a batch in any other state returns a 409. On success it returns the updated BatchDetail with the
batch back in the active lifecycle.
curl -X POST https://api.batchrouter.com/v1/batches/bat_123/cancel \ -H "Authorization: Bearer $BATCHROUTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"reason":"superseded by a re-run"}'const res = await fetch("https://api.batchrouter.com/v1/batches/bat_123/cancel", { method: "POST", headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ reason: "superseded by a re-run" }),});const batch = await res.json();import os, requests
res = requests.post( "https://api.batchrouter.com/v1/batches/bat_123/cancel", json={"reason": "superseded by a re-run"}, headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)batch = res.json()curl -X POST https://api.batchrouter.com/v1/batches/bat_123/retry \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/batches/bat_123/retry", { method: "POST", headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const batch = await res.json();import os, requests
res = requests.post( "https://api.batchrouter.com/v1/batches/bat_123/retry", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)batch = res.json()Review webhook deliveries
Section titled “Review webhook deliveries”If you configured a webhook (per-batch, or the org default via
PUT /v1/auth/account/delivery-webhook), GET /v1/batches/{batchId}/webhooks shows you exactly how
delivery is going. It returns the customer-visible delivery status, retry state, last failure
details, and persisted delivery events for the batch.
The response (BatchWebhooksResponse) has three top-level fields: batch_id, a data array of
delivery records, and an events array of delivery events. Each delivery in data includes:
urlandstatus— the destination and current state (pending,delivering,succeeded,failed,dead_lettered)attempt_count,last_attempt_at,next_attempt_at— retry bookkeepinglast_response_statusandlast_error— why the most recent attempt failed, if it did
curl https://api.batchrouter.com/v1/batches/bat_123/webhooks \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/batches/bat_123/webhooks", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const { data, events } = await res.json();import os, requests
res = requests.get( "https://api.batchrouter.com/v1/batches/bat_123/webhooks", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)deliveries = res.json()["data"]Audit the billing receipt
Section titled “Audit the billing receipt”Once a batch settles, GET /v1/batches/{batchId}/billing-receipt returns the finalized
BatchBillingReceipt. Final cost is settled from actual provider token usage, so the receipt is the
authoritative record of what you were charged. It includes:
final_settled_price,provider_subtotal, andbatchrouter_fee- the credit settlement:
credit_reserved,credit_charged,credit_released settled_atprovider_lanes— the quote lanes that actually ran (with the quote-time data/privacy proof for each)rejected_lanes— non-selected lanes, each with its rejection receipt
All money values are objects of the form { "currency": "usd", "amount": "1.50" } (a decimal string).
curl https://api.batchrouter.com/v1/batches/bat_123/billing-receipt \ -H "Authorization: Bearer $BATCHROUTER_API_KEY"const res = await fetch("https://api.batchrouter.com/v1/batches/bat_123/billing-receipt", { headers: { Authorization: `Bearer ${process.env.BATCHROUTER_API_KEY}` },});const receipt = await res.json();console.log(receipt.final_settled_price.amount);import os, requests
res = requests.get( "https://api.batchrouter.com/v1/batches/bat_123/billing-receipt", headers={"Authorization": f"Bearer {os.environ['BATCHROUTER_API_KEY']}"},)receipt = res.json()print(receipt["final_settled_price"]["amount"])