Claude API cheatsheet
Claude API: Caching, batches and tokens
5 common Claude API tasks.
Cache a large prompt
Add top-level cache_control to cache the last cacheable block. Repeated requests with the same prefix are much cheaper.
response = client.messages.create(
model="claude-opus-5-5",
max_tokens=16000,
cache_control={"type": "ephemeral"},
system=large_document_text,
messages=[{"role": "user", "content": "Summarize the key points"}],
)
Check that caching works
If cache_read_input_tokens stays zero across repeated requests, something in the prefix changes every time, such as a timestamp.
print(response.usage.cache_creation_input_tokens) # written to the cache
print(response.usage.cache_read_input_tokens) # served from the cache
print(response.usage.input_tokens) # not cached
Count tokens before sending
Estimate the input size and cost of a request without running it.
count = client.messages.count_tokens(
model="claude-opus-5-5",
system=system,
messages=messages,
)
print(count.input_tokens)
Submit a batch
Process many requests asynchronously at half the price. Each request needs a custom_id.
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request
batch = client.messages.batches.create(requests=[
Request(
custom_id=f"request-{i}",
params=MessageCreateParamsNonStreaming(
model="claude-opus-5-5",
max_tokens=16000,
messages=[{"role": "user", "content": prompt}],
),
)
for i, prompt in enumerate(prompts)
])
Wait for a batch and read results
Poll until processing ends, then stream the results. Results arrive in any order, so match them by custom_id.
import time
while client.messages.batches.retrieve(batch.id).processing_status != "ended":
time.sleep(60)
for entry in client.messages.batches.results(batch.id):
if entry.result.type == "succeeded":
print(entry.custom_id, entry.result.message.content[0].text)