CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
Batch Your Offline Claude Calls and Pay Half: The Message Batches API

Batch Your Offline Claude Calls and Pay Half: The Message Batches API

Chris Harper

2 min read

Aug 27, 2026 · 12:06 UTC

AI
Workflow
Best Practices
Developer Tools

TL;DR: The Anthropic Message Batches API processes up to 100K requests asynchronously at 50% of synchronous pricing, per Anthropic's published rates — the right default for eval runs, nightly reports, and bulk tagging, with a 24-hour maximum wait and no streaming.

Most Claude API workloads split into two populations: calls that need a real-time response, and calls that don't. The second population — evaluation runs against a test set, nightly document tagging, bulk classification — is running at full synchronous pricing even though nothing is actually waiting on the result. The Message Batches API exists for exactly this case.

Submitting a batch:

import anthropic, time

client = anthropic.Anthropic()

# Submit — up to 100K requests per batch; each follows the Messages API schema
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"doc-{i}",
            "params": {
                "model": "claude-sonnet-5",
                "max_tokens": 200,
                "messages": [{"role": "user", "content": f"Classify the sentiment of: {text}"}],
            },
        }
        for i, text in enumerate(texts)
    ]
)
print(f"Submitted batch {batch.id}. Status: {batch.processing_status}")

# Poll for completion (most batches finish in minutes; SLA is 24 hours)
while True:
    status = client.messages.batches.retrieve(batch.id)
    if status.processing_status == "ended":
        break
    time.sleep(60)

# Retrieve results
for result in client.messages.batches.results(batch.id):
    if result.result.type == "succeeded":
        print(result.custom_id, result.result.message.content[0].text)
    elif result.result.type == "errored":
        print(result.custom_id, "ERROR:", result.result.error)

When to use it:

  • Eval pipelines over a labeled test set: submit the whole set, retrieve results hours later
  • Nightly ingestion: summarize or tag new documents overnight, read results in the morning
  • Bulk classification at scale: 50K items in one API call, not 50K round trips

Limits — all real:

  • Results take up to 24 hours. Most batches finish in minutes to a few hours, but there's no timing SLA, so this isn't for anything time-sensitive.
  • No streaming. Poll or set a webhook; results don't come in incrementally.
  • No per-request adaptation. If Claude's response to request 3 should influence request 4, you can't do that within a single batch.
  • Results are stored for 29 days, then deleted.

Finding your biggest async opportunity: the /claude-api cost-optimize command added in Claude Code v2.1.247 (August 27, 2026) profiles your project's existing call patterns and flags high-frequency synchronous calls that look like batch candidates — a useful starting point before auditing manually.

Sources: Anthropic Message Batches API docs, Anthropic pricing — 50% batch discount, CloudZero: Claude pricing 2026, Claude Code v2.1.247 changelog