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

> Learn how to use the Anthropic Messages API with Claude clients in FreeLLMAPI. This guide shows seamless integration and clear instructions for quick setup.

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

---

**FreeLLMAPI implements a fully compatible Anthropic Messages API endpoint at `POST /v1/messages` in [`server/src/routes/anthropic.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/anthropic.ts) that authenticates requests via the `x-api-key` header, translates Anthropic-formatted payloads into an internal OpenAI-shaped format for unified routing, and converts provider responses back to Anthropic's wire protocol.**

FreeLLMAPI exposes the Anthropic Messages API to enable Claude-based clients (such as Claude Code) to connect to its free model routing infrastructure. The implementation acts as a thin adapter layer that validates Anthropic-specific request envelopes while leveraging the same retry, fallback, and analytics machinery used for OpenAI-compatible endpoints.

## Authentication and Request Validation

### Validating Anthropic API Keys

The route accepts authentication via the Anthropic-standard `x-api-key` header or a bearer token. In [`server/src/routes/anthropic.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/anthropic.ts), the `authenticate()` function (lines 27-33) validates the provided key against the unified API key stored in the database. If the key is missing or invalid, the endpoint returns a 401 `authentication_error` response immediately.

### Schema Validation with Zod

Incoming requests are validated using a Zod schema defined in `messagesSchema` (lines 48-89). The schema permissively validates required fields including `messages`, `max_tokens`, and `tools` while using `.passthrough()` to allow unknown fields. This design ensures forward compatibility with future Anthropic content block types without requiring immediate code changes.

## Request Translation and Model Routing

### Converting to Internal Format

The `convertRequest()` function (lines 94-184) translates the incoming Anthropic request into the internal `ChatMessage[]` format used by the router. This conversion includes flattening any `system` turn into a system message, extracting text and image blocks, and converting Anthropic tool-use structures into internal `ChatToolCall` and `ChatMessage` objects. The function also maps the Anthropic `tool_choice` enum to the OpenAI `ChatToolChoice` format expected by the routing layer.

### Model Resolution and Auto-Routing

Model resolution occurs via [`services/anthropic-map.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/services/anthropic-map.ts). When the request specifies `model: 'auto'` or omits the model entirely, the `resolveAnthropicModel()` call (lines 66-68) triggers automatic selection of an available free model from the catalog. If a specific Claude model identifier is provided (e.g., `claude-3-sonnet-20240229`), the system attempts to route to that pinned model or a compatible alternative based on current rate limits.

### Session Affinity for Claude Code

To prevent model "flapping" during multi-turn conversations, the route inspects the `X-Claude-Code-Session-Id` or generic `X-Session-Id` headers. The session handling logic (lines 70-77) uses `setStickyModel` and `getStickyModel` to remember the chosen model for the duration of the session, ensuring consistent provider selection across related requests.

## Streaming and Response Handling

### SSE Streaming Support

When `stream: true` is set in the request, the route delegates to `streamCompletion()` (lines 98-137). This helper consumes the OpenAI-style stream from the selected provider and re-emits it as an Anthropic-compliant Server-Sent Events (SSE) sequence, including events such as `message_start`, `content_block_delta`, and `message_stop`. The streaming implementation maintains the same retry logic as non-streaming requests, with `MAX_RETRIES` set to 20 for automatic failover.

### Mapping Responses Back to Anthropic Format

After receiving a provider response, the system translates internal `ChatMessage` objects back to Anthropic's wire format. The `toAnthropicContent()` function (lines 11-19) constructs the response `content` array from text and tool calls, while `mapStopReason()` (lines 100-105) converts OpenAI finish reasons (like `stop` or `length`) to Anthropic `stop_reason` values (such as `end_turn` or `max_tokens`).

## Error Handling and Analytics

The route implements comprehensive error handling through sanitized error messages. Provider errors are processed via `sanitizeProviderErrorMessage` from [`lib/error-redaction.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/lib/error-redaction.ts), logged through `logRequest`, and converted to Anthropic-compatible error payloads via `sendError`. The error handling sections (lines 55-78 and 150-170) distinguish between retryable errors (triggering cooldown and fallback) and fatal errors (returning immediately to the client). Rate-limit hits and model-not-found cases automatically increment fallback counters and select alternative providers.

## Auxiliary Endpoints

### Token Counting

The auxiliary endpoint `POST /v1/messages/count_tokens` (lines 390-399) provides token estimation without invoking an actual provider. It reuses the same request translation logic to calculate usage statistics for budget planning and client-side validation.

### Model Listing

The `GET /v1/models` endpoint (lines 514-576) returns the unified model catalog when the request includes an `anthropic-version` header. This allows Claude-compatible clients to discover available models through the standard Anthropic API surface.

## Implementation Examples

Below are minimal examples demonstrating how to call the FreeLLMAPI Anthropic endpoint from a Node.js environment.

### Non-Streaming Request

```typescript
const response = await fetch('https://YOUR_FREELLMAPI_HOST/anthropic/v1/messages', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_UNIFIED_API_KEY',
    'anthropic-version': '2023-06-01',
  },
  body: JSON.stringify({
    model: 'claude-3-sonnet-20240229',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello, Claude!' }],
  }),
});

const result = await response.json();
console.log(result.content);

```

### Streaming Request

```typescript
const res = await fetch('https://YOUR_FREELLMAPI_HOST/anthropic/v1/messages', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_UNIFIED_API_KEY',
    'anthropic-version': '2023-06-01',
  },
  body: JSON.stringify({
    model: 'auto',
    max_tokens: 1024,
    stream: true,
    messages: [{ role: 'user', content: 'Tell me a short story.' }],
  }),
});

const reader = res.body?.getReader();
while (true) {
  const { done, value } = await reader!.read();
  if (done) break;
  const chunk = new TextDecoder().decode(value);
  console.log(chunk); // SSE formatted events
}

```

Both examples target the `/anthropic/v1/messages` path and automatically benefit from the retry logic, session affinity, and model fallback implemented in [`server/src/routes/anthropic.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/anthropic.ts).

## Summary

- **Unified Authentication**: The Anthropic Messages API uses the same API keys as OpenAI routes, validated in `authenticate()` at lines 27-33 of [`server/src/routes/anthropic.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/anthropic.ts).
- **Format Translation**: `convertRequest()` maps Anthropic payloads to internal OpenAI shapes, enabling shared routing logic across provider types.
- **Automatic Failover**: Up to 20 retries with cooldown management and model fallback ensure high availability when using `model: 'auto'`.
- **Session Consistency**: The `X-Claude-Code-Session-Id` header triggers sticky model selection to prevent mid-conversation provider switches.
- **Full Streaming**: SSE streams are translated in real-time by `streamCompletion()` while preserving Anthropic event semantics.
- **Auxiliary Support**: Token counting and model listing endpoints provide complete API compatibility for Claude clients.

## Frequently Asked Questions

### How do I authenticate with the FreeLLMAPI Anthropic Messages API?

Authentication uses the unified API key system. Send your API key in the `x-api-key` header (or as a bearer token) exactly as you would for OpenAI endpoints. The `authenticate()` function in [`server/src/routes/anthropic.ts`](https://github.com/tashfeenahmed/freellmapi/blob/main/server/src/routes/anthropic.ts) validates this against the database at lines 27-33.

### Can I use Claude Code with FreeLLMAPI?

Yes. Configure Claude Code to point to your FreeLLMAPI host and provide the `anthropic-version` header (e.g., `2023-06-01`). The route specifically handles `X-Claude-Code-Session-Id` headers (lines 70-77) to maintain session affinity and prevent model switching mid-conversation.

### What happens if the requested Claude model is unavailable?

If you specify `model: 'auto'` or omit the model field, the system automatically selects a free available model via `resolveAnthropicModel()`. If you request a specific model that hits rate limits, the retry loop (lines 82-125) attempts up to 20 alternative providers before returning an error.

### Does the endpoint support tool use and function calling?

Yes. The Zod schema at lines 48-89 validates `tools` and `tool_choice` parameters, while `convertRequest()` translates Anthropic tool blocks into internal `ChatToolCall` structures. Tool results are similarly mapped back to Anthropic's expected response format in `toAnthropicContent()`.