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.
https://api.freetheai.org/v1/messagesThe Anthropic SDK and Claude Code take the base URL without /v1: https://api.freetheai.org.
Request
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."}]
}'# 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)// 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, 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
{
"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:
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 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.
Errors
The same statuses as Chat Completions, in FreeTheAI's error format. Every message: Errors.

