# How to Use the Anthropic Messages API with FreeLLMAPI for Claude Clients

> Easily access the Anthropic Messages API with FreeLLMAPI. Connect to Claude via OpenAI-compatible calls, enjoy free-tier providers, streaming, and tool support.

- Repository: [Tashfeen/freellmapi](https://github.com/tashfeenahmed/freellmapi)
- Tags: how-to-guide
- Published: 2026-06-29

---

**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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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:

```bash
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:

```bash
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):

```python
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:

```python
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:

```json
{
  "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:

```json
{
  "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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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`](https://github.com/tashfeenahmed/freellmapi/blob/main/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.