Anthropic Batch API for JSON Processing: 50% Off, High Volume (2026 Guide)
The Anthropic Message Batches API processes up to 100,000 JSON requests asynchronously at 50% off standard pricing. Learn when to use it, how to structure JSONL payloads, handle malformed outputs, and build reliable batch JSON pipelines in 2026.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →This guide covers when to use the Batch API, how to structure JSONL payloads for JSON output, and what to do when batch responses contain malformed JSON.
Written by The JSON Medic.
What Is the Anthropic Message Batches API?
The Batch API accepts a JSONL file of message requests, processes them asynchronously on dedicated infrastructure, and returns a JSONL file with one result per request. You submit once and poll for completion — typical batches complete in under an hour for moderate volumes.
Key specs:- Up to 100,000 requests per batch
- 50% discount on input and output tokens (all Claude models)
- 29-day result retention window
- Asynchronous — no blocking on individual request latency
- Returns JSONL: one
{custom_id, result}object per line
When to Use Batch vs. Synchronous API
Use the Batch API when your workload meets three conditions:
- Latency tolerance — you don't need real-time responses. Batch jobs complete in minutes to hours.
- Volume — 50+ requests per job. The overhead of polling isn't worth it for small one-off requests.
- Cost sensitivity — the 50% discount adds up fast. At 10,000 requests/day, you cut your API cost in half.
- Bulk structured JSON extraction from text (extract product data, parse invoices, classify content)
- Dataset annotation at scale
- Evaluation harnesses running the same prompts against thousands of examples
- Nightly content pipelines generating multiple articles or summaries
- JSON schema validation and transformation on large datasets
- Real-time API response handling — use the standard Messages API
- Interactive tools — users won't wait for batch completion
- Fewer than 10–20 requests — overhead isn't worth it
How to Structure Batch JSON Payloads
The Batch API accepts JSONL — one JSON object per line. Each object has two fields:
{"custom_id": "req-001", "params": {"model": "claude-opus-5-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Extract the JSON fields..."}]}}
{"custom_id": "req-002", "params": {"model": "claude-opus-5-5", "max_tokens": 1024, "messages": [{"role": "user", "content": "Extract the JSON fields..."}]}}
custom_id — your internal identifier for the request. Use something that lets you correlate the batch output back to your source data (e.g., document-12345, product-sku-abc).
params — a standard Messages API call object. max_tokens is required. system goes as a top-level field in params, not inside messages.
Requesting JSON Output
To get structured JSON back from each batch request, instruct the model explicitly in the system prompt:
{
"custom_id": "extract-001",
"params": {
"model": "claude-sonnet-5",
"max_tokens": 512,
"system": "You are a JSON extraction API. Respond ONLY with a valid JSON object. No explanation, no markdown fences, no commentary.",
"messages": [
{
"role": "user",
"content": "Extract: name, price, category from: 'Blue wireless headphones, $49.99, Electronics'"
}
]
}
}
For strict schema enforcement, use Claude's tool use mode — define your JSON schema as a tool and force the model to call it:
{
"custom_id": "extract-002",
"params": {
"model": "claude-sonnet-5",
"max_tokens": 512,
"tools": [{
"name": "extract_product",
"description": "Extract product information",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"price": {"type": "number"},
"category": {"type": "string"}
},
"required": ["name", "price", "category"]
}
}],
"tool_choice": {"type": "tool", "name": "extract_product"},
"messages": [{"role": "user", "content": "..."}]
}
}
Tool use with tool_choice: {type: tool} forces a structured response — the model cannot produce free text. This is the most reliable approach for batch JSON extraction.
Reading Batch Results
Results come back as JSONL with one line per request:
{"id": "msg_abc", "custom_id": "extract-001", "result": {"type": "succeeded", "message": {"content": [{"type": "text", "text": "{\"name\": \"Blue wireless headphones\", \"price\": 49.99, \"category\": \"Electronics\"}"}]}}}
{"id": "msg_def", "custom_id": "extract-002", "result": {"type": "errored", "error": {"type": "overloaded_error"}}}
Each result has a type: succeeded, errored, or expired.
Parse results and route by type:
import json
with open("batch_results.jsonl") as f:
for line in f:
result = json.loads(line)
if result["result"]["type"] == "succeeded":
raw = result["result"]["message"]["content"][0]["text"]
try:
data = json.loads(raw)
process(data)
except json.JSONDecodeError:
# Malformed JSON — send to repair queue
repair_queue.append({"id": result["custom_id"], "raw": raw})
elif result["result"]["type"] == "errored":
retry_queue.append(result["custom_id"])
The Batch JSON Failure Pattern
This is where most batch pipelines break down: the model returns nearly-valid JSON that causes json.loads() to throw.
Common failure patterns at batch scale:
1. Markdown fences — the model wraps JSON in code blocks despite instructions:json
{"name": "product", "price": 49.99}
2. Trailing commas — valid in JavaScript, invalid in JSON:
{"name": "product", "price": 49.99,}
3. Single-quoted strings — the model uses Python-style quoting:
{'name': 'product', 'price': 49.99}
4. Truncated JSON — max_tokens cuts off mid-object:
{"name": "product", "price
5. Python literals — True, False, None instead of true, false, null
These failures are rare per request (maybe 1–3%) but at 10,000 requests, you're looking at 100–300 broken JSON objects.
Repairing Malformed Batch JSON
Don't discard failures or re-run them at full price. Repair them first.
For programmatic repair: use the jsonrepair library (JavaScript) or json-repair (Python). Both handle the common failure patterns above. For edge cases: paste broken JSON into AI JSONMedic's repair engine. The 16-stage pipeline handles truncated payloads, mixed quoting, and LLM-specific output patterns that rule-based libraries miss. For batch workflows, the AI repair endpoint can be integrated as a fallback after the rule-based library fails. Repair pipeline pattern:import json
import json_repair # pip install json-repair
def parse_with_fallback(raw: str) -> dict | None:
# 1. Try clean parse
try:
return json.loads(raw)
except json.JSONDecodeError:
pass
# 2. Try rule-based repair (fast, free)
try:
repaired = json_repair.repair_json(raw)
return json.loads(repaired)
except Exception:
pass
# 3. Log for AI repair (AI JSONMedic API or manual review)
return None
This three-stage approach handles ~95% of failures programmatically, with the remaining edge cases flagged for AI repair.
Cost Calculation: When Batch Pays Off
At standard pricing for claude-sonnet-5 (as of 2026):
- Standard: ~$3/MTok input, ~$15/MTok output
- Batch: ~$1.50/MTok input, ~$7.50/MTok output (50% off)
For a 10,000-request extraction job with ~500 input tokens and ~200 output tokens per request:
- Input: 5M tokens × $1.50 = $7.50
- Output: 2M tokens × $7.50 = $15.00
- Total: $22.50 vs $45.00 synchronous — $22.50 saved
At 100,000 requests, you save $225/run. If you run this daily, that's ~$82,000/year in API cost savings.
Batch API vs. Real-Time for JSON Extraction
| Factor | Batch API | Synchronous API |
|---|---|---|
| Cost | 50% off | Full price |
| Latency | Minutes to hours | Seconds |
| Max requests | 100,000/batch | Rate-limited per minute |
| Failure handling | Per-request result | Per-request error |
| Best for | Pipelines, ETL, labeling | Real-time features |
Practical Batch JSON Pipeline
A production pattern for bulk JSON extraction:
- Build JSONL — generate one
{custom_id, params}per source document - Submit batch — POST to
/v1/messages/batches - Poll for completion — check
processing_statusevery 60s (not 1s — respect rate limits) - Download results — GET from
results_urlwhenended - Parse with fallback —
json.loads()→json_repair→ AI repair queue - Process successes — write to your database or downstream system
- Re-queue failures — overloaded errors retry; malformed JSON goes to repair
Keep result files — the 29-day retention window gives you time to re-process, but your own storage is safer.
FAQ
How long does the Anthropic Batch API take to complete?
Most batches complete within 24 hours, though moderate-volume batches (a few thousand requests) typically finish in under an hour. Anthropic processes batches on dedicated infrastructure separate from the synchronous API.
Can I use the Batch API with Claude's tool use / function calling?
Yes. The params object is a standard Messages API call, so tools and tool_choice work normally. Forcing tool use with tool_choice: {type: tool} is the most reliable way to get schema-valid JSON from every batch request.
What happens to failed batch requests?
Failed requests return type: errored with an error type (e.g., overloaded_error, invalid_request_error). Overloaded errors are retryable. Invalid request errors need the payload fixed before re-submission. Track failures by custom_id to requeue them.
How do I handle truncated JSON in batch outputs?
Set max_tokens high enough for your expected output. For extraction tasks, calculate the maximum possible output size from your schema and add 20% headroom. If truncation still occurs, AI JSONMedic's repair engine handles truncated JSON by inferring the missing closing brackets and braces.
What's the difference between the Batch API and streaming?
Streaming delivers tokens in real-time as they're generated — useful for interactive UIs. The Batch API is fully asynchronous — you submit a job and check back later. They serve opposite use cases. Streaming adds latency UX; Batch cuts cost for offline workloads.
Is there a minimum batch size for the 50% discount?
No minimum. Even a single-request batch gets the 50% discount if submitted via the Batches API endpoint. In practice, the polling overhead makes batches worthwhile only at 50+ requests, but you get the discount at any size.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles