---
title: "Anthropic Messages"
subtitle: "Use the Anthropic SDK with the gateway by changing its base URL."
---

The gateway serves Anthropic's Messages API. Point the Anthropic SDK at it and pass your Respan API key as the SDK's key. Routing, routes, limits, and logging all apply.

`POST https://gateway.respan.ai/v1/messages`

<Tabs>
<Tab title="cURL">
```bash
curl https://gateway.respan.ai/v1/messages \
  -H "x-api-key: $RESPAN_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5-20250929",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
```
</Tab>
<Tab title="Python">
```python
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://gateway.respan.ai",
    api_key=os.environ["RESPAN_API_KEY"],
)

message = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
print(message.content[0].text)
```
</Tab>
<Tab title="TypeScript">
```typescript
import Anthropic from "@anthropic-ai/sdk";

const client = new Anthropic({
  baseURL: "https://gateway.respan.ai",
  apiKey: process.env.RESPAN_API_KEY,
});

const message = await client.messages.create({
  model: "claude-sonnet-4-5-20250929",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Hello!" }],
});
console.log(message.content[0].type === "text" ? message.content[0].text : "");
```
</Tab>
</Tabs>

The gateway reads your Respan key from `x-api-key` (what the SDK sends) or from `Authorization: Bearer`.

## Request body

The body is Anthropic's.

