TL;DR: A Claude API request needs three fields: model, max_tokens, and messages. The system parameter is a top-level field, not a message role. And on every Claude model released after Opus 4.6 (Sonnet 5, Opus 5, Opus 5.5, both Fable 5 models), temperature, top_p, and top_k are deprecated: only the default value is accepted, anything else returns a 400. Verified against Anthropic's own docs, September 25, 2026.
If you last touched the Claude API a year ago, or you're coming from another provider's SDK, several things that used to be true no longer are. This is the current shape of a basic request: what's required, where the system prompt actually lives, and the single most surprising trap for anyone who assumes temperature behaves the way it always has.
None of this requires spending a production API key to follow along. Every request and response shape below is the documented contract from Anthropic's own reference, built to be pasted into your own test call rather than reproduced from a live one here.
What Does a Basic Claude API Request Actually Look Like?
Every Claude API call is a POST to /v1/messages. Three fields are required: model, max_tokens, and messages.
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-5-5",
"max_tokens": 1000,
"messages": [
{ "role": "user", "content": "Explain what a race condition is, in two sentences." }
]
}'
max_tokens has no server-side default. Anthropic's own Messages API reference lists it as required, so a request that omits it is rejected before Claude ever sees your prompt, not silently capped at some sensible number. It's worth setting it generously rather than lowballing it: hitting the cap truncates the response mid-thought, stop_reason comes back as "max_tokens" instead of "end_turn", and you're stuck retrying the whole call.
model takes an exact API ID string, such as claude-opus-5-5 or claude-sonnet-5. As of the models overview page, accessed September 25, 2026, Anthropic's own comparison table recommends starting with Claude Opus 5.5 for most workloads and reaching for Claude Fable 5.1 for demanding, long-horizon reasoning work; Claude Sonnet 5 is positioned as the speed-and-intelligence balance, and Claude Haiku 4.5 as the fastest option. None of the four is "the newest" in a way that stays true for long, so treat the model ID and this access date as the fact, not the label.
The response back is a JSON object, not just a string. The parts worth reading in code rather than printing straight to a log are content (an array of blocks, almost always starting with one {"type": "text", ...} block for a plain request), stop_reason ("end_turn" on a normal finish, "max_tokens" if the cap was hit, "tool_use" if Claude wants to call a tool), and usage (input_tokens and output_tokens, plus cache-related fields once caching is involved). Reading content[0].text and ignoring everything else works for a demo; reading stop_reason too is what keeps a production loop from silently shipping a truncated answer.
How Does the Messages API Structure a Conversation?
messages is an array, and each entry needs a role ("user" or "assistant") and a content. Content can be a plain string for simple text, or an array of typed blocks when you need more than one kind of content in a turn:
[
{ "role": "user", "content": "Hello there." },
{ "role": "assistant", "content": "Hi, how can I help?" },
{
"role": "user",
"content": [
{ "type": "text", "text": "What's in this image?" },
{ "type": "image", "source": { "type": "url", "url": "https://example.com/diagram.png" } }
]
}
]
Claude is trained on strictly alternating user/assistant turns. If your code accidentally appends two user messages in a row (a common bug in agent loops that assemble history from several sources), the API doesn't reject the request: it combines the consecutive same-role entries into one turn. That's convenient for not crashing, but it also means a structural bug in your message assembly can go unnoticed for a while, since nothing errors to flag it.
A basic prompting guide only needs a handful of the content-block types the schema supports, but it's worth knowing the full shape exists before you hit it:
| Block type | Carried by | What it's for |
|---|---|---|
text | user, assistant | Plain prompt or response text; the default for a simple string content |
image | user | A photo, screenshot, or diagram, passed by URL, base64, or a Files API file_id |
document | user | A PDF or plain-text file, same three source options as image |
tool_use | assistant | Claude's request to call one of the tools you defined |
tool_result | user | The output your code sends back after actually running that tool |
You won't need tool_use or tool_result for a plain question-answering request like the one above; they only appear once you've declared tools on the request and Claude decides to call one. A single assistant turn can also contain more than one tool_use block at once (parallel tool calls), which is why a tool-use loop collects every result into one combined user message rather than sending them back one at a time.
One more content-block type worth knowing early: ending the array with an assistant-role message used to be a common way to force Claude to continue from specific text (a "prefill"). On every current-generation model, that pattern is gone. Sending a trailing assistant message with content in it now returns a 400 rather than a continuation, on Claude Opus 5, Opus 5.5, Sonnet 5, and both Fable 5 models. If you're steering the exact shape of a response, structured outputs (output_config.format) or explicit prompt instructions do the job prefill used to.
What Does the system Parameter Actually Do?
This is the part that trips up developers coming from providers that put a "system" role directly inside the message array. Claude doesn't work that way. system is a separate, top-level field on the request, not a role you assign to a message:
{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"system": "You are a precise, terse code-review assistant. Flag correctness issues before style issues.",
"messages": [
{ "role": "user", "content": "Review this function for bugs." }
]
}
Per Anthropic's Messages API reference, there is no "system" role for input messages at all; a message with role: "system" is not the documented way to set instructions. system also accepts an array of text blocks instead of a plain string, which matters only when you want to attach a cache_control breakpoint to it, so a large, mostly-static system prompt gets reused across requests instead of reprocessed on every call.
There's no published character limit on the system field itself in Anthropic's Messages API reference. The one nearby number that does exist, a 3,000-character cap, applies to a different, separate feature entirely (organization-level instructions on Team and Enterprise claude.ai accounts), not to the API's system parameter, per this site's own prior research into Anthropic's docs (verified September 3, 2026; not independently re-fetched for this specific point). Don't borrow that number as a request-size limit; it isn't one.
For a deeper look at what belongs in a Claude system prompt specifically, versus a claude.ai Project's custom instructions or a CLAUDE.md file for Claude Code, see Claude system prompts: what belongs there.
Can You Still Set temperature on the Claude API?
Here's the part most likely to break code written even a few months ago. temperature, top_p, and top_k are not universal, timeless sampling knobs anymore. Per Anthropic's Messages API reference, accessed September 25, 2026, all three are deprecated on every model released after Claude Opus 4.6.
| Model | Claude API ID | temperature / top_p / top_k | Thinking |
|---|---|---|---|
| Claude Opus 5.5 | claude-opus-5-5 | Rejected (400) except the default temperature: 1.0 | Adaptive, always on, effort defaults to medium |
| Claude Sonnet 5 | claude-sonnet-5 | Rejected (400) except the default | Adaptive, effort defaults to high |
| Claude Fable 5.1 | claude-fable-5-1 | Rejected (400) except the default | Adaptive, always on |
| Claude Opus 4.6 | claude-opus-4-6 | Allowed, 0.0-1.0, default 1.0 | Adaptive optional; budget_tokens deprecated, not removed |
| Claude Haiku 4.5 | claude-haiku-4-5 | Allowed, 0.0-1.0, default 1.0 | Extended thinking via budget_tokens |
Source: platform.claude.com/docs/en/api/messages, accessed September 25, 2026.
This isn't a Prompt Architects house opinion; it's consistent with what Anthropic's own reference states and with what two other posts on this site already verified against the same source in early September 2026. For the full conceptual explainer of what temperature, top-p, and top-k actually do, and how the same deprecation plays out on OpenAI's and Google's APIs, see temperature, top-p, top-k explained and provider settings compared.
So How Do You Control Output Style Without temperature?
On a current-generation model, you don't reach for a sampling parameter at all. Two things stand in for what temperature used to do:
Prompt instructions. Telling Claude directly how exploratory or how conservative to be ("give the single most likely answer" versus "brainstorm several distinct options") does the work that lowering or raising temperature used to. This is more reliable on reasoning models generally, not just Claude: forcing a fixed sampling temperature can interfere with a model's internal reasoning passes, which is part of why several vendors deprecated it around the same time.
The effort parameter. Set inside output_config, effort runs from low through max and controls how much the model reasons before answering, trading cost for thoroughness rather than trading determinism for randomness. It's a different axis from what temperature controlled, and it's the one still available to tune on every current model.
{
"model": "claude-opus-5-5",
"max_tokens": 4096,
"thinking": { "type": "adaptive" },
"output_config": { "effort": "high" },
"messages": [{ "role": "user", "content": "..." }]
}
If you only need one current model that still takes real sampling parameters, that's Claude Haiku 4.5. It predates the Opus 4.6 cutoff and accepts temperature from 0.0 to 1.0 the way older documentation describes.
What Replaced budget_tokens for Extended Thinking?
The older pattern for extended thinking, thinking: {"type": "enabled", "budget_tokens": N}, is gone on current models. budget_tokens returns a 400 on Claude Opus 5, Opus 5.5, Sonnet 5, and both Fable 5 models. The replacement is adaptive thinking, where Claude decides its own reasoning depth:
// Before (older models, and Opus 4.6/Sonnet 4.6 as a deprecated transitional option only)
{ "thinking": { "type": "enabled", "budget_tokens": 8000 } }
// Current (Opus 5, Opus 5.5, Sonnet 5, Fable 5 / 5.1)
{ "thinking": { "type": "adaptive" }, "output_config": { "effort": "high" } }
budget_tokens still works, though it's marked deprecated, on Claude Opus 4.6 and Sonnet 4.6 specifically, as a transitional option for code that hasn't been re-tuned to effort yet. It is fully removed everywhere else in the current lineup.
What Other Basic Parameters Should You Know About?
Two smaller fields round out a basic request, and neither has changed shape recently:
stop_sequences is an array of strings that ends generation early if Claude produces one of them. When a stop sequence fires, the response's stop_reason comes back as "stop_sequence" rather than the normal "end_turn", and the field stop_sequence in the response tells you which string actually matched, since you can supply more than one candidate at once.
metadata currently supports one field, user_id, an opaque external identifier (a UUID or a hash, not a name or email address) that Anthropic's own documentation says helps it detect abuse patterns across requests. It has no effect on the model's output; it's purely an operational signal you're encouraged to send, not a prompting parameter.
What Else Changes If You're Coming from an Older Claude Model?
Beyond sampling and thinking, two more shapes moved:
Structured output. The parameter is now output_config.format, not the older, deprecated output_format. If you're constraining Claude to return valid JSON against a schema, that's where the schema goes on a current request.
Assistant prefill. Ending a request with a populated assistant-role message to force a continuation returns a 400 on every current-generation model, as covered above. Move that logic into output_config.format or an explicit instruction in the prompt itself.
None of these four changes announce themselves. Old code keeps compiling, since the SDKs still define the deprecated fields for backward compatibility; the failure only shows up as a runtime 400 the first time that code actually calls a current model.
Where to Go Next
This page covers the request shape: what's required, where instructions live, and which parameters still do anything. A few adjacent topics are deliberately out of scope here and covered elsewhere on this site. If you're steering Claude with less instruction rather than more (a genuinely different skill from getting the request syntax right), advanced ChatGPT prompting past the basics covers the mirror-image techniques on OpenAI's side, and much of it transfers directly. If you want Claude to remember context across separate chats rather than resending it in system on every call, that's a different product surface entirely, covered in Claude Projects: prompting with project knowledge. And if your actual bottleneck is fitting a large document into the request rather than any parameter covered here, long-context prompting with Claude covers what a 1M-token context window does and doesn't solve on its own, since a bigger window changes what fits, not how reliably Claude recalls what you put in it.
The throughline across all of it: the request shape itself (three required fields, a top-level system, alternating roles) has stayed remarkably stable across model generations. What keeps changing underneath it is which control parameters still do anything, and that's exactly the kind of fact worth re-checking against the current docs before you ship, not carrying forward from whatever was true the last time you looked.
Stop rewriting prompts. Start shipping.
Works with ChatGPT, Claude, Gemini, Grok, Midjourney, Ideogram, Veo3 & Kling. 4.8★ on the Chrome Web Store.
Create An Account