API features

Anthropic API Compatibility

Use the Anthropic-compatible endpoint to access Claude and GPT models through the familiar Anthropic API format.

Halfbill provides a native Anthropic-compatible endpoint at /v1/messages that allows you to use any model in our catalog — Claude or GPT — while maintaining the familiar Anthropic API format. This is the endpoint Claude Code and the Anthropic SDKs use.

Overview

The Anthropic endpoint transforms requests from Anthropic's message format to the OpenAI-compatible format used by Halfbill, then transforms the responses back to Anthropic's format. This means you can:

  • Use any model available in Halfbill with Anthropic's API format
  • Maintain existing code that uses Anthropic's SDK or API format
  • Access GPT models through the Anthropic interface
  • Use Halfbill's caching and cost tracking features

Basic Usage

Configuration for Claude Code

Use this endpoint to run Claude Code through Halfbill:

export ANTHROPIC_BASE_URL=https://api.halfbill.uk
export ANTHROPIC_AUTH_TOKEN=llmgtwy_your_api_key_here
# optional: specify a model, otherwise Claude Code uses its default Claude model
export ANTHROPIC_MODEL=claude-sonnet-5  # or any model from our catalog

# now run claude!
claude

Environment variables are read once at startup. The /model picker lists Claude models only, so non-Claude models are selected with ANTHROPIC_MODEL or --model. See the Claude Code guide for the settings-file options and model discovery.

Choosing Models

You can use any model from the models page. Popular options for Claude Code include:

# Anthropic's flagship coding model
export ANTHROPIC_MODEL=claude-sonnet-5

# Anthropic's most capable model
export ANTHROPIC_MODEL=claude-opus-5

# A cost-effective alternative
export ANTHROPIC_MODEL=claude-haiku-4-5

# OpenAI's GPT through the same endpoint
export ANTHROPIC_MODEL=gpt-5.5

Environment Variables

When configuring Claude Code or other Anthropic-compatible applications, you can use these environment variables:

ANTHROPIC_MODEL

Specifies the main model to use for primary requests.

  • Default: Claude Code's built-in default Claude model
  • Example: export ANTHROPIC_MODEL=claude-sonnet-5

ANTHROPIC_SMALL_FAST_MODEL

Specifies a smaller, faster model used for background functionality and internal operations.

  • Default: Claude Code's built-in default Haiku model
  • Example: export ANTHROPIC_SMALL_FAST_MODEL=claude-haiku-4-5
# Example configuration
export ANTHROPIC_BASE_URL=https://api.halfbill.uk
export ANTHROPIC_AUTH_TOKEN=llmgtwy_your_api_key_here
export ANTHROPIC_MODEL=claude-sonnet-5
export ANTHROPIC_SMALL_FAST_MODEL=claude-haiku-4-5

Advanced Features

Making a manual request

curl -X POST "https://api.halfbill.uk/v1/messages" \
  -H "Authorization: Bearer $HALFBILL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [
      {"role": "user", "content": "Hello, how are you?"}
    ],
    "max_tokens": 100
  }'

Response Format

The endpoint returns responses in Anthropic's message format:

{
	"id": "msg_abc123",
	"type": "message",
	"role": "assistant",
	"model": "claude-sonnet-5",
	"content": [
		{
			"type": "text",
			"text": "Hello! I'm doing well, thank you for asking. How can I help you today?"
		}
	],
	"stop_reason": "end_turn",
	"stop_sequence": null,
	"usage": {
		"input_tokens": 13,
		"output_tokens": 20
	}
}

Request Format

/v1/messages expects Anthropic Messages requests and always answers in Anthropic's format. Because the two formats share model and messages, an OpenAI Chat Completions body can reach this endpoint by accident — and since unknown parameters are ignored rather than rejected, the request succeeds and returns an Anthropic response body that OpenAI SDKs cannot read. If your client reports an empty completion here, check that it is pointed at /v1/chat/completions.

Unknown parameters are deliberately ignored rather than rejected, so a valid Anthropic request is never denied for carrying an extra field. As a consequence, OpenAI-only parameters (response_format, stream_options, max_completion_tokens, n, stop, seed, frequency_penalty, and similar) have no effect here — the model will not honour them. Use /v1/chat/completions if you need them.

A body that is structurally OpenAI is rejected by the schema, as it always has been — OpenAI-shaped tools ({"type": "function", "function": {…}}), OpenAI content parts such as image_url, or assistant turns with content: null. Those rejections now name the mismatch and point at the right endpoint instead of returning an opaque validation error:

{
	"type": "error",
	"error": {
		"type": "invalid_request_error",
		"message": "This endpoint implements Anthropic's Messages API, and the request body uses OpenAI Chat Completions structures (tools[0].function) that Anthropic's format has no equivalent for. Send OpenAI-format requests to /v1/chat/completions instead, or convert the body to Anthropic's Messages format."
	}
}

Rejected requests are recorded in your logs with a client_error finish reason and zero cost, so a malformed client is visible in the activity feed rather than failing silently.

Prompt Caching

For Claude models, cache_control markers on system and message content blocks are forwarded to the provider unchanged, including the optional ttl (5m or 1h):

{
	"model": "claude-sonnet-4-6",
	"max_tokens": 100,
	"system": [
		{
			"type": "text",
			"text": "<several thousand tokens of stable instructions...>",
			"cache_control": { "type": "ephemeral" }
		}
	],
	"messages": [{ "role": "user", "content": "Hello!" }]
}

Cache usage comes back in Anthropic's native fields: usage.cache_creation_input_tokens (tokens written to the cache this request, billed at the write premium), usage.cache_read_input_tokens (tokens served from cache at the discounted rate), and usage.cache_creation (the per-TTL write breakdown).

Each Claude model has a minimum cacheable prompt length (4,096 tokens on current-generation models such as Opus 4.5+, Sonnet 5, and Haiku 4.5). A cache_control marker on a shorter prompt is accepted but silently not cached — both cache usage fields stay 0. See Provider Cache Control for the per-model thresholds and details.

Anthropic's server-side tool search works on this endpoint. Pass a tool_search_tool_* tool alongside your catalog and mark the tools that should load on demand with defer_loading: true:

{
	"model": "claude-sonnet-4-6",
	"max_tokens": 1024,
	"messages": [{ "role": "user", "content": "What is the weather in Paris?" }],
	"tools": [
		{
			"type": "tool_search_tool_regex_20251119",
			"name": "tool_search_tool_regex"
		},
		{
			"name": "get_weather",
			"description": "Get the weather at a specific location",
			"input_schema": { "type": "object" },
			"defer_loading": true
		}
	]
}

Deferred tools stay out of the rendered tools section, so adding one does not invalidate an existing prompt cache. The response carries the server_tool_use and tool_search_tool_result blocks; replay them verbatim on the next request and Anthropic keeps expanding the tool_reference entries they carry, so Claude reuses a discovered tool instead of searching again. tool_reference blocks returned from your own client-side search inside a tool_result are forwarded unchanged too.

Send every tool definition on every request, including the deferred ones — Anthropic needs them server-side to run the search. At least one tool must stay non-deferred (normally the tool search tool itself), and a tool cannot carry both defer_loading: true and cache_control.

Tool search needs a Claude 4.5-generation model or newer — older Claude models reject it upstream.

Gateway Response Cache

If gateway caching is enabled on the project, a byte-identical request is replayed from cache instead of being sent upstream. Because the replayed body is identical (same id, same usage), the x-llmgateway-cache: HIT response header is the marker to check. Send x-no-cache: true to bypass the cache for a single request.

How is this guide?

On this page