| Field | Type | Description |
|---|---|---|
| `model` | string | A model ID from the [catalog](/docs/ai-gateway/models/overview). Required. |
| `max_tokens` | integer | Maximum output tokens. Required. |
| `messages` | array | The conversation, with text, image, and document blocks. Required. |
| `system` | string or array | System prompt. |
| `stream` | boolean | `true` returns Anthropic server-sent events. See [Streaming](#streaming). |
| `tools`, `tool_choice` | array, object | Tools the model may call. See [Tool calling](#tool-calling). |
| `output_config.format` | object | Structured output. See [Structured outputs](#structured-outputs). |
| `thinking` | object | Extended thinking settings. |
| `temperature`, `top_p`, `top_k`, `stop_sequences` | | Sampling settings. |
| `metadata.respan_params` | object | Respan params. Removed before the provider sees the body. |

## Other providers' models

Requests are routed by model, so the Anthropic SDK can call a model from another provider. The gateway translates the request and writes the answer back in Messages format.

```python
message = client.messages.create(
    model="gpt-5.5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)
```

An Anthropic-only field with no equivalent on the target provider is refused with `400` and named in the error, not dropped. See [known gaps](/docs/oss-gateway/api-formats#chat-gaps). Coding agents such as Claude Code rely on such fields, so keep them on Claude models.

## Streaming

Set `stream: true` and the gateway returns Anthropic server-sent events, whichever provider answers. A stream sends `message_start`, then `content_block_start`, `content_block_delta` and `content_block_stop` for each block, then `message_delta`, and ends with `message_stop`. Usage is reported in `message_start` (input) and `message_delta` (output).

```python
stream = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a haiku about routers."}],
    stream=True,
)
for event in stream:
    if event.type == "message_start":
        print(event.message.usage)
    elif event.type == "content_block_delta" and event.delta.type == "text_delta":
        print(event.delta.text, end="")
    elif event.type == "message_delta":
        print("\n", event.usage)
```

If the provider breaks off after the stream has started, the gateway sends the error as an `event: error`, the last event in the stream. A stream that ends with an error event did not finish, even if some content arrived. For errors before a stream starts, cancellation and billing, and the gateway's fixed 600 second timeout, see [Chat Completions](/docs/ai-gateway/requests/chat-completions#stream-errors).

## Structured outputs

Anthropic's structured output setting is `output_config.format`. It is also what the gateway sends to Anthropic models when a Chat Completions request carries a `json_schema` `response_format`. Anthropic always enforces the schema strictly.

```bash
curl https://gateway.respan.ai/v1/messages \
  -H "x-api-key: $RESPAN_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4-5-20250929",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Ada Lovelace was born in London in 1815."}],
    "output_config": {
      "format": {
        "type": "json_schema",
        "schema": {
          "type": "object",
          "properties": {
            "name": {"type": "string"},
            "birth_year": {"type": "integer"},
            "city": {"type": "string"}
          },
          "required": ["name", "birth_year", "city"],
          "additionalProperties": false
        }
      }
    }
  }'
```

From Chat Completions, a `json_object` response format without a schema is refused with `400` for Anthropic models, and so is a `json_schema` with a `description` or `strict: false`. See [Model support](/docs/ai-gateway/requests/chat-completions#model-support). The gateway doesn't repair JSON; see [Invalid JSON](/docs/ai-gateway/requests/chat-completions#invalid-json).

{/* REVIEW: new section. Source pages only document output_config.format as the translation target from Chat Completions; confirm it passes through unchanged on /v1/messages and how it is handled when an Anthropic-format request goes to another provider's model. */}

## Tool calling

Tools use Anthropic's shape: each tool has a `name`, a `description` and an `input_schema`. When the model calls one, the answer has `stop_reason: "tool_use"` and a `tool_use` block with an `id` and the `input`. Send the result back in a `user` message as a `tool_result` block with the same `tool_use_id`.

```python
import json

tools = [{
    "name": "get_weather",
    "description": "Get the current weather for a city",
    "input_schema": {
        "type": "object",
        "properties": {"city": {"type": "string"}},
        "required": ["city"],
    },
}]
messages = [{"role": "user", "content": "What is the weather in Paris?"}]

message = client.messages.create(
    model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=messages, tools=tools,
)
call = next(block for block in message.content if block.type == "tool_use")
result = {"temp_c": 18, "sky": "clear"}  # your function's output for call.input

messages.append({"role": "assistant", "content": message.content})
messages.append({
    "role": "user",
    "content": [{"type": "tool_result", "tool_use_id": call.id, "content": json.dumps(result)}],
})

final = client.messages.create(
    model="claude-sonnet-4-5-20250929", max_tokens=1024, messages=messages, tools=tools,
)
print(final.content[0].text)
```

For the agent loop, `tool_choice`, routing by tool support, and how tool calls are logged and billed, see [Tool calling](/docs/ai-gateway/requests/chat-completions#tool-calling) on Chat Completions.

{/* REVIEW: new section. Source pages describe tool translation and server tools for Chat Completions only; confirm tool_use / tool_result blocks are translated for other providers' models on /v1/messages and whether server tools run on this format. */}

## Prompt caching

Add `cache_control` to the blocks you want cached, as in Anthropic's API. It reaches Anthropic, and cached tokens are priced at Anthropic's cache rates.

```python
message = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    system=[{
        "type": "text",
        "text": "You are a support agent. <long product manual here>",
        "cache_control": {"type": "ephemeral"},
    }],
    messages=[{"role": "user", "content": "How do I reset my password?"}],
)
print(message.usage)
```

See [Prompt caching](/docs/ai-gateway/features/caching#prompt-caching).

## Pin a provider

To serve a model from a specific provider, send the `X-Respan-Route-Provider` header, such as `X-Respan-Route-Provider: anthropic`. You can also send a provider offering as `model`. To use your own provider account, save its key with [BYOK](/docs/ai-gateway/spend/credits-vs-byok#byok).

```python
message = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
    extra_headers={"X-Respan-Route-Provider": "anthropic"},
)
```

## Respan params

Put Respan params inside `metadata`. The gateway removes them before the provider sees the body.

```python
message = client.messages.create(
    model="claude-sonnet-4-5-20250929",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
    metadata={"respan_params": {"customer_identifier": "user_8842", "thread_identifier": "ticket_1042"}},
)
```

You can also send them in a top-level `respan_params` (with `extra_body`) or the `X-Data-Respan-Params` header. A `respan_params` value must be a JSON object; a string is ignored. See [Respan params](/docs/ai-gateway/customers/respan-params).

## Response

The body is an Anthropic `message`, whichever provider answered. Every response carries `X-Respan-Log-Id` and `X-Respan-Gateway-Request-Id`. Errors come back in Anthropic's error shape, `{"type": "error", "error": {...}}`.

## Passthrough instead

To send Anthropic's body to Anthropic exactly as written, on your own Anthropic key, with no routing or translation, use the [passthrough](/docs/ai-gateway/requests/other-endpoints#provider-passthrough) path `/api/anthropic/passthrough/v1/messages`.

## Next steps

- [Claude Code](/docs/integrations/gateway/claude-code) and the [Anthropic SDK guide](/docs/integrations/gateway/anthropic-sdk).
- [Chat Completions](/docs/ai-gateway/requests/chat-completions#request-body): the fields the gateway reads.
