# POST /v1/messages

The official Anthropic `/v1/messages` protocol. Its fields are fully consistent with the official API, allowing existing Anthropic SDK code to be migrated with almost no changes.

## Endpoint

```
POST https://relay.4aicode.com/v1/messages
```

## Request

```http
POST /v1/messages HTTP/1.1
Host: relay.4aicode.com
Authorization: Bearer sk-4ai-xxxxxxxxxxxxxxxx
anthropic-version: 2023-06-01
content-type: application/json

{
  "model": "claude-sonnet-4-6",
  "max_tokens": 1024,
  "stream": true,
  "messages": [
    { "role": "user", "content": "Say hi" }
  ]
}
```

### Required

| Field | Description |
|---|---|
| `model` | A Claude model (Sonnet / Haiku / Opus series) or a supported `gpt-*` model |
| `max_tokens` | Maximum number of tokens to generate |
| `messages` | Conversation array |

`/v1/messages` routes requests to the upstream service corresponding to `model`, supporting both `claude-*` and `gpt-*` models. Clients using the Anthropic Messages protocol, such as Claude Code, can access these models through this endpoint.

### Common Optional Fields

| Field | Description |
|---|---|
| `stream` | Set to `true` to enable SSE |
| `system` | System prompt |
| `temperature` | 0–1 |
| `tools` | Function calling |
| `stop_sequences` | Stop sequences |

## Streaming Response

When `stream: true`, the endpoint returns `text/event-stream` with an event sequence consistent with the official API:

```
event: message_start
event: content_block_start
event: content_block_delta
event: content_block_stop
event: message_delta
event: message_stop
```

The relay does not buffer SSE at any stage, so time to first byte is essentially the same as with a direct connection.

## Non-Streaming Response

```json
{
  "id": "msg_xxxx",
  "type": "message",
  "role": "assistant",
  "content": [{ "type": "text", "text": "Hi!" }],
  "model": "claude-sonnet-4-6",
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 8, "output_tokens": 3 }
}
```

`usage` is used for billing (see [Quota](/docs/en/guides/quota) for details).

## ChatGPT Models

To use a ChatGPT model with Claude Code, simply set the model to a supported `gpt-*` model:

```bash
export ANTHROPIC_BASE_URL=https://relay.4aicode.com
export ANTHROPIC_AUTH_TOKEN=sk-4ai-xxxxxxxxxxxxxxxx
export ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5.6-terra
export ANTHROPIC_DEFAULT_OPUS_MODEL_NAME="4AICode GPT 5.6 Terra"
export ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES=effort,xhigh_effort,thinking,adaptive_thinking,interleaved_thinking
export ANTHROPIC_MODEL=opus
export ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5.4-mini
export CLAUDE_CODE_EFFORT_LEVEL=xhigh
claude --effort xhigh
```

`ANTHROPIC_DEFAULT_OPUS_MODEL` causes Claude Code to request `gpt-5.6-terra` from the relay. `CLAUDE_CODE_EFFORT_LEVEL=xhigh` maps Anthropic's `output_config.effort` to OpenAI Responses' `reasoning.effort=xhigh`.

The supported models are the same as those for `/v1/chat/completions`: `gpt-6-astra`, `gpt-6-sol`, `gpt-6.1-sol`, `gpt-6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna`, `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, and `gpt-5.3-codex`.

## Errors

| HTTP | Meaning |
|---|---|
| **400** | Invalid fields (missing `max_tokens`, nonexistent `model`, etc.) |
| **401** | Invalid token |
| **403** | Team suspended |
| **429** | Rate limit or quota exceeded |
| **502** | Upstream Claude instability; retry the request |
| **503** | Upstream services are temporarily unavailable; see [Service Cooldowns and Retries](/docs/en/guides/account-cooldown) for details |

`503` example:

```json
{
  "code": "no_account_available",
  "message": "all accounts cooling down, retry in 60s"
}
```

## Complete Example (Python)

```python
from anthropic import Anthropic

client = Anthropic(
    base_url="https://relay.4aicode.com",
    api_key="sk-4ai-xxxxxxxxxxxxxxxx",
)

with client.messages.stream(
    model="claude-sonnet-4-6",
    max_tokens=512,
    messages=[{"role": "user", "content": "Introduce yourself in one sentence"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
```
