Education

Claude, GPT, and Gemini via One OpenAI-Compatible API

Anthropic and Google both ship their own OpenAI-compatible shim now, and neither is built to run production traffic on: dropped parameters, hoisted system messages, no guaranteed tool schemas. Here's what breaks in each one, and how to get Claude, GPT, and Gemini behind a single API key instead.

BSBrittany Seales· Marketing5 min read
SayGm article about accessing Claude, Gemini, GPT, through their OpenAI-Compatible API.

Anthropic and Google have each built their own OpenAI-compatible layer this year, so switching your code to call Claude or Gemini through an OpenAI-compatible API is no longer the rewrite it used to be. What's missing is a compatibility layer for switching between all three at once, and that's the gap this guide closes.

Anthropic's own documentation is upfront that its shim exists to test model capabilities, not to run production traffic on, and it silently drops things like prompt caching and strict tool schemas along the way. Google's Gemini shim works well for basic chat completions but doesn't promise every OpenAI parameter maps cleanly either. Add OpenAI's native API to the mix, and you've got three base URLs, three keys, and three sets of undocumented edge cases to track, even though every request looks the same shape on the wire.

This guide walks through what each provider's own compatibility layer actually supports, where each one breaks, and how to collapse all three into a single base URL and key, the approach SayGm takes, without losing the ability to fall back if one provider degrades.

SayGm gateway moving between LLM models

Table of Contents

Why One Shim Doesn't Cover Three Providers

An OpenAI-compatible API is any endpoint that accepts the same request shape OpenAI's SDK sends: a messages array, the same streaming flags, the same tool-calling schema. Because that shape became the default years ago, most model makers now offer some version of it so existing OpenAI-based code doesn't need a full rewrite to try a different model.

The catch is that "compatible" doesn't mean identical. Anthropic's own OpenAI SDK compatibility docs describe the layer as intended to test and compare model capabilities, not as a production-ready path, and they list specific gaps: the strict parameter for function calling is ignored, so tool-use JSON isn't guaranteed to follow the schema you gave it; prompt caching isn't supported through the shim, even though it is in Anthropic's native SDK; and every system or developer message gets concatenated into a single system message at the start of the conversation, since Claude only accepts one initial system message. None of that breaks a quick test. All of it can break a production agent that depends on tool schemas holding or prompts caching cleanly.

Google's Gemini OpenAI compatibility guide is more usable out of the box: streaming, function calling, and the standard chat completions shape all work. But Google is equally clear that provider-specific options don't all map cleanly between the two APIs, and recommends calling the native Gemini API directly the moment you need a Gemini-specific feature.

Individually, each shim is a reasonable stopgap for evaluating one model. Wire all three into one application, though, and you're maintaining three base URLs, three keys, three billing dashboards, and three different lists of silently-dropped parameters, for the privilege of writing code that looks identical across all of them.

Calling Claude Through an OpenAI-Compatible API

Anthropic's shim needs three changes to existing OpenAI SDK code: a new base URL, a Claude API key in place of an OpenAI one, and a Claude model name. This is the fastest way to test how to use the Claude API without committing to Anthropic's native SDK yet.

python
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get("ANTHROPIC_API_KEY"),
    base_url="https://api.anthropic.com/v1/",
)

response = client.chat.completions.create(
    model="claude-opus-5",
    messages=[{"role": "user", "content": "Explain how AI works"}],
)

That's the whole migration for a basic chat completion. Where it gets more involved is anything relying on the gaps above: if your agent leans on strict tool schemas, prompt caching, or Claude's extended thinking output, you'll need Anthropic's native API to get the full feature, not the OpenAI-shaped version of it.

Calling Gemini Through an OpenAI-Compatible API

Gemini's version of the same swap points at Google's endpoint instead. Grab a Gemini API key from Google AI Studio first if you don't already have one:

python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_GEMINI_API_KEY",
    base_url="https://generativelanguage.googleapis.com/v1beta/openai/",
)

response = client.chat.completions.create(
    model="gemini-3.7-flash",
    messages=[{"role": "user", "content": "Explain how AI works"}],
)

Streaming and function calling both work through this endpoint, and Gemini's reasoning controls map onto OpenAI's reasoning_effort parameter, though not always to an exact equivalent depending on which Gemini model you're calling. If you want a Gemini-only feature the day Google ships it, the native SDK is still the faster path to it.

What About Calling GPT Directly?

GPT needs no shim, since it's the shape everything else is imitating, but that's the problem in reverse: code already built around OpenAI's format doesn't make switching models any easier. It makes switching away from OpenAI easier once you already have Anthropic's and Google's shims wired in, but you're still holding three separate keys and three separate rate limits to get there.

One Base URL for All Three

This is the piece none of the three providers' own shims solve on their own: a single endpoint that already knows how to route to Claude, GPT, or Gemini, without you tracking which quirks belong to which shim.

Point an existing OpenAI SDK integration at SayGm's endpoint instead of any single provider's, and the swap looks the same as the ones above: change the base URL, change the key, pick a model.

python
from openai import OpenAI

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

response = client.chat.completions.create(
    model="claude-opus-5",
    messages=[{"role": "user", "content": "Explain how AI works"}],
)

Swap model to gpt-5.6-luna or gemini-3.7-flash and nothing else in the code above changes. That's also true in Cursor, Cline, Claude Code, and the Vercel AI SDK, since all four already read the OpenAI-compatible configuration shape; pointing their provider settings at one base URL and key covers every model in the catalog rather than one provider's models. The integrations guide covers the exact settings for each tool.

Two things are worth knowing about what you get and don't get by routing this way. First, you're still bound by whichever provider's real feature set you're calling. Routing Claude through a gateway doesn't unlock prompt caching that the OpenAI shape doesn't support; the same limits documented above still apply. Second, every request through SayGm's gateway is routed through a hardware-attested TEE, so the identity behind a request stays sealed from the gateway itself. That's a real difference from calling a provider's own shim directly, since SayGm structurally can't read what passes through it, but it's a separate guarantee from what the model maker itself receives; our breakdown of what an LLM gateway actually is covers that distinction in more depth.

Common Questions About Migrating to a Unified API

Do I lose Claude- or Gemini-specific features by going through an OpenAI-compatible layer?

You lose whatever the shim you're routing through doesn't map, the same as calling Anthropic's or Google's own compatibility layer directly. Extended thinking output, prompt caching, and PDF processing on Claude, or Gemini-specific reasoning parameters, still need the native API if you depend on them.

Is migrating to a gateway free?

Signing up and getting a key doesn't cost anything on its own; you're billed per token the same as calling a provider directly. Current, published rates are listed per model, so check the one you're switching to before committing production traffic.

What happens if one provider I'm calling goes down?

That's the point of routing through one endpoint rather than three: a gateway built for failover can reroute to a fallback model without you changing application code, where three separate direct integrations would each need their own retry logic.

Which Migration Path Fits Your Stack?

If you're calling one provider and just want to test another, each provider's own OpenAI-compatible shim is a fine way to try it; that's what it's built for. The moment you're running two or three in production, though, you're maintaining separate keys, separate dashboards, and separate lists of silently-dropped parameters for code that's supposed to look identical. Collapsing that into one base URL and key doesn't erase the underlying limits of any single provider's shim, but it does mean you stop tracking three of them by hand.

Ready to try it? The quickstart guide gets you from signup to a first request in a few minutes.

About SayGm

SayGm is a drop-in inference gateway for teams who don't want to just take a company's word that their prompts are private. Every request runs inside a hardware-verified confidential environment - not even SayGm can see what's inside it. That's not a policy, it's provable. Swap in your existing OpenAI, Anthropic, or Gemini code and you're covered in minutes, at transparent, published rates with no hidden markup.

Say gm to AI at saygm.com.

Website | Twitter | Discord | Blog | Medium | Docs

  • API
  • Inference
  • LLM Gateway
BS

Brittany SealesMarketing

Saying gm to marketing (and AI)

X ↗