Claude API version 2026-10-21 returns a 400 for temperature. Find every call before the SDK bump does
The first new Anthropic API version since 2023 removes sampling parameters and moves SDK auth to a bearer header. A 40-line audit script finds the call sites in a few minutes.

On 21 October 2026 Anthropic shipped API version 2026-10-21, the first new version since 2023-06-01, and it isn’t a drop-in. A request that sends temperature, top_p or top_k returns a 400 error, even at the default value. Eight official libraries released new major versions the same day, and each one sends the new version by default.
So the risky moment isn’t choosing to adopt the new version. It’s the routine dependency bump that pulls in anthropic 2.0.0 or @anthropic-ai/sdk 1.0.0 and quietly changes what goes over the wire. Here’s what changes, what doesn’t, and a script that finds the call sites first.
What breaks at the API level
Anthropic’s migration guide lists three changes to the Messages API, token counting and each request in a Message Batch created with the new version.
Sampling parameters are gone. temperature, top_p and top_k are rejected on every model. On models that already accept only the defaults, such as Claude 4.7 and later, nothing changes in behaviour, because those requests sample the same way without the parameters. On models that accept other values, Claude Sonnet 4.6 being the guide’s example, a request that lowered temperature for more consistent output loses that effect, and the guide says no other setting replaces it. If a request depends on a non-default value, the guide’s advice is to stop sending the parameter or keep that request on 2023-06-01.
A document block placed directly in an assistant message returns a 400. Documents belong in user messages. A document nested inside another block, such as a web fetch tool result Claude returned, is still accepted.
A text block with a non-empty citations array in a user message returns a 400, including inside search_result blocks. Citations on assistant text blocks, the kind you get back from Claude and replay in history, still work, and so does "citations": {"enabled": true} on documents and search results.
There’s also a set of renamed response fields in the Admin API and the Claude Enterprise Analytics API (for example actor.email becomes actor.email_address, and an API key’s workspace_id is replaced by scope). Those only matter if you read those endpoints.
What breaks in the SDKs, regardless of version
The release notes say the new SDK and CLI versions carry breaking changes that don’t depend on the API version. Two are worth a grep before you merge a bump.
The first is authentication. The SDKs and the ant CLI now send the key as Authorization: Bearer <key> instead of X-Api-Key. The API accepts either header, so Anthropic’s side is fine. Yours may not be: any proxy, gateway, log filter, middleware or test stub that reads or sets X-Api-Key stops seeing the key. A log filter that redacts X-Api-Key is the sharp example: it no longer matches the header that now carries the key. The guide documents a way to keep sending X-Api-Key yourself. The Foundry clients still send x-api-key by default.
The second is that a client now holds one credential. In the Python SDK, passing both api_key and auth_token to the constructor raises a ValueError. Version 1 sent both, each in its own header. If a setup passed both on purpose, it needs to choose.
The rest is type-level and language-specific: MessageParam is now a union with one type per role, one-value enums became constants, betas is gone from the non-beta Models methods, and Text Completions is removed. The Go module path is github.com/anthropics/anthropic-sdk-go/v2, so every import changes. The SDKs and CLI are also now licensed under Apache 2.0 instead of MIT, which matters only if you track dependency licences.
Two traps in the guide are easy to miss. The old go install path for the CLI keeps installing the latest v1 release with no error or warning, so a Go-based CI image can silently stay behind. And in PHP, composer update alone stays within your current version constraint, so you need composer require "anthropic-ai/sdk" to get 1.0.0.
Audit before you bump
The cheap move is to find every call site that the new version rejects or reroutes, then decide per call site. This script walks a directory and prints a line for each match. It checks three things: sampling parameters, x-api-key handling and hard-coded anthropic-version pins.
import re, sys, pathlib
CHECKS = {
"sampling parameter (400 on 2026-10-21)": r"\b(temperature|top_p|top_k|Temperature|TopP|TopK)\b",
"X-Api-Key handling (SDKs now send Authorization: Bearer)": r"x-api-key",
"pinned anthropic-version": r"anthropic-version",
}
SKIP = {"node_modules", ".git", "bin", "obj", "dist"}
for path in pathlib.Path(sys.argv[1]).rglob("*"):
if not path.is_file() or SKIP & set(path.parts):
continue
try:
lines = path.read_text(encoding="utf-8").splitlines()
except (UnicodeDecodeError, OSError):
continue
for n, line in enumerate(lines, 1):
for label, pattern in CHECKS.items():
if re.search(pattern, line, re.IGNORECASE if "x-api" in pattern or "version" in pattern else 0):
print(f"{path}:{n}: {label}")
Run against a small sample project with a C# service that sets temperature and pins the version header, a TypeScript call that sets top_p, and an nginx gateway config that sets X-Api-Key, it prints:
proj/infra/gateway.conf:1: X-Api-Key handling (SDKs now send Authorization: Bearer)
proj/src/Summariser.cs:1: sampling parameter (400 on 2026-10-21)
proj/src/Summariser.cs:2: pinned anthropic-version
proj/src/chat.ts:1: sampling parameter (400 on 2026-10-21)
It’s a grep with opinions, not a parser. The sampling check will flag unrelated variables named temperature (a weather service, say), and it won’t see a parameter built dynamically or passed through a wrapper. Treat hits as a worklist to read, and run it over your infrastructure and test folders as well as the application code, since the header problem lives there.
A pinned anthropic-version: 2023-06-01 line is a different kind of hit. Code that builds raw HTTP requests keeps working on the old version, and the versions page lists 2023-06-01 as the previous version without announcing a retirement. But Anthropic recommends the latest version, so a hard-coded pin is a decision someone should make deliberately.
Let the agent do the first pass
Claude Code 2.1.307 added /claude-api api-version. According to the Claude Code skills docs, it updates your Claude API code for a newer API version and then switches your requests to that version. It needs v2.1.307 or later, and it belongs to the same bundled /claude-api skill as migrate, which moves code to a newer model.
Run the audit script first and give the agent its output. That’s an opinion, not a documented requirement, but it works for a plain reason: the script’s list is exhaustive and cheap, while the agent’s judgement is what you want for the hard calls, such as a request that relied on temperature: 0.2 for consistent output on an older model. The guide says nothing replaces that parameter, so the honest options are to accept the new behaviour, change the prompt, or leave that one call on the old version.
Review the diff the way you’d review any migration. Pay attention to the calls where the agent deleted temperature: each one is a behaviour change on models that accepted other values, not a cleanup.
Two caveats for cloud platforms
On Amazon Bedrock, 2026-10-21 is available only for Claude 4.7 and later models. If you call an older model there, the guide says to stay on your current SDK version, or keep sending the version you send today if you set it yourself, until you switch those calls to a 4.7 or later model. A repo that mixes models across regions can therefore end up needing two SDK versions side by side.
The version is also not a rollback switch. Reverting only the header doesn’t bring back SDK methods and types the new majors removed, so pin the SDK in the same commit you’d revert.
Try this today
Run the audit script over your repo and your gateway configs, list every hit, and open the migration guide’s breaking-changes section next to it. Do that before the dependency bot opens its pull request, not after.