Send many requests at once, answered later on each model's batch price.
A batch is many requests sent at once and answered later, on the model's :batch entry — its batch price. It is billed once, when it ends, on what it used.
| Method | Path | Billed | Does |
|---|---|---|---|
POST | /v1/batches | at the end | submits a batch |
GET | /v1/batches | free | lists your batches, newest first |
GET | /v1/batches/{id} | free | polls one — its results once completed |
DELETE | /v1/batches/{id} | free | deletes a batch that has ended |
Every route takes an API key: Authorization: Bearer $OPENDUNES_API_KEY.
curl https://opendunes.com/v1/batches \
-H "Authorization: Bearer $OPENDUNES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "/v1/chat/completions",
"model": "anthropic/claude-sonnet-5",
"requests": [
{
"custom_id": "ticket-0001",
"body": {
"messages": [{ "role": "user", "content": "Summarise this ticket in one sentence: …" }]
}
},
{
"custom_id": "ticket-0002",
"body": {
"messages": [{ "role": "user", "content": "Summarise this ticket in one sentence: …" }]
}
}
]
}'| Field | Description |
|---|---|
endpoint | Required. /v1/chat/completions, /v1/responses, /v1/messages or /v1/embeddings — the shape every body is in |
model | Required. A model with a :batch entry; the batch runs on it on its own |
requests | Required. Each has a unique custom_id and a body in the endpoint's shape |
provider | Optional. provider.only is the only routing a batch takes |
completion_window | 24h, the only window |
What a batch refuses, before anything is sent:
:batch entry (400)"stream": true in any body — a batch never streamsA request that fails its checks after the batch was accepted fails the whole batch.
The answer is 202, with the batch's id:
{
"id": "a2d1a3f0-5b6c-4d7e-8f90-a1b2c3d4e5f6",
"object": "batch",
"endpoint": "/v1/chat/completions",
"model": "anthropic/claude-sonnet-5",
"completion_window": "24h",
"status": "validating",
"created_at": 1782097200,
"finalized_at": null,
"request_counts": { "total": 2, "completed": 0, "failed": 0 },
"usage": null,
"results": null,
"error": null
}curl https://opendunes.com/v1/batches/a2d1a3f0-5b6c-4d7e-8f90-a1b2c3d4e5f6 \
-H "Authorization: Bearer $OPENDUNES_API_KEY"status moves validating → in_progress → finalizing → completed; it may also end failed, expired or cancelled. Once completed, results holds one item per request, matched by custom_id, each with either a response or an error:
{
"id": "batch_req_123",
"custom_id": "ticket-0001",
"response": {
"status_code": 200,
"body": {
"id": "gen-batch-1782097200-a1b2c3d4e5f6a7b8c9d0",
"object": "chat.completion",
"model": "anthropic/claude-sonnet-5",
"choices": [
{ "index": 0, "message": { "role": "assistant", "content": "…" }, "finish_reason": "stop" }
]
}
},
"error": null
}The batch's usage.cost is its charge in DA, taken once when it completes. A failed batch charges nothing.
GET /v1/batches lists your own batches, newest first, without results. It takes limit (1 to 100, default 20), after (the previous page's last_id) and status[] (one or more statuses), and answers { "object": "list", "data": [ … ], "first_id", "last_id", "has_more" }.
DELETE /v1/batches/{id} deletes a batch that has ended and its results, and answers { "id": "…", "object": "batch", "deletion": { "opendunes": "deleted" } }. A batch still running answers 409. Its charge and receipt stay on your account.
A batch that is not yours, or does not exist, is a 404.