Sam Austinon October 29, 202612 min read

OpenAI-Compatible APIs: The Fields They Ignore

OpenAI-Compatible APIs: The Fields They Ignore
Contents

Figure 1: OpenAI-Compatible APIs: The Fields They Ignore — one request shape, four different contracts behind it

You change one URL, swap one key and your OpenAI client suddenly talks to Claude, Gemini or a model on your laptop. Magic? Not quite. It is a shared request shape that many providers agreed to copy, and "copy" is doing a lot of work in that sentence.

I read four providers' own compatibility pages: Anthropic, Google, Ollama and vLLM. I could not fetch OpenAI's own API reference in this session, so the OpenAI side below rests on those pages describing it. My checker script reads one request against all four pages and sends the same client code to mock servers.

What "Compatible" Actually Means

OpenAI's Chat Completions API became the common shape. A client posts messages and a model to /chat/completions and reads back choices. Providers that accept that shape let you reuse the official OpenAI SDKs by changing the base URL and the key.

Provider Base URL What the page says
Anthropic https://api.anthropic.com/v1/ Claude API key and Claude model name [1]
Google Gemini https://generativelanguage.googleapis.com/v1beta/openai/ "updating three lines of code" plus a Gemini API key [2]
Ollama http://localhost:11434/v1/ "requires an API key value, but Ollama ignores it" [3]
vLLM http://localhost:8000/v1 in the page's example --api-key or VLLM_API_KEY for authentication [4]

That is the whole trick, and it is why one client can work with many providers. One OpenAI(...) constructor with a different base_url covers all four.

from openai import OpenAI

client = OpenAI(base_url="https://api.anthropic.com/v1/", api_key=ANTHROPIC_KEY)

# The request body stays the same. Only the model name changes.

Same Shape, Different Promises

Compatibility covers the request and response shape. It does not promise identical behaviour. Every page I read has a list of exceptions, and the way each provider handles unsupported fields differs.

Provider Unsupported fields Notes
Anthropic "Most unsupported fields are silently ignored" [1] response_format, seed, logprobs, user, metadata, prediction, service_tier, audio, logit_bias, store, modalities and top_logprobs are all marked Ignored [1]
Gemini Silently ignored unless listed [2] Parameters outside the documented list or extra_body are ignored by the compatibility layer [2]
Ollama Not documented per field The page lists supported fields instead; see below [3]
vLLM user is ignored [4] parallel_tool_calls: false returns zero or one tool call [4]

Anthropic adds three structural rules that are easy to miss [1]:

  1. n must be exactly 1.
  2. System and developer messages are hoisted and concatenated into one top-level system field, wherever they appear in the conversation.
  3. temperature must be between 0 and 1, and values above 1 are capped at 1. On Claude 4.7 and later models and Claude Mythos Preview, any value below 1 returns a 400 error, and so does setting both temperature and top_p [1]. top_p on those models returns a 400 for any value other than the default 0.99 [1].

Ollama is the page where the common advice is most out of date. Its supported request fields now include tool_choice, logit_bias, user, n and reasoning_effort, and image content accepts both base64 and image URLs [3]. That is a direct correction to the claim that Ollama does not support these.

The Check I Ran

My checker script encodes only what those pages say, then sends one request to mock servers built from each profile. The request carried response_format, seed, n=2, user and tool_choice.

  • Anthropic's profile produced eight findings.
  • The vLLM profile produced two.
  • Ollama's produced six under the field table the script first encoded, and its current page has moved several of those fields to supported [3].

Same request, different outcomes. The mock servers are my code, not the providers, so this measures how far apart the documented contracts are — not how the live APIs behave.

Silent Ignoring Is the Dangerous Part

An error is easy to catch. A silently ignored field is not.

Ask Anthropic's compatibility layer for response_format: json_object and the field is ignored, so your parser gets prose [1]. Set seed and you will not get reproducible output, because that is ignored too [1]. Anthropic's own page says the layer is "primarily intended to test and compare model capabilities, and is not considered a long-term or production-ready solution for most use cases" [1]. For the full feature set it points to the native API [1].

In my mock test, a server applying Anthropic's documented rules returned HTTP 200 for a request carrying seed, user and response_format, then reported that it ignored all three. With n=2 it returned a 400. The mock is my code, and the 400 status is my assumption, since the page only says n "must be exactly 1."

