# Message batches

Message batches that stay in progress until you cancel them, with results as JSONL and ended batches ready to read in two scenarios.

A message batch queues many Messages requests under one id and reads their results back as JSONL. Create a batch, cancel it and read its results, then load a scenario that holds an ended batch with real results:

```bash
A=(-H 'x-api-key: sk-ant-placeholder' -H 'anthropic-version: 2023-06-01' -H 'content-type: application/json')
curl -s "${A[@]}" "$RYSTIC_URL/v1/messages/batches" -d '{"requests":[{"custom_id":"a","params":{"model":"claude-haiku-4-5-20251001","max_tokens":32,"messages":[{"role":"user","content":"Hi"}]}},{"custom_id":"b","params":{"model":"claude-haiku-4-5-20251001","max_tokens":32,"messages":[{"role":"user","content":"Yo"}]}}]}' | jq -c '{id, processing_status}'
# -> {"id":"msgbatch_000000000000000000000001","processing_status":"in_progress"}
curl -s "${A[@]}" -X POST "$RYSTIC_URL/v1/messages/batches/msgbatch_000000000000000000000001/cancel" | jq -c '{processing_status}'
# -> {"processing_status":"canceling"}
curl -s "${A[@]}" "$RYSTIC_URL/v1/messages/batches/msgbatch_000000000000000000000001" | jq -c '{processing_status, request_counts}'
# -> {"processing_status":"ended","request_counts":{"canceled":2,"errored":0,"expired":0,"processing":0,"succeeded":0}}
curl -s "${A[@]}" "$RYSTIC_URL/v1/messages/batches/msgbatch_000000000000000000000001/results" | jq -c '[.custom_id, .result.type]'
# -> ["a","canceled"]
# -> ["b","canceled"]
curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"anthropic_batch_queue"}'
curl -s "${A[@]}" "$RYSTIC_URL/v1/messages/batches/msgbatch_01QueueEnded00000001/results" | jq -c '[.custom_id, .result.type]'
# -> ["eval-0001","succeeded"]
# -> ["eval-0002","succeeded"]
# -> ["eval-0003","succeeded"]
# -> ["eval-0004","errored"]
```

### The lifecycle

A created batch's `processing_status` is `in_progress`, with `expires_at` 24 hours later. Its `ended_at`, `cancel_initiated_at`, `archived_at` and `results_url` read `null` until set.

**Differs from the Claude API:** a batch you create never finishes by itself. It stays `in_progress` until you cancel it.

Canceling a batch returns its `processing_status` as `canceling`. The next read shows it `ended`, with every request counted `canceled` and a `results_url`. `DELETE` removes an ended batch, and returns 400 `invalid_request_error` for one still in progress.

### Results

`GET /v1/messages/batches/{message_batch_id}/results` returns `application/x-jsonl`, one line per `custom_id`. Each line's result is `succeeded`, `errored`, `canceled` or `expired`.

To read results other than cancellations, load one of these scenarios:

| Scenario | Its batches |
|---|---|
| `anthropic_batch_queue` | one in progress, one canceling and one ended |
| `anthropic_batch_archive` | three ended, one of them archived, with succeeded, errored and expired results |

---

Source: https://www.rystic.ai/docs/simulators/anthropic/features/message-batches · Markdown: https://www.rystic.ai/docs/simulators/anthropic/features/message-batches.md
