How FreeLLMAPI Supports Anthropic /v1/messages Alongside OpenAI

FreeLLMAPI implements Anthropic’s /v1/messages endpoint as a thin translation layer that converts incoming requests to an internal OpenAI-shaped format, processes them through shared routing and fallback logic, and transforms responses back to Anthropic’s wire format, enabling unified access to free LLM models via both API specifications.

The tashfeenahmed/freellmapi repository provides an open-source API gateway designed to aggregate free-tier large language model providers. By treating the FreeLLMAPI Anthropic /v1/messages endpoint as a compatibility shim rather than a separate codebase, the system maintains exact wire-format compliance with Claude SDKs while leveraging the same resilient backend that serves OpenAI-compatible clients.

Translation-Only Router Architecture

The Anthropic route lives in server/src/routes/anthropic.ts and functions as a bidirectional adapter. Incoming requests undergo immediate structural transformation before entering the core processing pipeline.

Request conversion occurs at lines 33-38, where the Anthropic-specific JSON payload transforms into the internal ChatMessage structure used by the OpenAI implementation. This normalization allows the system to apply identical validation, rate limiting, and routing logic regardless of the client’s expected wire format.

After the shared runFallbackLoop completes processing, the response flows through toAnthropicContent (lines 93-115). This function remaps the OpenAI-style output—including content blocks, tool calls, and metadata—back into the Anthropic Messages API schema. For streaming responses, the streamCompletion wrapper (lines 62-66) translates Server-Sent Events (SSE) streams into the format expected by Claude Code and other Anthropic-native tools.

Model Mapping and Family Classification

Anthropic clients reference model families using aliases like claude-sonnet-4-5 or claude-opus, which must resolve to concrete catalog entries. The server/src/services/anthropic-map.ts module handles this resolution through two primary functions.

The classifyClaudeFamily function (lines 60-73) parses the incoming model string to identify whether the request targets Sonnet, Opus, or Haiku lineages. Subsequently, getClaudeModelMap checks operator-defined mappings stored in the settings database. If a family maps to "auto", the request enters the automatic provider-routing logic; otherwise, the configured catalog model ID pins the request to a specific backend (lines 88-115). This architecture allows administrators to redirect entire Claude families to specific free models or provider pools without modifying client code.

Unified Authentication and Fallback Logic

Both OpenAI and Anthropic endpoints accept identical authentication schemes. The Anthropic router’s authenticate middleware (lines 94-102) validates bearer tokens or x-api-key headers using the same credential store as the OpenAI routes, ensuring consistent access control across API surfaces.

The critical resilience layer resides in server/src/lib/fallback-loop.ts. Both route handlers invoke runFallbackLoop, which implements retry logic, provider cooldowns, exhaustion handling, and circuit-breaking. By pushing Anthropic requests through this shared machinery, FreeLLMAPI guarantees that Claude-format requests benefit from the same automatic failover between free providers as standard OpenAI chat completion calls.

Feature Parity: Tools, Images, and Reasoning

The translation layer preserves advanced capabilities through specialized normalizers:

  • Tool Calls: Anthropic’s tool_use blocks map to OpenAI’s tool_calls format. The system rescues inline tool invocations that appear as raw text through dialect-detection logic in server/src/lib/tool-args.ts and server/src/lib/tool-call-rescue.js.

  • Image Processing: Multimodal requests containing Anthropic image blocks undergo conversion via imageBlockToUrl (lines 31-39 in anthropic.ts), transforming base64 or URL-based Anthropic image objects into OpenAI-compatible image_url blocks.

  • Reasoning Content: When backends return chain-of-thought or reasoning metadata, the system renders Anthropic’s thinking blocks from the internal reasoning_content field (lines 95-101), ensuring that extended thinking models present structured reasoning to compatible clients.

Implementation Examples

Calling the Anthropic Messages Endpoint

This example demonstrates submitting a request using Claude-family nomenclature:

import fetch from 'node-fetch';

