OpenAI & Anthropic Compatibility

The gateway's two wire dialects — same underlying contract, different shapes.

The gateway natively speaks the OpenAI schema. The Anthropic Messages dialect is served by a translating proxy (/v1/messages), so Claude SDKs work unchanged against the same keys, models, limits, and ledger. This page is the side-by-side for developers with an existing integration in either dialect.

Which dialect do I need?

If your code uses…Send requests toAuth header
The OpenAI SDK (or anything OpenAI-dialect: LangChain, Vercel AI SDK, …)https://api.<domain>/v1/…Authorization: Bearer <key>
The Anthropic SDK / Claude Codehttps://api.<domain>/v1/messagesx-api-key: <key> (Bearer also accepted)

One API key works across both surfaces — the key, its model allowlist, plan, rate limits, and spend caps are enforced identically regardless of dialect.

What is identical (the contract)

Regardless of dialect:

  • model echoes verbatim — the response model field is exactly the alias you sent, even when failover changed the serving provider.
  • provider_metadata is always present on successful bodies, carrying provider (who actually served the request) and actual_model (the provider's internal model id).
  • Every error carries a server-minted request_id — quote it in support requests; it is the correlation id across all logs.
  • The same validation, policy, and billing path applies: model allowlist, rate limits, and the prepaid credit reservation run before any provider is called.
  • The same X-TF-* side-channel headers accompany every response (see Streaming and Errors).

What differs (the shapes)

OpenAI dialectAnthropic dialect
Path prefix/v1/* (except /v1/messages)/v1/messages (+ /v1/messages/count_tokens)
Auth headerAuthorization: Bearer <key>x-api-key: <key>; Authorization: Bearer also accepted
Error envelope{"error": {...}, "request_id": "…"}{"type": "error", "error": {...}, "request_id": "…"} — request_id is a top-level sibling, no code/param
Streaming eventsdata: {"choices":[…]} chunks, terminated by data: [DONE]Native message_start / content_block_* / message_delta / message_stop sequence
Usage blockusage{prompt_tokens, completion_tokens, total_tokens}usage{input_tokens, output_tokens} (+ prompt-cache keys)

Worked example — same request, both dialects

OpenAI dialect (Authorization: Bearer):

curl https://api.<domain>/v1/chat/completions \
  -H "Authorization: Bearer $TOKENFACTORY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet",
    "messages": [{ "role": "user", "content": "Hello!" }],
    "max_tokens": 64
  }'

Anthropic dialect (x-api-key):

curl https://api.<domain>/v1/messages \
  -H "x-api-key: $TOKENFACTORY_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet",
    "max_tokens": 1024,
    "messages": [{ "role": "user", "content": "Hello!" }]
  }'

Both hit the same model alias, consume the same wallet, and return provider_metadata. The OpenAI response wraps text in choices[0].message.content; the Anthropic response uses content[].text with a stop_reason.

Migrating an existing client

  • From a provider direct to the gateway: change the base URL and swap the API key — nothing else. See Quickstart for the two-step recipe.
  • Between dialects: path prefix, auth header, and response shape change (table above). Model names are shared — the same curated alias works on both surfaces (Models & Aliases).