Most LLM projects end up talking to more than one vendor: GPT for one job, Claude for another, Gemini or DeepSeek when cost matters. Each vendor has its own SDK, key, billing account and rate limits. An OpenAI-compatible gateway removes most of that: one base URL, one key, and the model is just a string.

This post shows the pattern with Gisoo, the gateway we run (disclosure: I'm on the team). It exposes 680+ models behind the standard OpenAI API shape, so the official openai SDKs work unchanged. The same code works with any OpenAI-compatible gateway; only the base URL and key change.

1. List the models (no key needed)

curl -s https://gisoo.pro/api/v1/models | jq '.data | length' # 682 curl -s https://gisoo.pro/api/v1/models \ | jq -r '.data[] | select(.type=="chat") | .id' | head 

Each entry has an id, an owned_by vendor and a type (chat, image, audio, embedding, video, music). Directly connected models use their own name (gpt-5-mini, deepseek-flash, gemini-3.6-flash); the rest carry an openrouter/ prefix (openrouter/anthropic/claude-sonnet-4.5).

2. Python: same client, three vendors

from openai import OpenAI client = OpenAI( base_url="https://gisoo.pro/api/v1", api_key="sk-gisoo-v1-...", # created in the Gisoo app ) question = "Explain idempotency keys in two sentences." for model in ["gpt-5-mini", "gemini-3.6-flash", "deepseek-flash"]: r = client.chat.completions.create( model=model, messages=[{"role": "user", "content": question}], ) print(f"--- {model}\n{r.choices[0].message.content}\n") 

Switching vendor is a one-word change. That makes it cheap to A/B models on your own prompts instead of trusting benchmarks.

3. Node.js with streaming

import OpenAI from "openai"; const client = new OpenAI({ baseURL: "https://gisoo.pro/api/v1", apiKey: process.env.GISOO_API_KEY, }); const stream = await client.chat.completions.create({ model: "openrouter/anthropic/claude-sonnet-4.5", messages: [{ role: "user", content: "Write a haiku about retries." }], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content ?? ""); } 

Streaming is plain SSE in the OpenAI format, so existing UI code (Vercel AI SDK, LangChain, LiteLLM clients) keeps working.

4. A cheap fallback chain

Because every model sits behind the same endpoint, fallback is a loop, not three SDKs:

from openai import OpenAI, APIError client = OpenAI(base_url="https://gisoo.pro/api/v1", api_key="sk-gisoo-v1-...") def ask(messages, models=("deepseek-flash", "gemini-3.6-flash", "gpt-5-mini")): last = None for m in models: try: return m, client.chat.completions.create(model=m, messages=messages, timeout=60) except APIError as e: last = e # vendor busy or refused: try the next one  raise last model, r = ask([{"role": "user", "content": "Summarise RFC 9110 in one line."}]) print(model, r.choices[0].message.content) 

Order the list cheapest-first and you only pay for the expensive model when the cheap one fails.

5. Not only chat

The same key covers the other OpenAI endpoints:

Task Endpoint
Chat / tools / JSON output POST /chat/completions, POST /responses
Embeddings POST /embeddings
Images POST /images/generations
Speech-to-text / text-to-speech POST /audio/transcriptions, POST /audio/speech
Video POST /videos

There is also an Anthropic-compatible endpoint (https://gisoo.pro/api) for tools that only speak the Anthropic Messages API, and a remote MCP server (https://gisoo.pro/api/mcp) for Claude Code, Cursor and Cline.

Things to check with any gateway

  • Data handling. Ask whether prompts are stored. (Gisoo's API stores metadata such as model, tokens and cost, not request or response bodies.)
  • Pricing. Per-token prices should match or be close to the vendor's, and be visible per model before you call it.
  • Model IDs. Pin exact IDs in production; aliases can move.
  • Limits. Per-key rate limits (Gisoo's default is 60 requests/minute) and per-key spend caps are worth setting before you ship.

Why we built it

Gisoo started for developers and teams in Iran, who can't pay OpenAI, Anthropic or Google directly: credit is paid in local currency, and there is an Iran-optimised mirror at ir.gisoo.pro. The API itself is the standard one, so the code above runs from anywhere.

Docs (Persian, code is universal): https://gisoo.pro/docs. Questions and corrections are welcome in the comments.