# Messages (Anthropic protocol)

> Request fields and response shape for POST /v1/messages, including calling non-Anthropic models.

```
POST https://api.tokrouter.dev/v1/messages
x-api-key: sk-…
anthropic-version: 2023-06-01
Content-Type: application/json
```

## Request fields

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `model` | string | Yes | Model id; any vendor's model works |
| `max_tokens` | integer | **Yes** | Required by the Anthropic protocol |
| `messages` | array | Yes | `role` is `user` / `assistant`; content may be a string or content blocks |
| `system` | string / array | No | System prompt (equivalent to OpenAI's `system` role) |
| `stream` | boolean | No | SSE streaming |
| `temperature` | number | No | |
| `tools` | array | No | Anthropic-shaped tool definitions |
| `stop_sequences` | array | No | |

```bash
curl https://api.tokrouter.dev/v1/messages \
  -H "x-api-key: $TOKROUTER_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-opus-5-5",
    "max_tokens": 512,
    "system": "You are a concise assistant",
    "messages": [{"role": "user", "content": "Hello"}]
  }'
```

## Response

```json
{
  "id": "msg_...",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-5-5",
  "content": [{"type": "text", "text": "Hello"}],
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 14, "output_tokens": 3}
}
```

## Differences from OpenAI

| Aspect | Anthropic | OpenAI |
| --- | --- | --- |
| System prompt | top-level `system` | `system` role in `messages` |
| Output cap | `max_tokens` **required** | optional |
| Response text | `content[0].text` | `choices[0].message.content` |
| Auth header | `x-api-key` | `Authorization: Bearer` |

Calling a non-Anthropic model over the Anthropic protocol still returns an Anthropic-shaped response,
so clients never branch on vendor.
