Requests
All examples use the official SDKs. Generate complete runnable files with
node scripts/claude-api.mjs scaffold <approach>.
Anatomy
{
"model": "claude-opus-5-5",
"max_tokens": 16000,
"system": "Stable instructions. Keep volatile values out of here.",
"thinking": {"type": "adaptive"},
"output_config": {"effort": "medium"},
"messages": [{"role": "user", "content": "…"}]
}messagesstarts with auserturn. Roles areuserandassistant; tool results travel in ausermessage astool_resultblocks (there is notoolrole).contentis a string or an array of blocks:text,image,document,tool_use,tool_result,thinking.- Default
max_tokens: about 16000 without streaming, up to 64000 with streaming. Lower only for a reason (a classifier needs ~256).
Streaming
TypeScript: client.messages.stream({...}), stream.on("text", …), await stream.finalMessage().
Python: with client.messages.stream(...) as s: → s.text_stream, s.get_final_message().
Use the helper's final message instead of reassembling events yourself.
Structured outputs
"output_config": {"format": {"type": "json_schema", "schema": {
"type": "object",
"properties": {"sentiment": {"type": "string", "enum": ["positive", "neutral", "negative"]}},
"required": ["sentiment"], "additionalProperties": false}}}The reply's text block is JSON matching the schema when stop_reason is end_turn. Check that
first: max_tokens leaves truncated JSON. Verified on all 15 probed models. Cannot be combined
with citations.
Images, PDFs, files
- Image:
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "…"}}. - PDF:
{"type": "document", "source": {"type": "base64", "media_type": "application/pdf", "data": "…"}}, placed before the question. - Plain text document with citations:
{"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "…"}, "citations": {"enabled": true}}— cited text blocks then carry acitationsarray withcited_text. - Files API:
client.files.upload(...)→file_id, referenced as{"type": "document", "source": {"type": "file", "file_id": "file_…"}}(or"type": "image"). Alsofiles.list,files.retrieveMetadata/retrieve_metadata,files.delete.
Batches
client.messages.batches.create({requests: [{custom_id, params}]}), poll retrieve(id) until
processing_status is "ended", then iterate results(id). Half price. Results come in any
order: match on custom_id. Each result is succeeded, errored, canceled or expired.
Token counting
client.messages.countTokens({model, messages, system, tools}) (Python: count_tokens) returns
input_tokens for free. Count on the model you will call: the same text costs a different number
of tokens on different generations (the same 7-word prompt measured 14 tokens on 4.5/4.6 models,
16–21 on newer ones). Do not use a third-party tokenizer.