Gemini has the same failure mode with a different trigger. Its compatibility layer silently ignores any parameter that is not in its documented list or in extra_body [2]. That includes the Gemini-specific settings you probably want: cached_content and thinking_config travel through extra_body, not the top level [2].

Features That Need the Native API

Compatible layers tend to drop the interesting features.

Provider What does not come through the OpenAI shape Where it lives instead
Anthropic Thinking output, prompt caching, structured outputs, strict tool schemas [1] Native Claude API and Anthropic SDKs [1]
Gemini cached_content, thinking_config, safety settings, Search grounding [2] extra_body on the OpenAI path, or the GenAI SDK [2]
Ollama Context size [3] A Modelfile with PARAMETER num_ctx [3]
vLLM Non-OpenAI sampling parameters such as top_k [4] extra_body={"top_k": 50} [4]

Two of these deserve a caveat.

Gemini's Batch API is not one of the gaps. You can create batch jobs, submit them and check their status through the OpenAI library, as long as the JSONL file uses OpenAI's input format [2]. That is a correction to the widespread claim that batching forces you onto the GenAI client.

vLLM's Chat Completions endpoint only applies to text generation models that ship a chat template [4]. Its page also carries a security note worth repeating: --api-key and VLLM_API_KEY only authenticate paths under /v1, /v2 and /inference. Other endpoints on the same server, most notably /invocations, are not authenticated [4].

One Field, Three Answers: tool_choice

tool_choice is a good example of one field with three answers.

Provider tool_choice behaviour
Anthropic "required" and named-function values force a tool call, but Claude Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1 return an error for forced tool use, so use "auto" on those models [1]
Gemini Not called out on the compatibility page, which routes the parameters it does document through extra_body [2]
Ollama Listed as a supported request field [3]
vLLM Not called out on the page I read [4]

So a request that works on one provider can fail or be ignored on the next. That is not a bug in your client. It is the contract.

How to Stay Portable

  1. Keep provider settings in configuration, not code. Base URL, key and model name belong in environment variables or a config file.
  2. Stick to the common core: messages, model, temperature, max_tokens, stream and tools.
  3. Treat every other field as provider-specific, and check that provider's page before you rely on it.
  4. Validate outputs yourself, for example by parsing JSON, instead of trusting response_format.
  5. Test each provider with your real requests, not a hello-world. A one-line completion proves nothing about tool calls or JSON mode.
  6. Use a gateway such as LiteLLM if you want one place to handle the differences. That keeps application code simple, at the cost of another service to run — the gateway roundup covers the options.

What I Could Not Verify

I would rather publish the gaps than paper over them.

  • I could not fetch OpenAI's own API reference in this session. Everything attributed to "the OpenAI shape" above comes from the four provider pages describing it, not from OpenAI's specification.
  • vLLM's first documentation URL returned a 404, so I read the current page under /serving/online_serving/openai_compatible_server/ instead. It states the base URL, the --api-key flag and the extra_body behaviour [4].
  • The checker script encodes only what those pages say. Where a page lists a field without saying whether it is ignored or rejected, the script reports it as unstated. The mock servers are mine, and the 400 for n=2 is my assumption.
  • The Gemini profile is thin. I included its base URL, its silent-ignore rule, extra_body and the reasoning_effort mapping, not a full field list [2].
  • Provider pages change quickly, and Anthropic's and Gemini's name specific models. I read all four on 2026-10-29 [1][2][3][4].

Common Pitfalls

  1. Assuming "compatible" means "identical." It means the shape parses, not that the behaviour matches.
  2. Sending response_format and trusting it. Anthropic ignores it, so your JSON parser gets prose [1].
  3. Setting seed for reproducibility. Ignored on Anthropic, so repeated runs still vary [1].
  4. Sending n=2 to Claude. n must be exactly 1 [1].
  5. Setting temperature on Claude 4.7 or later without checking. Anything below 1 returns a 400, and combining it with top_p does too [1].
  6. Assuming Ollama rejects tool_choice or image URLs. Both are supported now [3].
  7. Assuming Gemini batching needs the GenAI client. The Batch API works through the OpenAI library with OpenAI-format JSONL [2].
  8. Leaving vLLM's /invocations reachable. --api-key does not cover it [4].

Best Book to Read

CoverBookDescriptionGet it
Cover of “API Design Patterns” API Design Patternsby JJ Geewax the vocabulary for contracts, compatibility and versioning that makes the differences above easier to reason about. View on Amazon