const response = await fetch('https://my-freellmapi.com/anthropic/v1/messages', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-api-key': 'YOUR_FREE_LLMAPI_KEY',
  },
  body: JSON.stringify({
    model: 'claude-sonnet-4-5',
    max_tokens: 512,
    messages: [{ role: 'user', content: 'Explain quantum tunnelling.' }],
  }),
});

const data = await response.json();
console.log(data);

The request hits the POST handler in server/src/routes/anthropic.ts, undergoes model resolution via classifyClaudeFamily, and routes through the shared fallback loop.

Equivalent OpenAI Chat Completions Call

The same backend infrastructure processes standard OpenAI requests:

await fetch('https://my-freellmapi.com/v1/chat/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer YOUR_FREE_LLMAPI_KEY',
  },
  body: JSON.stringify({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: 'Tell a joke.' }],
  }),
});

Both requests consume from the same pool of free model providers, with routing decisions determined by the operator’s mapping configuration rather than the client’s chosen wire protocol.

Configuring Model Family Mappings

Administrators can pin Claude families to specific catalog models:

await fetch('https://my-freellmapi.com/admin/anthropic-model-map', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer ADMIN_KEY',
  },
  body: JSON.stringify({ sonnet: 'gpt-4o-mini' }),
});

This mapping persists in the settings table and is retrieved by getClaudeModelMap (lines 31-38 in server/src/services/anthropic-map.ts), forcing all Sonnet-family requests to target the specified model.

Summary

  • FreeLLMAPI implements the Anthropic /v1/messages endpoint in server/src/routes/anthropic.ts as a bidirectional translation layer rather than a standalone implementation.
  • Request and response conversion occurs at lines 33-38 and 93-115 respectively, transforming Anthropic wire formats to internal OpenAI-shaped structures and back.
  • Model family resolution happens via classifyClaudeFamily and getClaudeModelMap in server/src/services/anthropic-map.ts, supporting both automatic routing and operator-pinned mappings.
  • Shared infrastructure includes unified authentication (lines 94-102), the runFallbackLoop for resilience, and feature normalizers for tools, images, and reasoning content.
  • Full compatibility is maintained with existing Anthropic SDKs, Claude Code, and OpenAI clients while routing all traffic through a consolidated free-model aggregation backend.

Frequently Asked Questions

How does FreeLLMAPI handle authentication for Anthropic requests compared to OpenAI requests?

FreeLLMAPI uses identical authentication logic for both endpoints. The Anthropic router accepts the standard x-api-key header or Authorization: Bearer tokens, validating them against the same credential store as OpenAI routes (see authenticate in server/src/routes/anthropic.ts, lines 94-102). This unified approach allows users to use a single API key regardless of which wire format their application expects.

Can I use Claude-specific features like tool use and extended thinking through the FreeLLMAPI Anthropic endpoint?

Yes. The translation layer specifically handles Anthropic’s tool_use blocks by mapping them to OpenAI’s tool_calls format, with additional rescue logic for inline tool dialects. For reasoning content, the system populates Anthropic’s thinking blocks from the internal reasoning_content field (lines 95-101 in anthropic.ts). Image inputs are normalized via imageBlockToUrl (lines 31-39), ensuring multimodal parity across both APIs.

What happens if I request a Claude model that isn’t explicitly mapped to a free provider?

If the requested Claude family maps to "auto" in the operator configuration, the request enters the automatic routing logic that selects an available free provider based on current capacity and health status. If the family maps to a specific model ID via getClaudeModelMap (lines 88-115 in anthropic-map.ts), the request pins to that catalog entry. If no mapping exists and auto-routing fails, the runFallbackLoop returns an exhaustion error after exhausting the provider pool.

Is the streaming implementation different between Anthropic and OpenAI endpoints in FreeLLMAPI?

The core streaming logic is identical; both endpoints utilize the shared streamCompletion infrastructure. However, the Anthropic route includes a thin wrapper (lines 62-66 in anthropic.ts) that reformats the SSE event stream to match Anthropic’s expected data prefixes and termination sequences. This ensures compatibility with Claude Code and other Anthropic-native streaming consumers while maintaining the same underlying retry and fallback behavior.

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 →