How to Use the Anthropic Messages API with FreeLLMAPI for Claude Clients
FreeLLMAPI exposes a fully Anthropic-compatible Messages API at /v1/messages that translates Claude-formatted requests into OpenAI-shaped calls, routes them through free-tier providers, and returns native Anthropic responses including streaming and tool support.
FreeLLMAPI is an open-source gateway that unifies access to free LLM providers. The repository tashfeenahmed/freellmapi implements a complete Anthropic Messages API compatibility layer, allowing you to use standard Claude SDKs and tools while the system automatically routes requests to available free models.
Architectural Flow of the Anthropic Endpoint
The Anthropic Messages API implementation resides in server/src/routes/anthropic.ts and follows a bidirectional translation pattern between Anthropic wire format and internal OpenAI-shaped representations.
Request Routing and Authentication
The router mounts at /v1 as defined in server/src/app.ts where app.use('/v1', anthropicRouter); handles incoming requests. According to the source code, the endpoint accepts both x-api-key and Authorization: Bearer headers. The authenticate() function (lines 27-34 in anthropic.ts) validates tokens against the unified API key retrieved via getUnifiedApiKey().
Request bodies undergo validation through messagesSchema, a permissive Zod schema (lines 48-90) that tolerates extra fields such as cache_control.
Model Resolution and Mapping
Model classification occurs in server/src/services/anthropic-map.ts. The resolveAnthropicModel() function (lines 60-100) categorizes incoming Claude model names into families—default, opus, sonnet, or haiku—then checks operator-defined mappings stored in the database under the key anthropic_model_map. If no mapping exists, the system defaults to auto-routing, selecting the best available free model dynamically where preferredModelDbId remains undefined.
Request Conversion and Response Translation
The convertRequest() function (lines 95-144 in anthropic.ts) normalizes Anthropic-specific message blocks—including text, image, tool_use, and tool_result types—into the internal OpenAI-shaped ChatMessage format used by the router.
After the provider returns a response, toAnthropicContent() (lines 190-225) reconstructs the Anthropic content array with proper text and tool_use blocks, wrapping them in an AnthropicMessageResponse that includes id, model, stop_reason, and token usage.
Streaming Implementation
For streaming requests where stream: true is set, the streamCompletion() function (lines 500-620) consumes the provider's OpenAI-style stream and emits the exact Server-Sent Events (SSE) sequence expected by Claude clients: message_start, content_block_start, content_block_delta, content_block_stop, message_delta, and message_stop.
Response headers include X-Routed-Via indicating the actual platform and model that served the request, and X-Fallback-Attempts when retries occur.
Configuration and Setup
Client Environment Variables
Configure your Claude client to point to FreeLLMAPI instead of Anthropic's native endpoints:
export ANTHROPIC_BASE_URL=http://localhost:3001 # FreeLLMAPI host
export ANTHROPIC_AUTH_TOKEN=freellmapi-your-unified-key # Your unified API key
Note that this uses your FreeLLMAPI unified key, not an actual Anthropic API key.
Model Mapping Configuration
Access the dashboard at Dashboard → Keys → Anthropic to configure how Claude model families map to free providers:
- Auto: Routes requests to the best available free model dynamically
- Pinned: Maps specific families (opus, sonnet, haiku) to concrete catalog models
If unconfigured, all families default to auto-routing via the router's standard selection logic.
Implementation Examples
Direct HTTP Request
Send a native Anthropic-formatted request using cURL:
curl http://localhost:3001/v1/messages \
-H "x-api-key: freellmapi-your-unified-key" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 256,
"messages": [{"role": "user", "content": "hi"}]
}'
Python SDK Integration
Use the OpenAI Python SDK pointed at FreeLLMAPI (which auto-detects the anthropic-version header):
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:3001/v1",
api_key="freellmapi-your-unified-key",
)
resp = client.chat.completions.create(
model="claude-sonnet-4-5",
max_tokens=256,
messages=[{"role": "user", "content": "hi"}]
)
print(resp.choices[0].message.content)
print("Routed via:", resp.headers.get("x-routed-via"))
Streaming Responses
Enable streaming to receive incremental updates:
stream = client.chat.completions.create(
model="claude-opus-20240229",
max_tokens=256,
messages=[{"role": "user", "content": "Stream me a haiku"}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)
Tool Calling and Vision
FreeLLMAPI translates Anthropic tool definitions and image blocks automatically. For tool use:
{
"model": "claude-opus-20240229",
"max_tokens": 256,
"messages": [{ "role": "user", "content": "What is the weather in Paris?" }],
"tools": [
{
"name": "get_weather",
"description": "Returns current weather for a city",
"input_schema": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
],
"tool_choice": { "type": "auto" }
}
For vision inputs, the system converts Anthropic image blocks into OpenAI image_url format via imageBlockToUrl, routing only to vision-capable models:
{
"model": "claude-sonnet-4-5",
"max_tokens": 256,
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "What is shown?" },
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "<BASE64_DATA>"
}
}
]
}
]
}
Summary
- FreeLLMAPI implements the complete Anthropic Messages API at
/v1/messagesinserver/src/routes/anthropic.ts - Authentication accepts
x-api-keyorAuthorization: Bearerheaders validated against your unified API key viaauthenticate() - Model resolution in
server/src/services/anthropic-map.tssupports auto-routing or pinned mappings for Claude families (opus, sonnet, haiku) - Bidirectional translation handles messages, tools, images, and streaming via
convertRequest()andtoAnthropicContent() - Response headers
X-Routed-ViaandX-Fallback-Attemptsprovide visibility into routing decisions
Frequently Asked Questions
What authentication methods does FreeLLMAPI support for Anthropic clients?
FreeLLMAPI accepts both x-api-key and Authorization: Bearer headers. The authenticate() function in server/src/routes/anthropic.ts (lines 27-34) validates these against your unified API key retrieved via getUnifiedApiKey(), not against actual Anthropic credentials.
Can I use the official Anthropic Python SDK with FreeLLMAPI?
Yes. Set the ANTHROPIC_BASE_URL environment variable to your FreeLLMAPI host (e.g., http://localhost:3001) and use your FreeLLMAPI unified key as the authentication token. The endpoint fully implements the Anthropic Messages API specification, including model listing and message generation.
How does FreeLLMAPI handle Claude-specific features like tool use and vision?
The convertRequest() function (lines 95-144 in anthropic.ts) normalizes Anthropic message blocks—including tool_use, tool_result, and image types—into the internal OpenAI format. For images, the system converts base64 data to URLs for vision-capable providers. Tool definitions are translated between Anthropic's input_schema and OpenAI's function format automatically.
Where are the model mappings stored and how can I update them?
Model mappings for Claude families (opus, sonnet, haiku, default) are stored in the database settings table under the key anthropic_model_map. You can configure these through the Dashboard at Keys → Anthropic, choosing either auto-routing or pinning specific families to concrete catalog models.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →