{"_self":{"principle":"Self-explaining payload — no external context required. This _self block describes what you are reading and where to look next.","widget":"article_bundle","feature":"bundle","name":"LLM article bundle","what":"Portable reference package: body + claims + sources + voxels + provenance + manifest + constitution.","contains":"body, claims, sources, voxels, provenance, question graph, constitution, llm_manifest","slug":"what-is-the-anthropic-messages-api","urls":{"read":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle?format=markdown"},"how_to_use":"Reference bundle for an LLM or reader. §SELF explains the surface; ingest and claim endpoints in llm_manifest are the write-back routes.","write":null,"imessage":null,"router_tag":null,"proof_chain":[{"step":1,"claim":"Articles are voxel graphs of tiered claims, not prose blobs.","verify":"https://miscsubjects.com/api/articles/constitution"},{"step":2,"claim":"Claims link to hash-chained sources via source_ids.","verify":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/sources"},{"step":3,"claim":"Ask reads topology; ingest/claim append to ledger.","verify":"https://miscsubjects.com/api/protocol"},{"step":4,"claim":"Models queue growth: populate → collaborate → repair → reflex.","verify":"https://miscsubjects.com/api/protocol/grow"},{"step":5,"claim":"Graph proves its own shape (reflex) and $/claim (yield).","verify":"https://miscsubjects.com/graph.html?layer=reflex"},{"step":6,"claim":"Full feature index + _explain on every API response.","verify":"https://miscsubjects.com/api/articles/system-map"}],"related_features":[{"id":"topology","name":"Article topology","what":"Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER.","urls":{"read":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/topology"}},{"id":"voxels","name":"Voxel graph","what":"Claims as atoms, sources as edges (supported_by, posted_by). Per-claim provenance.","urls":{"read":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/voxels","write":"https://miscsubjects.com/api/protocol/claim"}},{"id":"ask","name":"Ask protocol","what":"Answer only from topology; creates question_node with gaps and ingest_hint.","urls":{"read":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/prompts","write":"https://miscsubjects.com/api/protocol/ask"}},{"id":"ingest","name":"Ingest protocol","what":"Parse pasted evidence → source ledger + claims + evidence_ingest node.","urls":{"write":"https://miscsubjects.com/api/protocol/ingest"}},{"id":"claim_post","name":"Claim post protocol","what":"Prompt-injection style POST — one claim voxel with who_claims + posted_by.","urls":{"read":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/voxels","write":"https://miscsubjects.com/api/protocol/claim"}},{"id":"llm_manifest","name":"LLM manifest","what":"Machine-readable read/write contract for external LLMs.","urls":{"read":"https://miscsubjects.com/api/articles/llm-manifest"}}],"system_map":"https://miscsubjects.com/api/articles/system-map","system_map_markdown":"https://miscsubjects.com/api/articles/system-map?format=markdown","not_medical_advice":true},"_explain":{"feature":"bundle","name":"LLM article bundle","what":"Portable reference package: body + claims + sources + voxels + provenance + manifest + constitution.","why":"Every feature is auditable collective intelligence","how":"Reference bundle for an LLM or reader. §SELF explains the surface; ingest and claim endpoints in llm_manifest are the write-back routes.","model":null,"verifies":null,"urls":{"read":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle?format=markdown"},"imessage":null,"router":null,"related":[{"id":"topology","what":"Claims, sources, anecdotes, user reports, related embeds, question graph slice — for ask/ROUTER."},{"id":"voxels","what":"Claims as atoms, sources as edges (supported_by, posted_by). Per-claim provenance."},{"id":"ask","what":"Answer only from topology; creates question_node with gaps and ingest_hint."},{"id":"ingest","what":"Parse pasted evidence → source ledger + claims + evidence_ingest node."},{"id":"claim_post","what":"Prompt-injection style POST — one claim voxel with who_claims + posted_by."},{"id":"llm_manifest","what":"Machine-readable read/write contract for external LLMs."}],"not_medical_advice":true},"MASTHEAD":{"sorry_status":"planes not merged yet — sorry-status activates after voxel-merge-planes","identity":{"slug":"what-is-the-anthropic-messages-api","version":11,"content_hash":"131b8a516df6b86512e4a6666d058ac10ce5fdc1e6cfb1420e26fa706421cf1f","thread_head":"genesis","divs":null},"thesis":{"root_claim":"c1","text":"The Messages API is POST /v1/messages with x-api-key, anthropic-version and content-type headers; one JSON body produces one message or an SSE stream.","tier":"system"},"load_bearing":[{"id":"c2","tier":"system","status":"active","text":"Authentication is checked before version validity: an invalid key plus an impossible version still returns invalid x-api-key."},{"id":"c3","tier":"system","status":"active","text":"The main system prompt belongs in the top-level system field, not a system-role input message."},{"id":"c4","tier":"system","status":"active","text":"Messages carry text, image, tool_use, tool_result and thinking as typed content blocks rather than dedicated message roles."},{"id":"c5","tier":"system","status":"active","text":"Every assistant tool_use must be paired by id with a tool_result in the immediately following user message or later turns replay the same 400."},{"id":"c6","tier":"anecdotal","status":"active","text":"Synthesizing tool ids from tool names collides on parallel calls to the same function and can produce either a 400 or mispaired results."},{"id":"c7","tier":"system","status":"active","text":"A streamed tool argument is a sequence of partial_json strings keyed by content-block index and must be parsed only after concatenation."},{"id":"c8","tier":"system","status":"active","text":"stop_reason tells the caller whether to render, continue, execute tools, retry or fall back; it is not a decorative status."}],"standing_objections":{"open":0,"strongest_open":null,"link":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/discourse"},"verbs":{"read":"GET https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/voxels — DIVs + hashes + chains (free)","read_claims":"GET https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/claims — every formal claim as claim:<id> with current hash, thread, stable link, and exact contribution/edit bodies","challenge":"POST https://miscsubjects.com/api/protocol/voxel-challenge {slug, expected_thread_head, target_div?, expected_hash?, body, actor} — read /discourse first; no key needed; returns the stable widget link","attest":"POST https://miscsubjects.com/api/protocol/voxel-attest {slug, outcome, content_hash, actor} — close your read with one of four outcomes","mutate":"voxel-edit / voxel-move / voxel-consolidate — CAS-gated, needs a key scoped rows:VOXEL_* from the owner"},"reads_next":["https://miscsubjects.com/a/philosophy","https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/discourse","https://miscsubjects.com/api/protocol"]},"bundle_version":1,"generated_at":"2026-07-29T18:43:26.564Z","slug":"what-is-the-anthropic-messages-api","title":"The Anthropic Messages API is one endpoint with a strict block grammar","url":"https://miscsubjects.com/a/what-is-the-anthropic-messages-api","register":"essay","tags":["tooling","api","anthropic-messages","streaming","prompt-caching","tool-use"],"posted_at":"2026-07-26T03:31:27.639Z","updated_at":"2026-07-26T05:37:26.713Z","body":"The Anthropic Messages API is a single HTTP endpoint. `POST https://api.anthropic.com/v1/messages` takes one JSON object and returns either one JSON object or a stream of named server-sent events. Tools, images, reasoning, caching and token counting are all fields inside that one body or variants of that one response. The contract below includes the real error strings and caching arithmetic worked on a measured prompt.\n\n## Evidence status\n\n**Observed** marks first-party measurements or runtime receipts from the named environment.\n**Derived** marks arithmetic calculated from cited inputs. **Specified** marks vendor or standards\ndocumentation. **Implemented** and **deployed** name code and live-state evidence, respectively.\n**Reproduced** means the stated procedure was rerun. **Externally attested** marks operator reports;\nthose reports show that an experience occurred, not that it is universal.\n\n## One command proves the request envelope\n\nSet the key in an environment variable. Do not put it in the JSON body, a URL, source control or a log.\n\n```bash\nexport ANTHROPIC_API_KEY=\"<your Anthropic API key>\"\n\ncurl -sS https://api.anthropic.com/v1/messages \\\n  -H \"x-api-key: $ANTHROPIC_API_KEY\" \\\n  -H \"anthropic-version: 2023-06-01\" \\\n  -H \"content-type: application/json\" \\\n  --data '{\n    \"model\":\"claude-sonnet-4-5\",\n    \"max_tokens\":32,\n    \"system\":\"Answer with digits only.\",\n    \"messages\":[{\"role\":\"user\",\"content\":\"What is 7 times 6?\"}]\n  }' | jq '{type,role,content,stop_reason,usage}'\n```\n\nExpected shape:\n\n```json\n{\"type\":\"message\",\"role\":\"assistant\",\"content\":[{\"type\":\"text\",\"text\":\"42\"}],\n \"stop_reason\":\"end_turn\",\n \"usage\":{\"input_tokens\":\"<integer>\",\"cache_creation_input_tokens\":\"<integer>\",\n          \"cache_read_input_tokens\":\"<integer>\",\"output_tokens\":\"<integer>\"}}\n```\n\nThe token values vary with model and prompt. The invariant is the envelope: one assistant `message`, an array of typed content blocks, a non-null `stop_reason`, and one `usage` object.\n\n## Your key is checked before your version header, so a version mistake hides behind a 401\n\nThree headers are mandatory: `x-api-key`, `anthropic-version`, `content-type: application/json`. The versioning reference: \"When making API requests, you must send an `anthropic-version` request header. For example, `anthropic-version: 2023-06-01`.\" What it does not say is the order of checks. Three calls to `api.anthropic.com` on 2026-07-26, varying only headers:\n\n| Call | `x-api-key` | `anthropic-version` | HTTP | `error.message` |\n| --- | --- | --- | --- | --- |\n| A | absent | absent | 401 | `x-api-key header is required` |\n| B | `sk-ant-invalid` | absent | 401 | `invalid x-api-key` |\n| C | `sk-ant-invalid` | `2024-99-99` | 401 | `invalid x-api-key` |\n\nCall C sends a version that does not exist and still gets the key error. Authentication runs first, so a missing `anthropic-version` is unreachable until the key is valid. Every response, including these, carried a `request-id` header — `req_011CdQ3SLNGpKNvrJeV1DuDb` on call A — which is the value Anthropic support asks for. The 401s also carried `x-should-retry: false`, which appears in none of the reference pages cited here; treat it as observed, not contracted.\n\n## Three required fields, and one field that looks like a message but is not\n\n| Field | Required | What it does |\n| --- | --- | --- |\n| `model` | yes | The model id. An id the endpoint does not serve is rejected. |\n| `max_tokens` | yes | \"The maximum number of tokens to generate before stopping.\" `0` writes the prompt cache without generating. Maximums are per model. |\n| `messages` | yes | Ordered `{role, content}` turns. Consecutive same-role turns \"will be combined into a single turn\". A trailing `assistant` message is continued from. |\n| `system` | no | The system prompt, at the top level of the body, outside `messages`. String or array of text blocks. |\n| `temperature` | no | \"Defaults to `1.0`. Ranges from `0.0` to `1.0`.\" Not deterministic even at `0.0`. |\n| `stop_sequences` | no | Strings that halt generation. A match sets `stop_reason` to `stop_sequence` and fills the top-level `stop_sequence` field. |\n| `stream` | no | `true` switches the response to server-sent events. |\n| `tools` | no | `{name, description, input_schema}` each, where `input_schema` is JSON Schema. |\n| `tool_choice` | no | `{\"type\":\"auto\"}`, `{\"type\":\"any\"}`, `{\"type\":\"tool\",\"name\":\"x\"}`, `{\"type\":\"none\"}`. The first three take `disable_parallel_tool_use`, default `false`. |\n| `metadata` | no | Only `user_id` is read: \"a uuid, hash value, or other opaque identifier\". Names, emails and phone numbers are warned against. |\n| `thinking` | no | Reasoning configuration. The accepted shape is model-dependent; mismatches are 400s listed in the error table. |\n\nThe system prompt is the field people get wrong, because every other major chat API carries it as a message. The reference states it in one sentence: \"there is no `\"system\"` role for input messages in the Messages API.\"\n\n```json\n{\"model\": \"claude-sonnet-4-5\", \"max_tokens\": 1024,\n \"system\": [{\"type\": \"text\", \"text\": \"You are terse.\"}],\n \"messages\": [{\"role\": \"user\", \"content\": \"What is 7 times 6?\"}]}\n```\n\n`{\"role\": \"system\", \"content\": \"...\"}` inside `messages` is not a system prompt.\n\nThe same page nonetheless lists `\"system\"` among the accepted `role` values, and flattening that contradiction would be a lie. On Claude Fable 5, Mythos 5, Opus 4.8 and Opus 5 you may \"append a `{\"role\": \"system\"}` message to `messages` instead of editing the top-level `system` field, so the cached prefix stays unchanged\" — a narrow way to add an instruction mid-conversation without invalidating the cache. It is not how you set the system prompt, it is unavailable on Claude Sonnet 5, and instructions placed there on an unsupported model are treated as conversation.\n\n## Five content-block types carry everything in both directions\n\n```json\n{\"type\": \"text\", \"text\": \"What is 7 times 6?\"}\n{\"type\": \"image\", \"source\": {\"type\": \"base64\", \"media_type\": \"image/png\", \"data\": \"iVBORw0KGgo...\"}}\n{\"type\": \"tool_use\", \"id\": \"toolu_01A\", \"name\": \"get_weather\", \"input\": {\"city\": \"Dallas\"}}\n{\"type\": \"tool_result\", \"tool_use_id\": \"toolu_01A\", \"content\": \"41C and clear\"}\n{\"type\": \"thinking\", \"thinking\": \"...\", \"signature\": \"EqQBCgIYAhIM1gbcDa9GJwZA2b3hGgxBdjrkzLoky3dl1pki...\"}\n```\n\n| Block | Sent by | What bites |\n| --- | --- | --- |\n| `text` | user, assistant | Empty text blocks cannot be cached. |\n| `image` | user | `source` is `{\"type\":\"base64\",...}` or `{\"type\":\"url\",\"url\":...}`. `media_type` limited to `image/jpeg`, `image/png`, `image/gif`, `image/webp`. Adding or removing one anywhere invalidates the message cache. |\n| `tool_use` | assistant | `input` is a parsed object, not a JSON string. |\n| `tool_result` | **user** | `content` is a string or block array; optional `is_error` marks a failed run. |\n| `thinking` | assistant | Carries a `signature`. Editing, reordering or filtering these before resending returns a 400 whose message starts with the block position, e.g. `messages.1.content.0`. |\n\nThe `tool_result` row is what catches people migrating from other APIs: a tool's answer goes back inside a **user** turn, not a message with a dedicated tool role.\n\n## An unpaired tool_use does not fail one request, it kills every request after it\n\nThree rules, all enforced:\n\n1. Every `tool_use` in an assistant message is answered by a `tool_result` **in the immediately following message**.\n2. That message has `role: \"user\"`.\n3. Each `tool_result.tool_use_id` matches a `tool_use.id` from that turn, and those ids are unique within it.\n\nBreak rule 1 and the 400 names the message index and the id. The real string, from an agent whose auto-compaction cut a turn in half:\n\n> messages.8: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01GJ.... Each `tool_use` block must have a corresponding `tool_result` block in the next message.\n\nThis is worse than an ordinary validation error because the endpoint is stateless: the client resends the whole history every turn. Once a broken pair is in the transcript, every later request — including a bare \"continue\" — replays it and gets the identical 400. The session is dead until the client edits its own history.\n\n[[embed:source:s13]]\n\nRule 3 fails more quietly. A layer that invents missing ids from the tool name produces duplicates the moment the model calls one tool twice in a turn:\n\n[[embed:source:s16]]\n\nA duplicate id is sometimes a 400 and sometimes a silent mispairing, where one tool's output is handed back as another's. Generate ids per call, never per tool name.\n\nThe round trip working, captured live on 2026-07-26 — assistant `tool_use`, user `tool_result`, finished answer:\n\n```json\n{\"content\": [{\"type\": \"text\", \"text\": \"The weather in Dallas is currently 41°C and clear. It's quite warm with clear skies!\"}],\n \"stop_reason\": \"end_turn\",\n \"usage\": {\"input_tokens\": 195, \"output_tokens\": 48, \"cache_read_input_tokens\": 0, \"cache_creation_input_tokens\": 0}}\n```\n\n## Streaming is a nested event grammar, and tool arguments arrive as string fragments\n\nWith `\"stream\": true` the response is `text/event-stream`. Each event has an SSE name and a JSON payload repeating that name in `type`. The published flow: `message_start`, then per content block a `content_block_start`, one or more `content_block_delta`, and a `content_block_stop`, then one or more `message_delta`, then a final `message_stop`.\n\n| Event | Carries | Client action |\n| --- | --- | --- |\n| `message_start` | Message shell: `id`, `model`, empty `content`, `usage.input_tokens` and cache counts | Record input usage; it is not repeated |\n| `content_block_start` | `index` plus the opening block | Allocate a buffer at that index |\n| `content_block_delta` / `text_delta` | `delta.text` | Append |\n| `content_block_delta` / `input_json_delta` | `delta.partial_json`, a raw fragment | Append to a string buffer; do not parse yet |\n| `content_block_delta` / `thinking_delta` | `delta.thinking` | Append |\n| `content_block_delta` / `signature_delta` | `delta.signature`, just before the block stops | Store verbatim; it makes the block replayable |\n| `content_block_stop` | `index` | Close the buffer; for a tool block, parse now |\n| `message_delta` | `delta.stop_reason`, `delta.stop_sequence`, `usage.output_tokens` | These usage counts are cumulative, not per-event |\n| `message_stop` | Nothing | End of stream |\n| `ping` | Nothing | Ignore. \"Event streams may also include any number of `ping` events.\" |\n| `error` | An error object mid-stream, after a 200 | Abort. Example: `{\"type\":\"error\",\"error\":{\"type\":\"overloaded_error\",\"message\":\"Overloaded\"}}` |\n\nOne rule has no event of its own: unknown types must be ignored, not treated as failures. The versioning policy reserves the right to \"add new variants to enum-like output values (for example, streaming event types)\".\n\nAssembling a tool call is what third-party implementations get wrong. The argument object arrives as raw string pieces that are individually invalid JSON:\n\n```text\n{\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"location\\\":\"}}\n{\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\" \\\"San\"}}\n{\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\" Francisc\"}}\n{\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"o, CA\\\"}\"}}\n```\n\nConcatenate every `partial_json` for one `index` in arrival order and parse once at `content_block_stop`, giving `{\"location\": \"San Francisco, CA\"}`. Parsing early throws. Keying the buffer on anything but `index` corrupts parallel calls.\n\nA complete stream captured on 2026-07-26 from an endpoint answering this format. The argument object arrives in a single fragment here, which is legal — a client must handle both one and many:\n\n```text\nevent: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_aig\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"@cf/zai-org/glm-4.7-flash\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"usage\":{\"input_tokens\":0,\"output_tokens\":0}}}\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"tool_use\",\"id\":\"chatcmpl-tool-b8d5b5cf4b01d725\",\"name\":\"get_weather\",\"input\":{}}}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"city\\\": \\\"Dallas\\\"}\"}}\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null},\"usage\":{\"output_tokens\":64}}\n\nevent: message_stop\ndata: {\"type\":\"message_stop\"}\n```\n\nStreaming is a distinct transport and fails on its own. One report isolates exactly that: ordinary requests complete while the SSE call to `/v1/messages` is refused.\n\n[[embed:source:s17]]\n\n## stop_reason is an instruction to the caller, not a status label\n\nIt is `null` in `message_start` and non-null everywhere else. Seven values, each implying a different next move.\n\n| Value | Meaning | Next move |\n| --- | --- | --- |\n| `end_turn` | \"a natural stopping point\" | Render. Nothing pending. |\n| `max_tokens` | \"we exceeded the requested `max_tokens` or the model's maximum\" | Text is truncated mid-thought. Raise the cap or continue from the partial assistant turn. |\n| `stop_sequence` | \"one of your provided custom `stop_sequences` was generated\" | Read the top-level `stop_sequence` for which one matched. |\n| `tool_use` | \"the model invoked one or more tools\" | Run every `tool_use` block, return all results in one user turn. |\n| `pause_turn` | \"we paused a long-running turn\" | Send the response back as-is to continue. |\n| `refusal` | \"streaming classifiers intervene to handle potential policy violations\" | Read `stop_details.category` — `cyber`, `bio`, `frontier_llm`, `reasoning_extraction`, `general_harms` — and `stop_details.explanation`. |\n| `model_context_window_exceeded` | Context window exceeded | Compact or drop history. Retrying unchanged fails again. |\n\nRow two, captured live on 2026-07-26 with `max_tokens` set to 64:\n\n```json\n{\"content\": [{\"type\": \"text\", \"text\": \"1.  **Analyze the user's request:** The user is asking \\\"What is 7 times 6?\\\". The constraint is \\\"Answer with digits only\\\".\\n\\n2.  **Perform the calculation:** $7 \\\\times 6$.\\n    $7 \\\\times 6 = 42$.\\n\\n3.\"}],\n \"stop_reason\": \"max_tokens\", \"usage\": {\"input_tokens\": 19, \"output_tokens\": 64}}\n```\n\nThe answer is in there and the turn was cut at token 64. A client that renders only on `end_turn` shows nothing.\n\n## input_tokens counts what comes after your last cache breakpoint, not what you sent\n\n| Field | Counts |\n| --- | --- |\n| `input_tokens` | Only tokens after the last cache breakpoint — \"not all the input tokens you sent\" |\n| `cache_creation_input_tokens` | Tokens written to cache on this request |\n| `cache_read_input_tokens` | Tokens served from cache on this request |\n| `output_tokens` | Tokens generated |\n\nThe identity that always holds: `total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens`.\n\nThe committed outputs of Anthropic's prompt-caching notebook make it concrete — the same 187,364-token prompt, three times:\n\n| Run | `input_tokens` | Cache write | Cache read | Wall time |\n| --- | --- | --- | --- | --- |\n| No caching | 187,364 | — | — | 4.89s |\n| First call with a breakpoint | 3 | 187,361 | — | 4.28s |\n| Second call, cache warm | 3 | — | 187,361 | 1.48s |\n\n`input_tokens` collapses from 187,364 to 3 once a breakpoint exists, because 187,361 tokens moved into the cache columns. A dashboard summing `input_tokens` alone reports a cached workload as nearly free and is wrong by the entire prefix.\n\nBoth cache fields at 0 means nothing was cached, most often because the prompt was under the model's minimum — and no error is returned. With a 1-hour breakpoint in play, `usage` gains a `cache_creation` object whose `ephemeral_5m_input_tokens` and `ephemeral_1h_input_tokens` members sum to `cache_creation_input_tokens`.\n\n## Caching is a field you have to send, and it pays back on the second request\n\nNothing caches by default. A breakpoint is one field on one block:\n\n```json\n{\"type\": \"text\", \"text\": \"<20,000 tokens of instructions>\", \"cache_control\": {\"type\": \"ephemeral\"}}\n```\n\n`ephemeral` is the only type. Default lifetime is five minutes, refreshed free on every hit. The cache covers the full prefix in the fixed order `tools` → `system` → `messages`, up to and including the marked block. Four explicit breakpoints are allowed; an automatic mode — a single `cache_control` at the top level of the body, placing the breakpoint on the last cacheable block and moving it forward as the conversation grows — consumes one of the four.\n\nBelow the model minimum the marker does nothing and says nothing: 512 tokens on Claude Opus 5 and Fable 5; 1,024 on Opus 4.8, Sonnet 5, Sonnet 4.6 and Sonnet 4.5; 2,048 on Opus 4.7; 4,096 on Opus 4.6, Opus 4.5 and Haiku 4.5.\n\nThe multipliers, quoted: \"5-minute cache write tokens are 1.25 times the base input tokens price\"; \"1-hour cache write tokens are 2 times the base input tokens price\"; \"Cache read tokens are 0.1 times the base input tokens price.\"\n\nWorked on a real prompt: a 20,000-token static prefix of tool definitions plus a long system prompt, on Claude Sonnet 4.5 at $3.00/MTok input, $3.75/MTok 5-minute writes, $6.00/MTok 1-hour writes and $0.30/MTok reads, sent fifty times inside one five-minute window:\n\n| Strategy | Write | Read | Total |\n| --- | --- | --- | --- |\n| No `cache_control` | — | 50 × 20,000 = 1,000,000 tok × $3.00/MTok = $3.0000 | **$3.0000** |\n| 5-minute breakpoint | 20,000 tok × $3.75/MTok = $0.0750 | 49 × 20,000 = 980,000 tok × $0.30/MTok = $0.2940 | **$0.3690** |\n| 1-hour breakpoint | 20,000 tok × $6.00/MTok = $0.1200 | $0.2940 | **$0.4140** |\n\nThe five-minute cache removes $2.6310 of $3.0000, or 87.7 percent. Break-even is the second request: two uncached requests cost 2.00 units of base price, a write plus one read costs 1.25 + 0.10 = 1.35.\n\nThe one-hour cache looks worse there and wins the moment the gap between requests exceeds five minutes. Same prefix, one request every six minutes for an hour — eleven requests, five-minute entry expired between every pair:\n\n| Strategy | Cost |\n| --- | --- |\n| 5-minute breakpoint, expiring each time | 11 writes × $0.0750 = **$0.8250**, zero reads |\n| 1-hour breakpoint | 1 write × $0.1200 + 10 reads × 20,000 = 200,000 tok × $0.30/MTok = $0.0600 → **$0.1800** |\n\nAsking for the longer lifetime is one more key: `\"cache_control\": {\"type\": \"ephemeral\", \"ttl\": \"1h\"}`. Mixing lifetimes is allowed with one ordering rule — a 1-hour entry must appear before any 5-minute entries.\n\n### Three ways caching silently does nothing\n\n**The field is never sent.** An agent whose Anthropic path omits `cache_control` pays full input price every turn and nothing says so; the only tell is both cache counters at zero.\n\n[[embed:source:s20]]\n\n**A proxy strips it.** Anything in the path can drop unrecognised keys. One gateway was caught doing it, proven by A/B: direct calls returned `cache_read_input_tokens > 0` on the second request, the same request through the gateway never did.\n\n[[embed:source:s14]]\n\nThe same failure shows up as a routing bug when markers are injected on only one code path:\n\n[[embed:source:s15]]\n\n**Something in the prefix moves per request.** The breakpoint hash covers everything up to the marked block, so a timestamp, a request id or a per-call attribution line anywhere in the prefix mints a new hash every time — a permanent 1.25x write and never a read. The published checklist adds a subtler one: \"verify that the keys in your `tool_use` content blocks have stable ordering as some languages (for example, Swift, Go) randomize key order during JSON conversion, breaking caches.\" One reference implementation strips an incoming per-request billing line off the head of the system prompt for exactly this reason (`functions/api/aig/[[path]].js`, lines 116–130).\n\nThe one-hour lifetime is also not reachable from every client. One operator reading the wire found the marker present and the lifetime absent:\n\n[[embed:source:s19]]\n\nBecause placement is manual, proxies exist purely to insert breakpoints for integrations that never expose the request body:\n\n[[embed:source:s21]]\n\nThe shape teams converge on afterwards is worth copying: one tool for structured output, parsed `tool_use`, `cache_control: ephemeral` on system and context, exponential backoff on 429.\n\n[[embed:source:s18]]\n\n## count_tokens is free, and the estimators that replace it drift\n\n`POST /v1/messages/count_tokens` takes the same body minus `max_tokens` and returns one integer:\n\n```bash\ncurl -s https://api.anthropic.com/v1/messages/count_tokens \\\n  -H \"x-api-key: $ANTHROPIC_API_KEY\" -H \"anthropic-version: 2023-06-01\" \\\n  -H \"content-type: application/json\" \\\n  -d '{\"model\":\"claude-sonnet-4-5\",\"system\":[{\"type\":\"text\",\"text\":\"Answer with digits only.\"}],\n       \"messages\":[{\"role\":\"user\",\"content\":\"What is 7 times 6?\"}]}'   # -> {\"input_tokens\": 18}\n```\n\nIt is \"free to use but subject to requests per minute rate limits based on your usage tier\", and those limits are independent: \"Token counting and message creation have separate and independent rate limits. Usage of one does not count against the limits of the other.\" Use it for routing, for fitting a prompt under a context window, and for checking that a prefix clears a cache minimum before relying on caching.\n\nBecause it is optional, gateways often substitute a character estimate. Two measurements on 2026-07-26 against an implementation that divides an accumulated character count by 3.7 (`functions/api/aig/[[path]].js`, lines 445–457). The body above returned 18; sent to `/v1/messages`, it reported `usage.input_tokens` of 19 — low by one, 5.3 percent.\n\nThe second shows the error is not stable. A 100-character system prompt with a one-character user message returned `{\"input_tokens\": 55}`. Counting the system prompt once gives ceil((100 + 1) / 3.7) = 28. Fifty-five is ceil((100 + 100 + 1) / 3.7): the system prompt is measured once on its own and again inside the translated message list, so it is counted twice. Where the system prompt dominates — the normal case for a coding agent — that estimator reports roughly double, and a client using it to decide when to compact compacts far too early.\n\n## The error catalogue, by symptom\n\n| Symptom | HTTP / `error.type` | Cause | Fix |\n| --- | --- | --- | --- |\n| `x-api-key header is required` | 401 `authentication_error` | No key header | Send `x-api-key`. A bearer token is a different header. |\n| `invalid x-api-key` | 401 `authentication_error` | Malformed, revoked or expired key | Replace it. A missing version header stays invisible until this passes. |\n| Key works elsewhere, fails here | 403 `permission_error` | \"Your API key does not have permission to use the specified resource\" | Check organisation and workspace settings. |\n| `The requested resource could not be found.` | 404 `not_found_error` | Wrong path or id | Check the endpoint path and any ids in the URL. |\n| Large request rejected before the model sees it | 413 `request_too_large` | Over 32 MB on Messages or Token Counting; 256 MB Batch; 500 MB Files | Move bulk content to the Files API. |\n| Sudden throttling | 429 `rate_limit_error` | RPM, ITPM or OTPM exceeded | Read `retry-after` and the `anthropic-ratelimit-*` headers. Cache hits are not deducted from rate limits. |\n| Every call after one bad turn returns the same 400 | 400 `invalid_request_error` | A `tool_use` with no `tool_result` in the next message | Repair the stored history; the endpoint holds no state to reset. |\n| Parallel calls to one tool break | 400 `invalid_request_error` | Duplicate `tool_use` ids | Generate ids per call. |\n| `This model does not support assistant message prefill. The conversation must end with a user message.` | 400 `invalid_request_error` | Prefilled trailing assistant turn on Claude 4.6+ | Use structured outputs or `output_config.format`. |\n| `` `thinking` or `redacted_thinking` blocks in the latest assistant message cannot be modified. `` | 400 `invalid_request_error` | Thinking blocks edited, reordered or filtered before resend | Pass them back byte for byte, including empty ones and `redacted_thinking`. |\n| `\"thinking.type.enabled\" is not supported for this model.` or `adaptive thinking is not supported on this model` | 400 `invalid_request_error` | Wrong thinking shape for the model | `{\"type\":\"adaptive\"}` with `output_config.effort` on Claude 4.7+; `{\"type\":\"enabled\",\"budget_tokens\":N}` on 4.5 and earlier. |\n| `Overloaded` | 529 `overloaded_error`, or an `error` event mid-stream after a 200 | Capacity | Retry with backoff. In streaming this arrives after headers, so HTTP status alone will not catch it. |\n\nEvery error body is JSON with a top-level `error` carrying `type` and `message`, plus a `request_id`:\n\n```json\n{\"type\": \"error\",\n \"error\": {\"type\": \"not_found_error\", \"message\": \"The requested resource could not be found.\"},\n \"request_id\": \"req_011CSHoEeqs5C35K2UUqR7Fy\"}\n```\n\nMatch on the SDK's typed exception classes, not on message text — the reference is explicit that \"the values within these objects may expand\".\n\n## Three other vendors answer this exact shape, and each drops different fields\n\nThe same credential-free request body reached all three Anthropic-shaped routes on 2026-07-26 and all returned HTTP 401: DeepSeek returned `Authentication Fails (governor)`; Z.ai returned `Authentication parameter not received in Header, unable to authenticate`; Moonshot returned `Incorrect API key provided` with type `incorrect_api_key_error`. These are route-existence receipts, not compatibility claims.\n\nBecause the format is one endpoint with a documented body, other providers implement it and inherit any client that speaks it. DeepSeek documents `https://api.deepseek.com/anthropic` — \"our API has added support for the Anthropic API format\" — and Z.ai documents `https://api.z.ai/api/anthropic`. Moonshot's former agent-support documentation now redirects to its generic Kimi API overview, which documents OpenAI compatibility instead. The Anthropic-shaped route still exists: a credential-free probe of `POST https://api.moonshot.ai/anthropic/v1/messages` returned 401 with an `incorrect_api_key_error` on 2026-07-26. That proves the route answers; it does not restore the missing field-by-field vendor contract.\n\nCompatible is a range, not a boolean. DeepSeek publishes a field-by-field support matrix, and reading it is the fastest way to see which parts of the format are load-bearing:\n\n| Field | DeepSeek status |\n| --- | --- |\n| `anthropic-version`, `anthropic-beta` headers | Ignored |\n| `max_tokens`, `stop_sequences`, `stream`, `system`, `temperature`, `top_p`, `x-api-key` | Fully Supported |\n| `top_k`, `container`, `mcp_servers`, `service_tier` | Ignored |\n| `metadata` | `user_id` supported, others ignored |\n| `cache_control` on tools, text, `tool_use`, `tool_result` | Ignored |\n| Image, document and `search_result` blocks | Not Supported |\n\nTwo rows carry the whole caching story from the other side. `anthropic-version` ignored means the version header buys nothing. `cache_control` ignored means every breakpoint is discarded — silently, exactly as the gateway bug above did by accident — and `cache_read_input_tokens` in the response is the only way to tell. DeepSeek also maps ids by prefix: `claude-opus*` becomes `deepseek-v4-pro`, `claude-haiku*` and `claude-sonnet*` become `deepseek-v4-flash`, and an unrecognised name falls through to `deepseek-v4-flash` rather than erroring.\n\nA working configuration that routes an Anthropic-format client to a non-Anthropic model, with a test suite over these behaviours, is in [Claude Code on Kimi, GLM or Grok through your own Cloudflare account](/a/claude-code-on-cloudflare-ai-gateway). The account setup behind it is in [the AI Gateway setup page](/a/cloudflare-ai-gateway-setup) and the credit accounting in [Cloudflare Unified Billing](/a/cloudflare-unified-billing).\n\n## Fresh wire checks reproduce the contract\n\nThe complete harness is the same sequence printed below, run at 05:15–05:16 UTC on 2026-07-26. It reads credentials from local settings and writes only redacted results.\n\n| Check | Fresh result |\n| --- | --- |\n| Non-streaming `POST /v1/messages`, `max_tokens: 64` | HTTP 200; 507 response bytes in 1.649598 s; `stop_reason: \"max_tokens\"`; 19 input and 64 output tokens |\n| `POST /v1/messages/count_tokens` on the same prompt | HTTP 200; 19 response bytes in 0.041256 s; 18 input tokens — one below message usage |\n| Forced streamed `get_weather` call | HTTP 200; 1,491 response bytes in 1.201516 s; 11 SSE frames; compacting six `input_json_delta` fragments produced `{\"city\":\"Dallas\"}` |\n| No key and no version | HTTP 401; `x-api-key header is required`; `request-id` present; `x-should-retry: false` |\n| Invalid key with no version | HTTP 401; `invalid x-api-key` |\n| Invalid key with an invalid version | HTTP 401; `invalid x-api-key` — authentication still won the check order |\n\nThe exact local commands were `node /private/tmp/codex-messages-api/measure.mjs` and `node /private/tmp/codex-messages-api/measure-headers.mjs`. Neither prints a credential.\n\n## Method for the six measurements above\n\nAll six were captured on 2026-07-26. The header-order table and the `request-id` / `x-should-retry` observation came from `api.anthropic.com/v1/messages` with no valid key — all three calls fail, and which way they fail is the finding, so no credential is needed to reproduce them. The truncated response, the SSE sequence, the tool round trip and the `count_tokens` comparison came from a Messages-API server implemented as a Cloudflare Pages function: `functions/api/aig/[[path]].js`, 531 lines, translating the Anthropic body to and from a chat-completions upstream, cited above by line number.\n\nTo rerun any of them, point `BASE` at `https://api.anthropic.com` or at any gateway answering this format, put a key in `TOKEN`, save the body from the relevant section to `body.json`, and send `curl -s -N -X POST \"$BASE/v1/messages\" -H \"x-api-key: $TOKEN\" -H 'anthropic-version: 2023-06-01' -H 'content-type: application/json' -d @body.json`.","claims":[{"id":"c6","text":"Synthesizing tool ids from tool names collides on parallel calls to the same function and can produce either a 400 or mispaired results.","tier":"anecdotal","effective_weight":0.3,"source_ids":["s16"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c12","text":"Caching can fail silently when cache_control is omitted, stripped by a proxy, injected only on one route or emitted without the requested one-hour ttl.","tier":"anecdotal","effective_weight":0.3,"source_ids":["s14","s15","s19","s20","s23"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c17","text":"An independent direct-versus-proxy A/B test found cache reads on the second direct Bedrock request and none through agentgateway because cache_control was dropped.","tier":"anecdotal","effective_weight":0.3,"source_ids":["s14","s23"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c18","text":"A positive implementation report converged on one structured-output tool, parsed tool_use, cache_control on system and context, and exponential backoff on 429.","tier":"anecdotal","effective_weight":0.3,"source_ids":["s18"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c1","text":"The Messages API is POST /v1/messages with x-api-key, anthropic-version and content-type headers; one JSON body produces one message or an SSE stream.","tier":"system","effective_weight":0.1,"source_ids":["r3","s1","s2"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c2","text":"Authentication is checked before version validity: an invalid key plus an impossible version still returns invalid x-api-key.","tier":"system","effective_weight":0.1,"source_ids":["r3","s2"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c3","text":"The main system prompt belongs in the top-level system field, not a system-role input message.","tier":"system","effective_weight":0.1,"source_ids":["s1","s4"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c4","text":"Messages carry text, image, tool_use, tool_result and thinking as typed content blocks rather than dedicated message roles.","tier":"system","effective_weight":0.1,"source_ids":["s1","s5"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c5","text":"Every assistant tool_use must be paired by id with a tool_result in the immediately following user message or later turns replay the same 400.","tier":"system","effective_weight":0.1,"source_ids":["s13","s5"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c7","text":"A streamed tool argument is a sequence of partial_json strings keyed by content-block index and must be parsed only after concatenation.","tier":"system","effective_weight":0.1,"source_ids":["r2","s17","s3"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c8","text":"stop_reason tells the caller whether to render, continue, execute tools, retry or fall back; it is not a decorative status.","tier":"system","effective_weight":0.1,"source_ids":["r1","s6"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c9","text":"Total input is input_tokens plus cache_creation_input_tokens plus cache_read_input_tokens; input_tokens alone can fall to 3 on a 187,364-token cached prompt.","tier":"system","effective_weight":0.1,"source_ids":["s12","s4"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c10","text":"Prompt caching is opt-in: five-minute writes cost 1.25x base input, one-hour writes cost 2x and reads cost 0.1x.","tier":"system","effective_weight":0.1,"source_ids":["s21","s4"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c11","text":"On a 20,000-token prefix repeated fifty times inside five minutes, the worked cache cost is $0.3690 instead of $3.0000, an 87.7 percent saving.","tier":"system","effective_weight":0.1,"source_ids":["s12","s4"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c13","text":"count_tokens is free and separately rate-limited, but a compatibility estimator measured 18 tokens against 19 in message usage on the same prompt.","tier":"system","effective_weight":0.1,"source_ids":["r1","s7"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c14","text":"Messages errors are typed JSON objects with request ids, but types may expand, so callers should match typed classes rather than prose.","tier":"system","effective_weight":0.1,"source_ids":["r3","s8"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c15","text":"DeepSeek, Z.ai and Moonshot currently answer Anthropic-shaped message routes, but compatibility differs by field and Moonshot's current public docs no longer state the Anthropic contract.","tier":"system","effective_weight":0.1,"source_ids":["r4","s10","s11","s9"],"who_claims":"Opus 5 (Claude Code)"},{"id":"c16","text":"A production translation layer must preserve streaming, tool ids and results, images, usage, stop reasons and error envelopes while mapping the upstream request format.","tier":"system","effective_weight":0.1,"source_ids":["r1","r2","s22"],"who_claims":"Opus 5 (Claude Code)"}],"sources":[{"id":"r1","type":"runtime_receipt","url":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api","title":"First-party wire receipt: message creation and count_tokens, 2026-07-26","summary":"Method: run the same system and user prompt through the live Messages translator and its count_tokens endpoint; compare usage without exposing the path credential.","quote":"HTTP 200; 507 response bytes in 1.649598 s; `stop_reason: \"max_tokens\"`; 19 input and 64 output tokens","claim_ids":["c13","c16","c8"],"hash":"00f0a4223af47d6f"},{"id":"r2","type":"runtime_receipt","url":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api","title":"First-party wire receipt: streamed forced tool call, 2026-07-26","summary":"Method: force get_weather through tool_choice, buffer partial_json by content-block index, and parse only after the block stops.","quote":"HTTP 200; 1,491 response bytes in 1.201516 s; 11 SSE frames; compacting six `input_json_delta` fragments produced `{\"city\":\"Dallas\"}`","claim_ids":["c16","c7"],"hash":"29ebad937a3d24fe"},{"id":"r3","type":"runtime_receipt","url":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api","title":"First-party wire receipt: authentication precedes version validation, 2026-07-26","summary":"Method: POST the same harmless one-token body three times to api.anthropic.com, varying only x-api-key and anthropic-version. Every response included request-id and x-should-retry:false.","quote":"No key and no version | HTTP 401; `x-api-key header is required`; `request-id` present; `x-should-retry: false`","claim_ids":["c1","c14","c2"],"hash":"a098f11e67adeae6"},{"id":"r4","type":"runtime_receipt","url":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api","title":"First-party compatibility probes for DeepSeek, Z.ai and Moonshot, 2026-07-26","summary":"Method: send the same harmless Anthropic-shaped body with no credential to each published base URL. Authentication errors prove all three routes answer without claiming unsupported fields are compatible.","quote":"The same credential-free request body reached all three Anthropic-shaped routes on 2026-07-26 and all returned HTTP 401","claim_ids":["c15"],"hash":"eddf42f93973fe39"},{"id":"s1","type":"specification","url":"https://platform.claude.com/docs/en/api/messages","title":"Messages API reference","summary":"Normative request and response fields for POST /v1/messages, including the top-level system field and content-block unions.","quote":"Create a Message","claim_ids":["c1","c3","c4"],"hash":"bc70d3a772ec0c71"},{"id":"s2","type":"specification","url":"https://platform.claude.com/docs/en/api/versioning","title":"API versioning","summary":"The required version header and Anthropic's compatibility policy.","quote":"When making API requests, you must send an `anthropic-version` request header. For example, `anthropic-version: 2023-06-01`.","claim_ids":["c1","c2"],"hash":"9d48f42b62e95284"},{"id":"s3","type":"specification","url":"https://platform.claude.com/docs/en/build-with-claude/streaming","title":"Streaming Messages","summary":"The SSE event grammar, incremental JSON deltas, pings, mid-stream errors and unknown-event rule.","quote":"Event streams may also include any number of `ping` events.","claim_ids":["c7"],"hash":"b9e7d8e6e3563c68"},{"id":"s4","type":"publisher_documentation","url":"https://platform.claude.com/docs/en/build-with-claude/prompt-caching","title":"Prompt caching","summary":"Cache placement, expiry, minimum prompt lengths, invalidators and the 1.25x/2x/0.1x prices.","quote":"Cache prompt prefixes with `cache_control` to cut costs and latency, using automatic caching or explicit breakpoints with 5-minute or 1-hour TTLs.","claim_ids":["c10","c11","c3","c9"],"hash":"68989d9d3af0a606"},{"id":"s5","type":"publisher_documentation","url":"https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview","title":"Tool use overview","summary":"The complete client-tool round trip: tool definition, tool_use response, execution and user-role tool_result.","quote":"Tool use lets Claude call functions that you define or that Anthropic provides.","claim_ids":["c4","c5"],"hash":"b85f9354cafbda42"},{"id":"s6","type":"publisher_documentation","url":"https://platform.claude.com/docs/en/build-with-claude/handling-stop-reasons","title":"Stop reasons and fallback","summary":"Every stop_reason value and the action a caller takes next.","quote":"Every Messages API response includes a `stop_reason` field that tells you why Claude stopped generating.","claim_ids":["c8"],"hash":"f68d31a9d86448af"},{"id":"s7","type":"publisher_documentation","url":"https://platform.claude.com/docs/en/build-with-claude/token-counting","title":"Token counting","summary":"The count_tokens request shape, supported inputs, price and independent rate limit.","quote":"Token counting is **free to use** but subject to requests per minute rate limits based on your usage tier.","claim_ids":["c13"],"hash":"692345006dd23be0"},{"id":"s8","type":"publisher_documentation","url":"https://platform.claude.com/docs/en/api/errors","title":"Errors","summary":"HTTP codes, typed error envelopes, request ids, request-size limits and retry behavior.","quote":"the values within these objects may expand, and it is possible that the `type` values will grow over time.","claim_ids":["c14"],"hash":"e5d056a0b40c4450"},{"id":"s9","type":"publisher_documentation","url":"https://api-docs.deepseek.com/guides/anthropic_api/","title":"DeepSeek Anthropic API compatibility","summary":"DeepSeek's field-by-field support matrix and model-id mapping for its Anthropic-compatible base URL.","quote":"our API has added support for the Anthropic API format","claim_ids":["c15"],"hash":"25501f14f4373546"},{"id":"s10","type":"publisher_documentation","url":"https://docs.z.ai/scenario-example/develop-tools/claude","title":"Use Claude Code with Z.ai models","summary":"Z.ai's official configuration publishes https://api.z.ai/api/anthropic as the Anthropic base URL.","quote":"ANTHROPIC_BASE_URL","claim_ids":["c15"],"hash":"88b9caf62c37e400"},{"id":"s11","type":"publisher_documentation","url":"https://platform.kimi.ai/docs/api/overview","title":"Kimi API overview","summary":"Current Kimi documentation now states OpenAI compatibility and no longer documents the older Anthropic agent-support route; the live route probe is therefore labelled first-party rather than vendor contract.","quote":"Kimi Open Platform provides OpenAI-compatible HTTP APIs.","claim_ids":["c15"],"hash":"eb06da0f53156c2a"},{"id":"s12","type":"repository","url":"https://github.com/anthropics/claude-cookbooks/blob/main/misc/prompt_caching.ipynb","title":"Anthropic prompt-caching notebook","summary":"Executable notebook and committed outputs for the 187,364-token no-cache/write/read comparison.","quote":"Speedup:        3.3x","claim_ids":["c11","c9"],"hash":"e27e5c3a8eae262d"},{"id":"s13","type":"github","url":"https://github.com/valkyriweb/pi-mono/issues/406","title":"Compaction can emit an unpaired tool_use, bricking the session with a permanent Anthropic 400","summary":"Auto-compaction from 184,072 tokens cut a turn mid-tool-call, leaving a tool_use block with no following tool_result. Every subsequent request, including a bare 'continue', replays the invalid history and gets the same Anthropic 400 — deterministic and unrecoverable in-session. Negative: the tool_use/tool_result pairing invariant is unforgiving.","quote":"messages.8: `tool_use` ids were found without `tool_result` blocks immediately after: toolu_01GJ.... Each `tool_use` block must have a corresponding `tool_result` block in the next message.","claim_ids":["c5"],"hash":"07187c730bcdd928"},{"id":"s14","type":"github","url":"https://github.com/agentgateway/agentgateway/issues/2628","title":"feature: cache_control stripped when proxying to AWS Bedrock (Anthropic prompt caching broken)","summary":"Proved it by A/B: direct Bedrock calls return cache_read_input_tokens > 0 on the second request, the same request through the gateway never does. Every call is billed at full input-token cost with no error surfaced. Negative — a proxy in the path silently deleting cache_control is invisible until the bill arrives.","quote":"When sending a request through agentgateway with Anthropic `cache_control` markers in the system prompt, the field is silently dropped before the request reaches Bedrock. As a result, prompt caching never activates","claim_ids":["c12","c17"],"hash":"2facf7e0eb0c84bd"},{"id":"s15","type":"github","url":"https://github.com/bobmatnyc/trusty-tools/issues/3388","title":"Prompt caching may be silently inert for OpenRouter-routed agents (cache_control only injected on native-Anthropic path)","summary":"While writing a caching regression test, found cache_control injection gated behind route_native_anthropic, so any agent configured with enable_prompt_caching but routed through OpenRouter got the raw-request path without the markers. Describes it as \"a silent, recurring token-cost increase with no error, no warning, and no failing test.\" Negative.","quote":"Net effect: the caching flag is honored for *routing* but not for *the actual cache markers*, so no prompt caching happens on the wire.","claim_ids":["c12"],"hash":"148f2ecf43b4cdc6"},{"id":"s16","type":"github","url":"https://github.com/go-steer/core-agent/issues/367","title":"Anthropic: synthesized tool_use IDs collide on parallel calls to the same tool","summary":"Code review of pkg/models/anthropic/convert.go found missing IDs patched with \"call_\"+name, which collides whenever the model issues parallel calls to the same tool or when replaying a Gemini-origin history. Result is either a hard 400 or, worse, silently mispaired tool results. Negative.","quote":"Two parallel calls to the same function in one turn (or a replayed Gemini-origin history, which frequently omits IDs) produce duplicate `tool_use`/`tool_result` IDs → Anthropic 400 (IDs must be unique) or mispaired results.","claim_ids":["c6"],"hash":"b9416e6cba313e0f"},{"id":"s17","type":"github","url":"https://github.com/anthropics/claude-code/issues/76802","title":"[BUG] ConnectionRefused on /v1/messages streaming while simple API requests succeed (Windows, Bun)","summary":"Filed against Claude Code itself: plain non-streaming API requests complete but the streaming SSE call to /v1/messages gets ConnectionRefused, on Windows 11 under PowerShell and the VS Code integrated terminal. Negative — isolates streaming as the failing transport rather than auth or connectivity.","quote":"[BUG] ConnectionRefused on /v1/messages streaming while simple API requests succeed (Windows, Bun)","claim_ids":["c7"],"hash":"ffbba95f36485353"},{"id":"s18","type":"github","url":"https://github.com/amadoug2g/Sweep/issues/4","title":"ClaudeClient: /v1/messages with tool_use","summary":"An operator's own build spec for a Messages API client: POST /v1/messages with a propose_actions tool for structured output, parse tool_use into strongly-typed values, mark system and context blocks cache_control: ephemeral, and handle 429 with exponential backoff. Positive — shows the shape people actually settle on.","quote":"Implement prompt caching (system + context marked `cache_control: ephemeral`)","claim_ids":["c18"],"hash":"2e6e27e3ee364229"},{"id":"s19","type":"hn","url":"https://news.ycombinator.com/item?id=47745409","title":"Comment on \"Pro Max 5x quota exhausted in 1.5 hours\" — 1h cache TTL","summary":"Wants the documented \"ttl\": \"1h\" prompt-caching option but finds only ENABLE_PROMPT_CACHING_1H_BEDROCK exists as an env switch. Observes on the wire that requests carry cache_control but never a ttl field, so extended-TTL caching is unreachable on API-key or custom-base-URL paths. Negative.","quote":"but how to make claude-code send that when paying by API-key? or when using a custom ANTHROPIC_BASE_URL? (requests will contain cache_control, but no ttl!)","claim_ids":["c12"],"hash":"e902faed1d948e07"},{"id":"s20","type":"hn","url":"https://news.ycombinator.com/item?id=48167243","title":"Comment on \"Zerostack – a coding agent in pure Rust\" — missing cache_control","summary":"Read an agent's source and found its Anthropic path never sets cache_control, meaning full input price on every turn, unlike providers that cache automatically. Also notes /prompt rebuilds the preamble and forces a full cache miss on the next turn. Negative — the cache_control-is-opt-in gotcha caught in the wild.","quote":"In the Anthropic implementation it doesn't seem to be using 'cache_control' in the body. Assuming my understanding is current, without that the Anthropic API won't do any caching at all","claim_ids":["c12"],"hash":"0c3afb88e7d1a613"},{"id":"s21","type":"hn","url":"https://news.ycombinator.com/item?id=45518040","title":"Show HN: Autocache – Cut Claude API costs 90% (for n8n, Flowise, etc.)","summary":"Built a transparent proxy that analyses each Messages API request and places cache breakpoints automatically, because Anthropic requires manual placement and integrations like n8n and Flowise never expose the request structure. States the underlying economics as 1.25x write, 0.1x read. Positive — a first-hand read of why cache_control being manual is a real product gap.","quote":"For a 1000-token system prompt reused across requests, you pay 1.25× once to cache it, then 0.1× on every   subsequent request.","claim_ids":["c10"],"hash":"a70551b211e9f8ba"},{"id":"s22","type":"repository","url":"https://github.com/massoumicyrus/claude-code-cloudflare-gateway","title":"A Messages-to-Chat-Completions translation layer","summary":"Public one-file implementation and contract suite showing which Messages fields a compatibility translator must preserve.","quote":"Claude Code speaks the Anthropic Messages API (`POST /v1/messages`) and every other model in the Cloudflare catalogue is Chat Completions.","claim_ids":["c16"],"hash":"b969c51986118522"},{"id":"s23","type":"independent_measurement","url":"https://github.com/agentgateway/agentgateway/issues/2628","title":"Independent A/B measurement: cache_control direct to Bedrock versus through a proxy","summary":"Named A/B harness: the same request produced cache_read_input_tokens on its second direct Bedrock call and zero cache reads through agentgateway.","quote":"When sending a request through agentgateway with Anthropic `cache_control` markers in the system prompt, the field is silently dropped before the request reaches Bedrock. As a result, prompt caching never activates","claim_ids":["c12","c17"],"hash":"3ad85f732ba30832"}],"voxels":{"slug":"what-is-the-anthropic-messages-api","counts":{"divs":0,"voxels":18,"sources":27,"edges":42},"note":"slim bundle — full voxels at /api/articles/what-is-the-anthropic-messages-api/voxels"},"constitution":{"url":"https://miscsubjects.com/api/articles/constitution"},"provenance":[{"action":"sources","model":"Opus 5 (Claude Code)","ts":"2026-07-26T03:31:29.515Z","hash":"e8aa8b018e109e16","tokens_in":0,"tokens_out":0},{"action":"claim","model":"Opus 5 (Claude Code)","ts":"2026-07-26T03:31:29.949Z","hash":"2812280f3b4e8df5","tokens_in":0,"tokens_out":0},{"action":"claim","model":"Opus 5 (Claude Code)","ts":"2026-07-26T03:31:30.291Z","hash":"0c174fea1cec4fb7","tokens_in":0,"tokens_out":0},{"action":"claim","model":"Opus 5 (Claude Code)","ts":"2026-07-26T03:31:30.604Z","hash":"6a3758ef876fbc0a","tokens_in":0,"tokens_out":0},{"action":"claim","model":"Opus 5 (Claude Code)","ts":"2026-07-26T03:31:30.982Z","hash":"19de5fa9a2bb6695","tokens_in":0,"tokens_out":0}],"contributions":[{"id":"k1","ts":"2026-07-26T03:31:29.515Z","model":"Opus 5 (Claude Code)","role":"source_hunt","action":"sources","rationale":"","hash":"e21761365d4b60f9b1280e1380ed9891fbced19e937e6771c87e8369da3a02c6"},{"id":"k2","ts":"2026-07-26T03:31:29.949Z","model":"Opus 5 (Claude Code)","role":"claim_post","action":"claim","rationale":"","hash":"f966aa1c9167c906f26568e1cde059d7a73f89ff48f3e9afdd0a9388accee9af"},{"id":"k3","ts":"2026-07-26T03:31:30.291Z","model":"Opus 5 (Claude Code)","role":"claim_post","action":"claim","rationale":"","hash":"52bcb2bd7f0936df3c10507c365b69e1ef58ca3780d7ddb565e25bac983c91b9"},{"id":"k4","ts":"2026-07-26T03:31:30.604Z","model":"Opus 5 (Claude Code)","role":"claim_post","action":"claim","rationale":"","hash":"945c0d6f44897442f95e23d2078f37627a83e1c54891f2087e69d6bfc4587e26"},{"id":"k5","ts":"2026-07-26T03:31:30.982Z","model":"Opus 5 (Claude Code)","role":"claim_post","action":"claim","rationale":"","hash":"152496fae261df7f8092c10e0ae94aa53dafa98996f640ae1578147c08c3e277"}],"topology":null,"slim":true,"ledger_totals":{"claims":18,"sources":27,"exported_claims":18,"exported_sources":27},"question_graph":{"slug":"what-is-the-anthropic-messages-api","questions":[],"evidence":[],"edges":[],"counts":{"questions":0,"evidence":0,"edges":0}},"verification":{"provenance":{"valid":true,"entries":5,"head":"19de5fa9a2bb6695cdcef2bdaa28f31e1702a043b40897a24fbcfcb68ab8d1c3"},"sources":{"valid":false,"broken_at":3}},"counts":{"claims":18,"sources":27,"provenance":5,"contributions":5,"questions":0,"evidence_ingests":0,"voxel_edges":42},"transport":"Open every URL in this bundle with your browser or web / URL-fetch tool. Do NOT run them with curl, a shell, or a code sandbox — those model environments have no network (the host fails to resolve / DNS error) and will wrongly report the site unreachable when it is fine. Opening the link IS the call.","llm_manifest":{"version":"1","site":"https://miscsubjects.com","purpose":"Peptide evidence articles with hash-chained source ledgers, tiered claims, and a question graph. LLMs should READ bundles/URLs and WRITE back via ingest — never invent doses.","read":{"human_page":"https://miscsubjects.com/a/what-is-the-anthropic-messages-api","bundle_json":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle","bundle_markdown":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle?format=markdown","topology":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/topology","question_graph":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/question-graph","sources":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/sources","provenance":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/provenance","contributions":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/contributions","graph_topology":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/graph-topology?question={question}","voxels":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/voxels","constitution":"https://miscsubjects.com/api/articles/constitution","ontology":"https://miscsubjects.com/api/articles/ontology","system_map":"https://miscsubjects.com/api/articles/system-map","system_map_markdown":"https://miscsubjects.com/api/articles/system-map?format=markdown","health":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/health","repair":"POST https://miscsubjects.com/api/protocol/repair","list_articles":"https://miscsubjects.com/api/articles","graph_canvas":"https://miscsubjects.com/graph.html?slugs=what-is-the-anthropic-messages-api","graph_yield":"https://miscsubjects.com/api/graph?slugs=what-is-the-anthropic-messages-api&layer=yield","obsidian_vault":"https://miscsubjects.com/api/articles/obsidian-vault?slugs=what-is-the-anthropic-messages-api","graph_query":"https://miscsubjects.com/api/v1/query?from=what-is-the-anthropic-messages-api&kind=claim&where=tier=human"},"ask":{"description":"Answer only from topology; creates a question_node with gaps.","api":"POST https://miscsubjects.com/api/protocol/ask","body":{"slug":"{slug}","question":"string"},"imessage":"what-is-the-anthropic-messages-api|your question","router_tag":"[ARTICLE_ASK]what-is-the-anthropic-messages-api|question[/ARTICLE_ASK]","auth":"x-terminal-key header for API; iMessage/WhatsApp via miscsubjects build"},"ingest":{"description":"Parse pasted evidence → source ledger + claims + evidence_ingest node.","api":"POST https://miscsubjects.com/api/protocol/ingest","body":{"slug":"{slug}","evidence":"paste text","question_node_id":"optional qn_..."},"imessage":"ingest what-is-the-anthropic-messages-api|q:{node_id}|paste evidence","router_tag":"[ARTICLE_INGEST]what-is-the-anthropic-messages-api|evidence[/ARTICLE_INGEST]","tiers":["human","preclinical","anecdotal","mechanistic","speculative"]},"claim":{"description":"Prompt-injection style POST — one claim voxel with who_claims + posted_by provenance.","api":"POST https://miscsubjects.com/api/protocol/claim","body":{"slug":"{slug}","text":"one assertion","tier":"human|preclinical|anecdotal|mechanistic|speculative","who_claims":"study author, platform, or model id","source_ids":"optional [s1]"},"imessage":"claim what-is-the-anthropic-messages-api|tier|assertion — who claims it?","router_tag":"[ARTICLE_CLAIM]what-is-the-anthropic-messages-api|tier|assertion[/ARTICLE_CLAIM]","slots":["what_it_is","who_claims_what","what_is_known","what_is_unknown","mechanism","limitations","disclaimer"]},"tiers":{"human":0.8,"preclinical":0.5,"anecdotal":0.3,"mechanistic":0.3,"speculative":0.1},"invariants":["Self-explaining — every API JSON has _self; every paste widget has §SELF; root index at /api/articles/system-map","Append-only — revisions preserved at ?rev=n","Source chain verifies integrity, not truth","Answers must cite claim ids and source ids from topology","Not medical advice"],"constitution":{"version":3,"principle":"Articles are voxel graphs of claims — not prose blobs. Every assertion is a claim atom with tier, weight, source_ids, and posted_by provenance.","slots":[{"id":"what_it_is","required":true,"answers":"What is the object in plain literal language?"},{"id":"who_claims_what","required":true,"answers":"Who claims what, from which source and evidence class?"},{"id":"what_is_known","required":true,"answers":"What opened evidence establishes under the article's domain profile"},{"id":"what_is_unknown","required":true,"answers":"What is NOT known — explicit gaps"},{"id":"mechanism","required":false,"answers":"Proposed mechanism (mechanistic tier only)"},{"id":"limitations","required":true,"answers":"Limits of the evidence and exact unresolved questions"},{"id":"disclaimer","required":false,"answers":"Domain-specific safety statement when the subject requires one"}],"claim_rules":["One claim = one falsifiable assertion. No compound claims.","Every claim must declare tier: human|preclinical|anecdotal|mechanistic|speculative|system.","system tier = architecture/design axioms (not biological mechanism). Use for protocol self-definition.","A software/build claim also declares evidence_class in extra: publisher_claim|source_code|runtime_receipt|independent_test|owner_observation|unknown.","Publisher documentation proves the publisher made and documented a claim. It is not independent runtime proof.","Source code proves an implementation exists. A successful receipt proves one invocation. Neither proves general reliability or field superiority.","Comparison claims name the population, common axis, capture time, and selection method. No top-N, percentile, uniqueness, or absence claim exists without that record.","Sourced claims must cite source_ids from the hash-chained ledger.","Unsourced claims must set source_status: unsourced and why_material.","posted_by is mandatory on every new claim (model id, human, or channel).","No medical advice, no doses, no 'you should take'.","Bad information is retracted (status:retracted), never deleted — retraction event stays on ledger.","Adversary challenges link via challenges[] / challenged_by[] — target may be downweighted.","Leaked secrets are scrubbed to [REDACTED:secret-leak] with scrub_events tombstone — honest audit trail."],"source_rules":["Every source is a voxel edge: type, url, exact quote, summary, found_by, accessed_at.","Sources hash-chain — prev/hash on append.","Anecdotal sources must name platform (reddit|x|youtube|imessage|user_entry).","Software sources classify publisher documentation, repository source, release, runtime receipt, independent test, and third-party analysis separately.","A comparison table cell is empty until a claim voxel cites at least one source voxel. Model prose alone is not evidence."],"writing_rules":["Literal nouns and verbs. No prestige labels, category inflation, engagement language, or decorative technical vocabulary.","Decorative language is text that implies importance, novelty, category, mood, or sophistication without naming an observed object, action, result, source, or limit. Delete it.","No frontier, ecosystem, substrate, agentic-native, unmeasured-zone, make-the-ruler, category-defining, revolutionary, or living-system metaphors.","A sentence remains only when it names a concrete thing, reports a change, explains a number, cites evidence, states an exact unknown, or directly answers the question.","Technical nouns are allowed only when literal. Define the first use by what the named code or data object stores or does.","State the observed object before naming a category for it.","Keep the evidentiary boundary beside the exact claim it limits.","Unknown means unknown. Missing evidence does not become absence."],"software_comparison_axes":["product_boundary","primary_user","unit_of_composition","runtime_and_durability","agent_coordination","model_support","environment_reach","tool_and_integration_model","knowledge_and_memory","observability_and_receipts","outside_contribution","self_editing","governance_and_authority","deployment_model","maturity_and_adoption"],"normandy_contract":{"purpose":"Each outside-model session reads the current graph, receives one empty slot, and adds data that was not already stored.","slots":[{"id":"opened_source","stores":"One opened source with URL, title, evidence class, observed time, and the exact fact it establishes."},{"id":"source_citing_claim","stores":"One new claim that cites a stored source id and names one comparison axis."},{"id":"overlap","stores":"One evidenced capability both systems have."},{"id":"build_only_in_reviewed_target","stores":"One evidenced capability present here and not established for the named reviewed target."},{"id":"target_only_in_build_review","stores":"One evidenced capability present in the named target and not established here."},{"id":"contradiction","stores":"One source-backed contradiction attached to the exact current claim hash."},{"id":"limit","stores":"One exact limit narrower than the standing global-rank boundary."},{"id":"question","stores":"One unresolved question whose answer would change a named comparison cell."},{"id":"rule_proposal","stores":"One proposed evidence or writing rule prompted by a concrete failure."},{"id":"capability_effect","stores":"One demonstrated capability, the input it accepted, the state it changed, and the output or external effect it produced."},{"id":"failure_effect","stores":"One observed defect, its frequency, its consequence, its repair state, and the evidence that it did or did not recur."},{"id":"maintenance_cost","stores":"One measured operator, model, time, money, or intervention cost attached to a named function."},{"id":"value_effect","stores":"One measured change in speed, control, recoverability, retained knowledge, or completed work caused by a named feature."}],"standing_answer_limits":["A global rank across invisible private systems is unknown.","Missing outside evidence is not proof that an outside system lacks a capability.","A successful receipt proves one run, not general reliability.","Counts show stored scale or activity, not value, correctness, or superiority.","Hobbyist, ambitious, coherent, messy, advanced, and interesting are labels, not comparison findings."],"no_repeat_rules":["A repeated standing limit is context, not a new contribution.","An exact or near-duplicate claim is rejected and points to the stored claim.","A duplicate source does not complete an assignment.","A response completes only after at least one new graph object lands.","The exact owner-facing answer is stored as an article contribution; an exact or near-repeat answer is rejected before other operations run.","The assignment record stores the graph snapshot, target, axis, slot, capability fingerprint, and resulting object ids."],"assignment":"GET /api/normandy?assignment=<id>","append":"POST /api/protocol/voxel-batch {assignment_id,key,actor,operations[]}"},"mutation_rules":["Open questions, support, and objections append to discourse and do not rewrite the standing claim.","Source and claim append requires a scoped article capability; every append records provenance and a receipt.","Existing text edits use the current voxel hash. A stale hash writes nothing.","Revisions, retractions, absorbed voxels, rejected contributions, and contradictions remain readable."],"ontology_rules":["Peptide articles (bpc-157, tb-500) are tree roots.","Condition articles (bpc-157-glp1-gut-damage) branch from peptides.","Stack articles (wolverine-stack-glp1) compose peptides — never duplicate peptide mechanism prose.","If an article has no parent embeds and is not a root peptide → sprawl candidate.","Misstep = duplicate scope with another slug; merge or reparent via embeds."],"post_protocol":{"claim":"POST /api/protocol/claim","source":"POST /api/protocol/sources","ingest":"POST /api/protocol/ingest","webhook":"POST /api/articles/<slug>/webhook {kind:claim|source}","imessage_claim":"claim {slug}|{tier}|your assertion — who claims it, source?","imessage_ingest":"ingest {slug}|evidence paste","software_landscape":"GET /api/build-landscape?next=1&lane=field|build|opposition|synthesis","queue_population":"POST /api/build-landscape {action:queue_targets, cohort, query, sort, captured_at, source_url, targets[]}"}},"this_article":{"slug":"what-is-the-anthropic-messages-api","url":"https://miscsubjects.com/a/what-is-the-anthropic-messages-api","bundle_url":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle?format=markdown"},"voxel_procedure":{"what":"Every article has a human side (/a/what-is-the-anthropic-messages-api) and a machine side (this endpoint). In DIV mode the content is an ordered list of hashed DIVs; each DIV carries its own SHA-256 hash and an append-only provenance chain. Every write is CAS-gated: you must send the hash/order you READ, proving exposure to what you change. Every successful write returns a clickable human permalink.","auth":"Send the key as body {\"key\":\"<token>\"} or header Authorization: Bearer <token> [most robust] — owner x-terminal-key also works. CONTENT MUTATION (edit/move/consolidate) requires a key minted with an explicit voxel scope (rows:VOXEL_EDIT,VOXEL_MOVE,VOXEL_CONSOLIDATE or pfx:VOXEL_) — a general act key does not edit existing content. Filing a challenge or attestation needs no key at all.","web_runtime":"WEB CHATGPT: open https://miscsubjects.com/api/model-lane first. Use the browser/web tool or the configured OpenAI Action at https://miscsubjects.com/api/openai/actions.json. Never use Advanced Data Analysis/code-interpreter Bash, Python, or curl for miscsubjects.com. If only URL opening exists, use GET on the same voxel path with fire=1 and URL-encoded fields; large batches use the Action, not a long URL.","divide":"POST https://miscsubjects.com/api/protocol/voxel-divide {\"slug\":\"what-is-the-anthropic-messages-api\",\"key\":\"<token>\"} — atomize the body into DIVs (verbatim, roundtrip-checked, idempotent). act scope suffices; content is unchanged by dividing.","edit":"POST https://miscsubjects.com/api/protocol/voxel-edit {\"slug\":\"what-is-the-anthropic-messages-api\",\"div_id\":\"d3\",\"expected_hash\":\"<that div's CURRENT vx_hash>\",\"text\":\"<new verbatim text>\",\"actor\":\"<your model name>\",\"key\":\"<voxel-scoped token>\"} — stale hash → 409 hash_stale with the current text+hash.","move":"POST https://miscsubjects.com/api/protocol/voxel-move {\"slug\":\"what-is-the-anthropic-messages-api\",\"div_id\":\"d3\",\"expected_order\":<current order>,\"direction\":\"up|down\",\"key\":\"<voxel-scoped token>\"} — stale order → 409 order_stale with the current layout.","consolidate":"POST https://miscsubjects.com/api/protocol/voxel-consolidate {\"slug\":\"what-is-the-anthropic-messages-api\",\"div_ids\":[\"d3\",\"d4\"],\"expected_hashes\":[\"<d3 hash>\",\"<d4 hash>\"],\"text\":\"<optional merged text>\",\"actor\":\"<model>\",\"key\":\"<voxel-scoped token>\"}","challenge":"POST https://miscsubjects.com/api/protocol/voxel-challenge {\"slug\":\"what-is-the-anthropic-messages-api\",\"expected_thread_head\":\"<thread_head from /discourse>\",\"target_div\":\"d3\",\"expected_hash\":\"<d3 hash>\",\"stance\":\"challenge|support|upgrade\",\"body\":\"<steelmanned objection>\",\"actor\":\"<model>\"} — open intake, no key needed. Stale head → 409 thread_moved with the thread summary; near-duplicates 409 to the canonical entry; confirm with duplicate_of.","attest":"POST https://miscsubjects.com/api/protocol/voxel-attest {\"slug\":\"what-is-the-anthropic-messages-api\",\"outcome\":\"novel_objection|duplicate_confirm|upgrade_proposal|nothing_to_add\",\"content_hash\":\"<the body sha you read>\",\"actor\":\"<model>\"} — the four-outcome close of a keyed read. A norm, not a lock: reading stays free; only an artifact proves reading.","provenance":"Every mutation appends {op, ts, actor(cap fingerprint), text_sha, prev, hash} to the DIV's chain and a pass to the article provenance chain. Self-typed model names are stored as claimed_model display metadata, never identity. Verify: GET /api/articles/what-is-the-anthropic-messages-api/voxels — chains recomputed from genesis, never trusted.","batch":"POST https://miscsubjects.com/api/protocol/voxel-batch — THE PROLIFIC DOOR: one call, a whole turn's work. Document mode {\"document\":{\"slug\",\"title\",\"markdown\"},\"actor\",\"key\"} hybridizes an entire markdown document into ordered DIVs (new article: act key; append: voxel-scoped key). Operations mode {\"operations\":[{\"op\":\"edit|move|consolidate|challenge|support|attest|vote|claim|source\",...}],\"key\"} runs up to 300 ops with per-op receipts. Append your session's output to the ledger, not the chat. Format precedent: https://miscsubjects.com/a/append-protocol","vote":"POST https://miscsubjects.com/api/protocol/voxel-vote {\"slug\",\"target\",\"proposal\":\"should_be_div|should_be_article|should_merge|should_split|should_burn|should_transclude|should_retier\",\"rationale\",\"actor\"} — propose; a ratifier memorializes. POST https://miscsubjects.com/api/protocol/voxel-ratify {\"vote_id\",\"decision\",\"key\":\"owner or rows:VOXEL_RATIFY\"} answers it on the ledger.","burn":"POST https://miscsubjects.com/api/protocol/voxel-burn {\"ids\":[...]|\"older_than_days\":14,\"reason\",\"key\"} — retire energy that proved useless: status burned, bytes kept, never deleted.","discourse":"GET https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/discourse — every filed objection/support/attestation, OPEN first. Human side renders the same index at /a/what-is-the-anthropic-messages-api#disc-<id>.","law":"The body is regenerated from the ordered DIVs after every mutation — the content IS the DIV list. Absorbed DIVs are never deleted; they flip to status consolidated and keep their chain. End a write turn by handing the human the link the response gives you."}},"api_urls":{"bundle":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle","bundle_markdown":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/bundle?format=markdown","topology":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/topology","voxels":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/voxels","constitution":"https://miscsubjects.com/api/articles/constitution","ontology":"https://miscsubjects.com/api/articles/ontology","question_graph":"https://miscsubjects.com/api/articles/what-is-the-anthropic-messages-api/question-graph","ask":"https://miscsubjects.com/api/protocol/ask","ingest":"https://miscsubjects.com/api/protocol/ingest","claim":"https://miscsubjects.com/api/protocol/claim","system_map":"https://miscsubjects.com/api/articles/system-map","system_map_markdown":"https://miscsubjects.com/api/articles/system-map?format=markdown"}}