← Blog

Claude API Request Body Format: Full Example Guide

2026-10-07 · 4 min read · SubToAPI Team

The Claude API Request Body Format

A Claude API request body is a JSON object sent to the /v1/messages endpoint. At minimum it needs three fields: model, max_tokens, and messages. The messages field is an array of objects, each with a role (user or assistant) and content, which can be a plain string or an array of content blocks for more advanced use cases like images or tool results.

Here's the simplest valid request body:

{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "messages": [
    { "role": "user", "content": "Explain what a REST API is in two sentences." }
  ]
}

That's the core shape you'll use for 90% of requests. Everything else — system prompts, tool definitions, multi-turn history, streaming — builds on top of this same structure. Let's go through each field and the common variations you'll actually need.

Required Fields

model

A string identifying which Claude model to use, e.g. claude-sonnet-4-5 or claude-opus-4. If this is omitted or misspelled, you'll get a validation error, not a fallback.

max_tokens

An integer capping the length of the model's response. This isn't optional — Claude's API rejects requests without it. It doesn't guarantee that many tokens will be generated; it's a ceiling, not a target.

messages

An array of turn objects. Roles alternate between user and assistant. You don't send a system role inside this array — that's a separate top-level field (covered below).

Each message's content can be:

Example with multi-turn history:

{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "messages": [
    { "role": "user", "content": "What's the capital of Portugal?" },
    { "role": "assistant", "content": "Lisbon." },
    { "role": "user", "content": "And its population?" }
  ]
}

Optional Fields You'll Use Often

system

A top-level string (or array of blocks) that sets behavior and context before the conversation starts. It is not part of messages.

{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "system": "You are a concise technical writer. Answer in bullet points only.",
  "messages": [
    { "role": "user", "content": "Summarize the benefits of HTTP/2." }
  ]
}

temperature

A float between 0 and 1 controlling randomness. Lower values (0–0.3) are better for deterministic tasks like extraction or classification; higher values (0.7–1) suit creative writing.

stop_sequences

An array of strings that, if generated, stop the response immediately.

stream

A boolean. When true, the response comes back as server-sent events instead of a single JSON object — useful for chat UIs where you want tokens to appear incrementally.

Content Blocks: Images and Tool Use

When content needs to carry more than text, it becomes an array of typed blocks.

Image input example:

{
  "role": "user",
  "content": [
    { "type": "text", "text": "What's in this image?" },
    {
      "type": "image",
      "source": {
        "type": "base64",
        "media_type": "image/png",
        "data": "<base64-encoded-data>"
      }
    }
  ]
}

Tool definitions go in a top-level tools array, and tool results are sent back as tool_result content blocks on the next user turn:

{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "tools": [
    {
      "name": "get_weather",
      "description": "Get current weather for a city",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": { "type": "string" }
        },
        "required": ["city"]
      }
    }
  ],
  "messages": [
    { "role": "user", "content": "What's the weather in Porto?" }
  ]
}

Claude will respond with a tool_use block containing the input it wants to call the function with. Your code executes the function and sends the result back as a tool_result block in a new user message — the request body format stays consistent, you're just appending to the messages array each turn.

A Full Example Request with curl

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-sonnet-4-5",
    "max_tokens": 1024,
    "system": "You are a helpful assistant.",
    "temperature": 0.5,
    "messages": [
      { "role": "user", "content": "List three uses for the Claude API." }
    ]
  }'

Same Request Through SubToAPI

If you're building a product on top of Claude and want a hosted API key, streaming, and usage metadata without managing Anthropic billing directly, SubToAPI wraps the same request body format behind your own sub_live_... key:

curl https://api.subtoapi.app/v1/messages \
  -H "content-type: application/json" \
  -H "Authorization: Bearer $SUBTOAPI_KEY" \
  -d '{
    "model": "claude-sonnet-4-5",
    "max_tokens": 1024,
    "messages": [
      { "role": "user", "content": "List three uses for the Claude API." }
    ]
  }'

The body shape is identical — the only difference is the auth header and endpoint. If you're just getting started, the quickstart walks through signup and your first request, and the messages reference covers every field in detail. Streaming responses are documented separately in the streaming guide, and tool calling in the tools guide.

Common Mistakes in Request Bodies

Questions

Does the request body format differ between models (Sonnet, Opus, Haiku)? No. The JSON structure is identical across models — only the model string value changes.

Can I send multiple images in one request? Yes. Add multiple image content blocks inside the same message's content array, alongside a text block if needed.

What happens if I omit max_tokens? The request is rejected with a validation error. It's a required field, not a default-assumed one.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →