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/messages in server/src/routes/anthropic.ts
  • Authentication accepts x-api-key or Authorization: Bearer headers validated against your unified API key via authenticate()
  • Model resolution in server/src/services/anthropic-map.ts supports auto-routing or pinned mappings for Claude families (opus, sonnet, haiku)
  • Bidirectional translation handles messages, tools, images, and streaming via convertRequest() and toAnthropicContent()
  • Response headers X-Routed-Via and X-Fallback-Attempts provide 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →