CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
Cut Claude API Costs 50% on Any Async Workload: The Message Batches API in 20 Lines

Photo: Daniil Komov / Pexels

Cut Claude API Costs 50% on Any Async Workload: The Message Batches API in 20 Lines

Chris Harper

2 min read

Aug 12, 2026 · 12:05 UTC

AI
Workflow
Best Practices
Developer Tools

The Anthropic Message Batches API runs up to 100,000 Claude requests asynchronously at exactly 50% off standard token prices — submit, wait a few hours, retrieve.

Any workload that doesn't need instant results — nightly evaluations, document pipelines, offline enrichment, bulk code analysis — is paying double. The Message Batches API costs 50% less per token with zero quality difference.

How it works

You submit a list of MessageBatchRequest objects, each with a custom_id and the same parameters as a standard /messages call. Anthropic processes them asynchronously (typically 1-2 hours, max 24h) and makes results available via the batch id. No streaming, no webhooks — you poll for status or come back later.

import anthropic

client = anthropic.Anthropic()
docs = ["Article 1 text...", "Article 2 text...", "Article 3 text..."]

# Submit the batch
batch = client.messages.batches.create(
    requests=[
        {
            "custom_id": f"doc-{i}",
            "params": {
                "model": "claude-sonnet-5-20260801",
                "max_tokens": 256,
                "messages": [{"role": "user", "content": f"Summarize in 2 sentences: {docs[i]}"}]
            }
        }
        for i in range(len(docs))
    ]
)
print(f"Batch {batch.id} submitted — status: {batch.processing_status}")

Poll until complete:

import time

while True:
    status = client.messages.batches.retrieve(batch.id)
    if status.processing_status == "ended":
        break
    print(f"Still processing... ({status.request_counts.processing} remaining)")
    time.sleep(60)

# Retrieve and print 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[:120])
    else:
        print(result.custom_id, "FAILED:", result.result.error.type)

Cost math

A nightly pipeline summarizing 1,000 documents (2,000 input + 500 output tokens each) on Sonnet 5:

ApproachInputOutputTotal/dayAnnual
Synchronous$4.00$5.00$9.00$3,285
Batch API$2.00$2.50$4.50$1,642

Add prompt caching on a shared system prompt and the cached tokens cost another 90% less, pushing complex pipelines toward 65-70% total savings.

Best uses

Batch is ideal when latency doesn't matter: code analysis across a full repo at PR-merge time, generating descriptions for 10K embeddings, running eval suites against 1,000 test cases, nightly newsletter digests, classifying a backlog of support tickets.

Not for: real-time chat, streaming responses, any user-facing flow where waiting hours isn't acceptable.

Sources: Message Batches API — Claude Platform Docs · Anthropic Batch API: process thousands of prompts at 50% cost — CodeWords · Claude Batch API Tutorial — AI for Anything