# Anthropic API version 2026-10-21: what breaks and how to migrate

URL: https://infro.io/blog/anthropic-api-version-2026-10-21
Author: INFRO Editorial (https://infro.io/blog/editorial)
Publisher: INFRO
Published: 2026-10-27
Last modified: 2026-10-27
Last reviewed: 2026-10-27 (next review due 2026-11-26)
Topic: Architecture and migration
Format: Guide

> Requests sent with anthropic-version 2026-10-21 return a 400 error if they include temperature, top_p or top_k (even at the default value), place a document block directly in an assistant message, or send a text block with non-empty citations in a user message. The new SDK majors (Python 2.0.0, TypeScript 1.0.0 and the others) send this version by default and also move the API key to Authorization: Bearer. Nothing forces the change: 2023-06-01 keeps working, and Claude 4.7 and later models already sample only at the defaults, so on them removing the parameters changes nothing.

Key takeaways:
- On anthropic-version 2026-10-21, sending temperature, top_p or top_k returns a 400 on every model, even at the default value.
- A document block placed directly in an assistant message, and a text block with non-empty citations in a user message, also return a 400.
- The new SDK majors send 2026-10-21 by default and send the API key as Authorization: Bearer, which breaks proxies that only read X-Api-Key.
- On Claude 4.7 and later nothing about sampling changes; on older models such as Claude Sonnet 4.6 a lowered temperature loses its effect and no other setting replaces it.
- Effort is not a temperature substitute: it controls how many tokens Claude spends, not how random the output is.

Anthropic's API version `2026-10-21` makes three kinds of request that used to work return a `400`: any request that sends `temperature`, `top_p` or `top_k`; a `document` block placed directly in an `assistant` message; and a `text` block with a non-empty `citations` array in a `user` message[1]. You get the new version when you send `anthropic-version: 2026-10-21` yourself, or when you upgrade to one of the new SDK majors, which send it by default. Nothing forces the move: `2023-06-01` still works, and the migration guide tells you to keep a request on it if that request relies on a non-default temperature[1].

This guide is for the developer who has to bump the SDK and the lead who has to approve it: what changed, where the affected calls hide, what to use instead, and how to test before release.

## What changes on 2026-10-21

The Messages API changes apply to `POST /v1/messages`, to token counting, and to every request inside a Message Batch created with the new version[1]. Anthropic's versions page lists the same three rules and adds that the sampling parameters return a 400 "on every model"[2].

| Request shape | On `2023-06-01` | On `2026-10-21` |
| --- | --- | --- |
| `temperature`, `top_p` or `top_k` present | Accepted where the model takes it | `400`, even at the default value |
| `document` block directly in an `assistant` message | Accepted | `400`; send documents in `user` messages |
| `text` block with non-empty `citations` in a `user` message, including inside `search_result` | Accepted | `400`; remove `citations` from those blocks |
| Citations on `assistant` text you send back | Accepted | Still accepted |
| `"citations": {"enabled": true}` on documents and search results | Accepted | Still accepted |
| A document nested in another block, such as a web fetch result Claude returned | Accepted | Still accepted |

Table: Messages API changes, from Anthropic's migration guide and versions page, read 2026-10-27.

The Admin API and the Claude Enterprise Analytics API also drop old field names on the new version: `roles` becomes `role_ids`, `group_id` becomes `rbac_group_id`, an RBAC role's `name` becomes `display_name`, rate-limit entries lose `group_type` for `group.type`, and API keys lose `workspace_id` in favour of `scope`[1]. If you have an internal tool that lists keys or workspaces, it is in scope too. The `workspace_id` change has a trap: on `2023-06-01` a `null` meant the Default Workspace or an all-workspaces key; on the new version a key bound to the Default Workspace carries the workspace's real id in `scope.workspace_id`, and an all-workspaces key has `scope` `{"type": "organization"}`[1].

### What it means for sampling on each model

Removing the three parameters is not the same change on every model. Anthropic is explicit: without them a request samples at the defaults, including a `temperature` of 1.0, exactly like a `2023-06-01` request that leaves them out. Claude 4.7 and later models already accept only the defaults, so they "sample as before". On a model that accepts other values, such as Claude Sonnet 4.6, a request that lowered `temperature` for more consistent output loses that effect, and "no other setting replaces it"[1].

The current lineup (Claude Fable 5.1, Opus 5.5, Sonnet 5.5 and Haiku 5.5) is all on the 4.7-and-later side[3]. For traffic on those models, the version change is mostly about deleting parameters that were already doing nothing beyond their defaults. The risk sits with older models still in use and with code paths you forgot send a temperature at all.

## What the new SDKs change besides the header

Each SDK's first release on `2026-10-21` is a new major version: `anthropic` 2.0.0 for Python, `@anthropic-ai/sdk` 1.0.0 for TypeScript, Go 2.0.0 (module path ending in `/v2`), `anthropic-java` 3.0.0, the C# package 13.0.0, PHP 1.0.0, Ruby 2.0.0, and the `ant` CLI 2.0.0[1]. Three of the accompanying changes catch teams that only expected the API rules.

- **The sampling parameters are gone from the SDK.** As of the new majors, the SDKs and the CLI "no longer have the three parameters"[1]. In a typed codebase that is useful: the compiler finds the call sites for you. Code that passes extra fields through an untyped dictionary or an extra-body escape hatch is not caught that way and fails at the API instead.
- **The key moves to `Authorization: Bearer`.** The SDKs and the CLI now send the API key as a bearer token instead of `X-Api-Key`. Any proxy, gateway, middleware, log filter or test stub that reads `X-Api-Key` must read `Authorization` instead, or you set `X-Api-Key` yourself. The Claude API itself accepts either header[1].
- **Companion packages move together.** In TypeScript, v1 of the Bedrock, Vertex, Foundry, AWS and Google Cloud packages needs v1 of `@anthropic-ai/sdk`; upgrade one without the others and the package manager installs a second, older copy[1].

The guide also lists SDK-only changes: per-role message types, removal of the legacy Text Completions API from several SDKs, and removal of client-side compaction in the TypeScript and Ruby tool runners in favour of server-side compaction[1]. Read the section for your language before you open the pull request.

On Amazon Bedrock, `2026-10-21` exists only for Claude 4.7 and later. Calls to older Claude models on Bedrock should stay on the SDK version or header they use today until they move to a newer model[1].

## Find every affected call site

The calls that fail after an SDK bump are rarely the ones in your main service. They are in a helper that sets `temperature=0` "for determinism", a batch job, an eval harness, or a framework adapter that fills in a default you never wrote.

### Search the code

Start with a literal search across every repository, including notebooks and infrastructure code:

```bash
# Sampling parameters near Anthropic calls (review each hit by hand).
rg -n --hidden -g '!node_modules' -g '!*.lock' \
  -e '\b(temperature|top_p|top_k|topP|topK)\b' \
  -e 'anthropic-version' \
  -e '(x-api-key|X-Api-Key)'

# Documents in assistant turns and citations sent back in user turns.
rg -n --hidden -g '!node_modules' -e '"type":\s*"document"' -e 'citations'
```

Then look where the values are not literals: shared client wrappers, prompt-template files and stored prompt configurations, feature flags and remote config that carry model settings, and the configuration of any agent or LLM framework you call Claude through. Many frameworks expose `temperature` as a model setting; check whether yours sends one when you leave it unset, in the version you run, by reading its request logging or source rather than assuming.

### Search the traffic

Code search shows what could be sent; traffic shows what was. If you log outgoing request bodies, or a gateway records them, count Claude requests in the last 30 days that carry any of the three parameters, grouped by service and model. Do the same for request bodies that send a `document` block in an `assistant` turn. A conversation store that replays Claude's earlier replies with their citations is fine; a pipeline that copies cited text into the next `user` message is not.

### Check the auth path

List every hop between your code and Anthropic: corporate egress proxies, API gateways, logging middleware, mock servers in tests. Any of them that keys on `X-Api-Key` needs a change before the SDK upgrade ships.

## What to use instead

**Drop the parameters on Claude 4.7 and later.** They were already pinned to the defaults there, so removing them changes nothing about sampling[1].

**Use structured outputs for consistent shape.** Much of the `temperature=0` in production code exists to stop a parser from breaking. Claude's structured outputs constrain the response to a JSON schema with `output_config.format` set to `{"type": "json_schema", "schema": {...}}`, and strict tool use sets `"strict": true` on a tool definition; the feature is generally available on the current models[4]. A schema guarantees the shape, not the content, so keep validating values.

**Use effort for spend and depth, not randomness.** `output_config.effort` (`low`, `medium`, `high`, `xhigh`, `max`) controls how many tokens Claude spends on a response, thinking and tool calls included. Claude Opus 5.5 and Haiku 5.5 default to `medium`, other models to `high`[5]. It is a useful setting to make explicit during the same migration, but it is not a replacement for a lowered temperature, and Anthropic does not present it as one.

**Keep a request on 2023-06-01 when it truly needs the parameter.** On a model such as Claude Sonnet 4.6, if a lower temperature measurably matters to a task, the documented option is to keep that request on the old version[1]. Treat that as a pin with an owner and a review date, and plan the model move that makes it unnecessary.

```python
# Before: anthropic 1.x, anthropic-version 2023-06-01
client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=2048,
    temperature=0,          # removed in 2.0.0; a 400 on 2026-10-21
    messages=messages,
)

# After: anthropic 2.0.0, anthropic-version 2026-10-21
client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=2048,
    output_config={
        "effort": "medium",  # explicit spend and depth, not randomness
        "format": {"type": "json_schema", "schema": TICKET_SCHEMA},
    },
    messages=messages,
)
```

## A test plan before release

1. **Inventory.** Run the code, config and traffic searches above. Give every hit an owner.
2. **Upgrade in a branch.** Move the SDK and every companion package in one change, fix compile errors, and remove the three parameters everywhere.
3. **Replay recorded requests.** Send a few hundred recorded requests per workload through the new SDK against a staging key. Any `400` names a call site the searches missed.
4. **Compare outputs where sampling changed.** For calls to models older than 4.7 that used a non-default temperature, compare task success, parse failures and output tokens per request before and after. On 4.7 and later models expect no difference.
5. **Test the auth path end to end.** Through every proxy and in CI, not only from a laptop that talks to Anthropic directly.
6. **Release with the fixes.** Anthropic's own guide says to release the SDK upgrade together with the code fixes[1]; a staged SDK bump without them is a staged outage.
7. **Watch for a week.** Alert on Anthropic `400` errors by service and on any change in output tokens per request.

## Running Claude through INFRO during the change

INFRO is a control plane that sits between your applications and the provider accounts you already hold; you connect your own Anthropic account and Anthropic bills you directly. Two of its paths matter here, and they behave differently.

**OpenAI-compatible chat (`/v1/chat/completions`).** When the model that serves a request refuses a sampling parameter, INFRO does not send it. For Claude 4.7 and later (Opus 4.7 and 4.8, the Claude 5 family, Fable) it drops `temperature`, `top_p` and `top_k`, and for Claude 4.5 and 4.6 it keeps `temperature` and drops `top_p` when both are sent. The response lists what was dropped in the `X-INFRO-Params-Dropped` header, for example `X-INFRO-Params-Dropped: temperature, top_p`, so you can find callers still sending them without a 400. Only sampling parameters are ever dropped; a refused `stop`, `tools` or `response_format` reaches you as the provider's `400`. See [chat completions](https://infro.io/docs/api/chat-completions).

**Anthropic's own shape (`/v1/messages`).** For Claude Code, the Agent SDK and code written against Anthropic's SDK, INFRO accepts the key as `x-api-key` or `Authorization: Bearer`, so the new SDK majors authenticate without a change. On an Anthropic connection the body reaches Anthropic as written, so INFRO does not strip parameters on this path. INFRO accepts the `anthropic-version` header and pins the version it sends to Anthropic itself (2023-06-01 when this was written), so a request through this path is evaluated under that version, not the one your SDK sent. INFRO therefore does not give you 2026-10-21 behaviour today, and a non-default temperature sent to a Claude 4.7 or later model is still refused by Anthropic. See [coding agents](https://infro.io/docs/coding-agents).

Either way, the [request log](https://infro.io/docs/observability/traces) records each request with its model, key and status, which gives you the traffic inventory in step 1 for whatever goes through INFRO. Calls made straight to Anthropic do not appear there.

## Questions

### Do I have to move to anthropic-version 2026-10-21?

No date forces it. Anthropic recommends the latest version, but 2023-06-01 keeps working, and the migration guide itself suggests keeping a request on 2023-06-01 if it depends on a non-default temperature. You move when you upgrade to the new SDK majors or change the header yourself.

### Why does my request fail with a 400 about temperature after upgrading the Anthropic SDK?

The new SDK majors (Python 2.0.0, TypeScript 1.0.0, Go 2.0.0, Java 3.0.0, C# 13.0.0, PHP 1.0.0, Ruby 2.0.0) send anthropic-version 2026-10-21, and on that version any temperature, top_p or top_k returns a 400, even at the default value. Remove the parameter from the request, including any a wrapper or framework adds for you.

### What replaces temperature on Claude?

Nothing, according to Anthropic's guide: a request without the parameters samples at the defaults, including a temperature of 1.0. If you used a low temperature for consistent formatting, constrain the format with structured outputs instead; if you need it for anything else, keep that request on 2023-06-01 and test whether the model still needs it.

### Does the version change affect Claude on Amazon Bedrock?

On Bedrock, 2026-10-21 is available only for Claude 4.7 and later models. Calls to older models on Bedrock should stay on the SDK version or header they use today until they move to a 4.7 or later model.

### Does the new SDK break my proxy or gateway?

It can. The new majors send the API key as Authorization: Bearer instead of X-Api-Key. A proxy, log filter or test stub that only reads X-Api-Key stops seeing the key. INFRO's /v1/messages accepts either header.

## Sources

1. Migrating to API version 2026-10-21 — Anthropic. https://platform.claude.com/docs/en/api/migration-2026-10-21 (accessed 2026-10-27)
2. Versions — Anthropic. https://platform.claude.com/docs/en/api/versioning (accessed 2026-10-27)
3. Models overview — Anthropic. https://platform.claude.com/docs/en/about-claude/models/overview (accessed 2026-10-27)
4. Structured outputs — Anthropic. https://platform.claude.com/docs/en/build-with-claude/structured-outputs (accessed 2026-10-27)
5. Effort — Anthropic. https://platform.claude.com/docs/en/build-with-claude/effort (accessed 2026-10-27)