As an Amazon Associate I earn from qualifying purchases. Links on this page are affiliate links, and I may earn a commission at no extra cost to you.

Wrapping Up

OpenAI-compatible APIs work because providers copied one request shape, and they differ because each copied a different subset. Treat the shared shape as a convenience and the provider's compatibility page as the real contract.

Pick your two most-used providers, read their exception lists and write down which of your request fields get ignored. Then run one real request through each and compare the output, not the status code.

If you route through a gateway instead, LiteLLM vs OpenRouter vs Portkey covers where those differences get normalised, and the Aider, Claude Code and Cursor proxy guide covers the clients that consume these endpoints.

Frequently Asked Questions

Do OpenAI-compatible APIs work with the official OpenAI SDK?

Yes, that is the point of the shape. You construct the client with a different base_url and API key, keep the request body, and change the model name. Anthropic, Gemini, Ollama and vLLM all document that path, and each lists the fields it does not honour.

Which fields does Anthropic's compatibility layer ignore?

response_format, seed, logprobs, user, metadata, prediction, service_tier, audio, logit_bias, store, modalities and top_logprobs are marked Ignored, along with presence_penalty, frequency_penalty and reasoning_effort. Most unsupported fields are silently ignored rather than rejected, so a 200 response does not prove the field took effect.

Does Gemini's OpenAI compatibility support the Batch API?

Yes. You can create batch jobs, submit them and check their status through the OpenAI library, provided the JSONL file uses OpenAI's input format. Parameters outside the documented list or extra_body are silently ignored by the compatibility layer.

Why does temperature return a 400 error on Claude 4.7 and later?

Those models accept only the default sampling settings through the compatibility layer. temperature must be between 0 and 1, with anything above 1 capped, but on Claude 4.7 and later models and Claude Mythos Preview any value below 1 returns a 400, and setting both temperature and top_p returns a 400 as well.

Can I set the context size through Ollama's OpenAI API?

No. The OpenAI API has no field for it, so Ollama documents a Modelfile with PARAMETER num_ctx instead: create the model with ollama create, then call the API with the new model name.

Sources

  • [1] Anthropic, OpenAI SDK compatibility — the base URL and quickstart, "Most unsupported fields are silently ignored rather than producing errors", the full Ignored list (response_format, seed, logprobs, user, metadata, prediction, service_tier, audio, logit_bias, store, modalities, top_logprobs, presence_penalty, frequency_penalty, reasoning_effort), n must be exactly 1, system and developer messages hoisted into the top-level system field, temperature between 0 and 1 with values above 1 capped and a 400 for anything below 1 on Claude 4.7 and later models and Claude Mythos Preview, top_p returning a 400 for anything other than 0.99 on those models, a 400 when both are set, forced tool_choice erroring on Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1, prompt caching unsupported through the layer but supported in the Anthropic SDKs, thinking output and strict schemas not carried through, and the "not considered a long-term or production-ready solution" caveat: docs.anthropic.com/en/api/openai-sdk
  • [2] Google, Gemini OpenAI compatibility — the https://generativelanguage.googleapis.com/v1beta/openai/ base URL, "by updating three lines of code", parameters outside the documented list or extra_body being silently ignored, cached_content, thinking_config, safety settings and Search grounding routed through extra_body, the reasoning_effort to thinking_level and thinking_budget mapping across model generations, and the Batch API being usable through the OpenAI library with OpenAI-format JSONL: ai.google.dev/gemini-api/docs/openai
  • [3] Ollama, OpenAI compatibility — the http://localhost:11434/v1/ base URL, "The client requires an API key value, but Ollama ignores it", supported request fields including tool_choice, logit_bias, user, n and reasoning_effort, image content as base64 or an image URL, PARAMETER num_ctx in a Modelfile as the only way to set context size, the /v1/completions field list with prompt limited to a string, and stateful /v1/responses being unsupported: docs.ollama.com/api/openai-compatibility
  • [4] vLLM, OpenAI-Compatible Server — /v1/chat/completions applying only to text generation models with a chat template, the user parameter being ignored, parallel_tool_calls: false returning zero or one tool call while true guarantees nothing, extra_body for non-OpenAI parameters such as top_k, the http://localhost:8000/v1 base URL in the example, and --api-key or VLLM_API_KEY authenticating only /v1, /v2 and /inference paths while /invocations stays open: docs.vllm.ai/en/latest/serving/online_serving/openai_compatible_server/

What are You Looking For?

esc