---
url: https://docs.freetheai.org/api/messages.md
description: >-
  POST /v1/messages - the Anthropic Messages format on FreeTheAI, used by Claude
  Code and the Anthropic SDK. Parameters, examples, streaming, and tool use with
  free models.
---

# Anthropic Messages

Creates a message in the Anthropic Messages format. Claude Code and the Anthropic SDKs use it. Every free model answers here, streamed or not, with tool use.

`POST https://api.freetheai.org/v1/messages`

The Anthropic SDK and Claude Code take the base URL **without** `/v1`: `https://api.freetheai.org`.

## Request

::: code-group

```bash [curl]
curl https://api.freetheai.org/v1/messages \
  -H "x-api-key: $FTAI_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "fta/zai/glm-5.3",
    "max_tokens": 512,
    "system": "You are a concise assistant.",
    "messages": [{"role": "user", "content": "Give me a name for a grey cat."}]
  }'
```

```python [Python]
# pip install anthropic
import os
import anthropic

client = anthropic.Anthropic(
    base_url="https://api.freetheai.org",
    api_key=os.environ["FTAI_KEY"],
)

message = client.messages.create(
    model="fta/zai/glm-5.3",
    max_tokens=512,
    system="You are a concise assistant.",
    messages=[{"role": "user", "content": "Give me a name for a grey cat."}],
)
print(message.content[0].text)
```

```ts [TypeScript]
// npm install @anthropic-ai/sdk
import Anthropic from '@anthropic-ai/sdk'

const client = new Anthropic({
  baseURL: 'https://api.freetheai.org',
  apiKey: process.env.FTAI_KEY,
})

const message = await client.messages.create({
  model: 'fta/zai/glm-5.3',
  max_tokens: 512,
  system: 'You are a concise assistant.',
  messages: [{ role: 'user', content: 'Give me a name for a grey cat.' }],
})
const first = message.content[0]
console.log(first.type === 'text' ? first.text : first)
```

:::

`Authorization: Bearer ftai_...` works in place of `x-api-key`. Send the `anthropic-version` header your client normally sends; the SDKs do it for you.

## Body parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `model` | string, **required** | A model ID from [`GET /v1/models`](/api/models), such as `fta/zai/glm-5.3`. Anthropic model names do not work here. |
| `max_tokens` | integer, **required** | The most tokens to generate. |
| `messages` | array, **required** | Alternating `user` and `assistant` messages. `content` is a string or an array of content blocks (`text`, `image`, `tool_use`, `tool_result`). |
| `system` | string or array | The system prompt, as a string or text blocks. |
| `stream` | boolean | Return Anthropic server-sent events. Default `false`. |
| `temperature`, `top_p`, `top_k` | number | Sampling, where the model supports it. |
| `stop_sequences` | array | Text that ends the reply. |
| `tools` | array | Tools with `name`, `description`, and `input_schema`. `{"type": "web_search_20250305", "name": "web_search"}` turns on web search for `fta/dog/` and `fta/lion/` models. |
| `tool_choice` | object | `{"type": "auto"}`, `{"type": "any"}`, or `{"type": "tool", "name": ...}`. |
| `thinking` | object | `{"type": "disabled"}` turns reasoning off for models that think. |

Other Anthropic fields are passed to the model when it supports them. Features that exist only in Claude models may not work on other models.

## Response

```json
{
  "id": "msg_01H...",
  "type": "message",
  "role": "assistant",
  "model": "fta/zai/glm-5.3",
  "content": [
    { "type": "text", "text": "How about Ash?" }
  ],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 24, "output_tokens": 6 }
}
```

| Field | Description |
| --- | --- |
| `content` | Content blocks: `text`, `tool_use`, and `thinking` blocks for models that think. |
| `stop_reason` | `end_turn`, `max_tokens`, `stop_sequence`, or `tool_use`. |
| `usage` | `input_tokens` and `output_tokens`. |

## Streaming

With `"stream": true` you get Anthropic's events: `message_start`, `content_block_start`, `content_block_delta`, `content_block_stop`, `message_delta`, and `message_stop`. The SDK helpers work as usual:

```python
with client.messages.stream(
    model="fta/zai/glm-5.3",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a limerick about tea."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
```

## Tool use

See the [Anthropic SDK page](/sdks/anthropic#tool-use) for a complete tool-use loop.

## Claude Code

Claude Code sends this format to whatever `ANTHROPIC_BASE_URL` names. A tested `settings.json` is in the [Claude Code guide](/guides/claude-code).

## Errors

The same statuses as [Chat Completions](/api/chat-completions#errors), in FreeTheAI's error format. Every message: [Errors](/errors).
