What is an OpenAI-compatible endpoint?

Updated 2026-07-16

An OpenAI-compatible endpoint is a server that implements the request and response contract of OpenAI's API, chiefly POST /v1/chat/completions, so that software written for OpenAI works against it by changing one value: the base URL. That single convention is why one integration now reaches models from every vendor, and why nearly every AI tool ships a base URL field.

Quick answer: a contract, not a brand.

OpenAI's API became the industry's de facto wire protocol the way HTTP verbs did: enough software was written against it that implementing the same contract became the obvious move for everyone else. An endpoint is OpenAI-compatible when it honors that contract: the same routes under a /v1 prefix, the same JSON request fields, the same response structure, the same streaming format, and Bearer-token auth. The consequence is interchangeability. The OpenAI SDK does not know it is talking to OpenAI; it knows it is POSTing JSON to base_url plus /chat/completions with an Authorization header. Any server that answers correctly is, from the SDK's point of view, OpenAI. That is the whole trick, and it is why vendors as different as DeepSeek, Moonshot, and Z.ai, self-hosted runtimes like vLLM and Ollama, and multi-vendor gateways like APIsRouter all expose the same surface.

The /v1 conventions, precisely.

Everything above is what a client may rely on. Note what is absent: nothing in the contract says which models exist, how they are priced, what rate limits apply, or which optional parameters every model honors. Those live outside the compatibility promise, which is exactly where the differences between endpoints, and the section below on what compatibility does not mean, come in.

  • Routes: POST /v1/chat/completions is the core; GET /v1/models lists addressable ids; common companions are /v1/embeddings and /v1/images/generations. The /v1 prefix is part of the contract, which is why a base URL missing it fails with 404s.
  • Auth: Authorization: Bearer <key>. Compatible endpoints accept their own keys in the same header.
  • Request: model as a plain string, messages as an array of role/content objects, plus the standard optional fields (temperature, max_tokens, tools, stream, response_format, and friends).
  • Response: an id, a choices array whose entries carry message and finish_reason, and a usage object with prompt_tokens, completion_tokens, total_tokens.
  • Streaming: stream: true switches the response to server-sent events, each chunk carrying choices[].delta fragments, terminated by a [DONE] sentinel.
  • Tools: function definitions in tools[], model-emitted tool_calls on the assistant message, results returned as role: "tool" messages.

base_url mechanics: why one line moves the whole stack.

Every official OpenAI SDK, and every tool built on them, constructs request URLs by concatenation: base_url + route. The default base URL points at OpenAI; override it, and every call the SDK makes follows. The key travels in the same client constructor. That is the entire migration surface: two values, usually two environment variables. The same mechanics power the base URL field in end-user tools. When Open WebUI, Cline, LibreChat, or OpenClaw asks for an OpenAI API base URL, it is exposing this constructor argument. Point it at a compatible endpoint, supply that endpoint's key, and the tool's whole model roster comes from the endpoint's /v1/models listing. Two mechanical gotchas recur everywhere. The /v1 suffix belongs in the base URL exactly once: omitted, routes miss; duplicated, logs show /v1/v1 404s. And the model field must name an id the endpoint actually serves, for which the /v1/models listing is the ground truth, ids are exact strings, not fuzzy names.

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["APISROUTER_API_KEY"],          # value two
    base_url="https://api.apisrouter.com/v1",          # value one
)

# same code, any catalog model: the string decides the vendor
for model in ("gpt-5.5", "claude-sonnet-4-6", "deepseek-v4-flash"):
    r = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": "Reply with one word: ok"}],
        max_tokens=8,
    )
    print(model, "->", r.choices[0].message.content)

What compatible does not mean.

Compatibility is a shape guarantee, not a semantics guarantee, and the gap between the two is where integrations actually break. Model behavior differs: the same prompt on a Claude id and a GPT id produces different output styles, tool-call eagerness, and refusal boundaries; the contract carries the request, it does not normalize the model. Parameter support differs per model: reasoning-era models reject or ignore parameters that older ones honored, temperature restrictions and token-field renames being the famous cases, and a compatible endpoint passes those vendor rules through rather than erasing them. Coverage differs too: compatible almost always means chat completions plus the models listing, while the rest of OpenAI's product surface, Assistants, fine-tuning, Realtime, and the newer Responses API, is implemented endpoint by endpoint or not at all. And operational properties, latency, rate limits, uptime, logging policy, are entirely the endpoint operator's, not the contract's. The practical takeaway: treat compatible as the beginning of due diligence, not the end. The contract guarantees your code will speak; the endpoint's documentation and a smoke test tell you whether the conversation will go well.

The contract moves your code; judgment still picks the endpoint and the model.
Compatibility promisesIt does not promise
Your OpenAI-SDK code runs unchangedThat every model behaves like an OpenAI model
Request and response shapes matchThat every optional parameter works on every model
Streaming and tool-call formats parseFull coverage of Assistants, Realtime, or Responses
/v1/models tells you what is addressableAny particular latency, limits, or uptime
One-line migration in and outIdentical outputs after you migrate

Pay-as-you-go · transparent per-model pricing

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModelOfficial PriceOur Price
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M
Gemini 3.5 Flash$1.50 / $9.00 per M$1.20 / $7.20 per M
DeepSeek V4 Flash$0.14 / $0.28 per M$0.13 / $0.25 per M
GLM-5.2$1.14 / $4.00 per M$1.03 / $3.60 per M

How to verify an endpoint in three requests.

Before pointing anything real at a compatible endpoint, run the three-step smoke test. List the models: proves auth and shows the exact ids. Complete one chat turn on the id you intend to use: proves the core contract end to end. Stream one turn: proves the SSE path, which is where thinner implementations wobble first. If your workload uses tools or JSON mode, add a fourth request exercising that feature on the specific model, because feature support is per model, not per endpoint. Sixty seconds of curl replaces an afternoon of debugging a tool three layers up, since a failure here is unambiguous: the endpoint, the key, or the id, before any application code enters the picture.

# 1) auth + catalog
curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -40

# 2) one turn on the exact id you plan to run
curl -s https://api.apisrouter.com/v1/chat/completions \
  -H "Authorization: Bearer $APISROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-4-6",
       "messages":[{"role":"user","content":"Say ready."}],
       "max_tokens":8}'

# 3) the streaming path
curl -sN https://api.apisrouter.com/v1/chat/completions \
  -H "Authorization: Bearer $APISROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet-4-6","stream":true,
       "messages":[{"role":"user","content":"Count to three."}]}'

The hub: where to go from here.

This page is the definitional root of a cluster. If you came here from a specific tool's base URL field, the per-tool guides in the links below walk the exact settings for Open WebUI, LibreChat, Cline, Dify, Cursor, OpenClaw, and more, each one an application of the mechanics above. If you are weighing where such an endpoint should live in your architecture, the gateway-versus-aggregator taxonomy and the API-shape comparison are the two companion explainers. And if you just want the working endpoint: APIsRouter serves the compatible surface, /v1/chat/completions, /v1/models, /v1/images/generations, plus Anthropic's /v1/messages dialect, against a multi-vendor catalog with one key. The smoke test above runs against it verbatim.

FAQ

What does OpenAI-compatible API mean?

A server that implements OpenAI's API contract, the /v1 routes, request and response JSON shapes, Bearer auth, and SSE streaming, so software written for OpenAI works against it by changing the base URL and key. It is a wire-format standard, not an OpenAI product.

How do I point the OpenAI SDK at a different endpoint?

Pass base_url and api_key to the client constructor (or set the equivalent environment variables). The SDK builds every request as base_url plus route, so all calls follow. Include /v1 in the base URL exactly once.

Can an OpenAI-compatible endpoint serve Claude or Gemini models?

Yes, that is the point of multi-vendor gateways: the model field is a plain string, so an endpoint can route claude-sonnet-4-6 to Anthropic and gpt-5.5 to OpenAI behind one contract. The /v1/models listing shows exactly which ids an endpoint serves.

Is every OpenAI API feature available on compatible endpoints?

No. Compatible reliably means chat completions plus the models listing, commonly embeddings and images. Assistants, fine-tuning, Realtime, and the newer Responses API are implemented per endpoint or not at all, and optional parameters remain per-model. Check the endpoint's docs for its exact surface.

Why does my tool fail after I set a custom base URL?

The recurring trio: a missing or doubled /v1 in the URL (404s, or /v1/v1 paths in logs), a model id that does not match the endpoint's catalog exactly, or a key pasted with whitespace. The three-request curl smoke test isolates all of them in a minute.

Is OpenAI-compatible the same as an aggregator?

No, it is orthogonal. Compatible describes the interface; aggregator describes who runs the routing and holds vendor accounts. Vendors, self-hosted routers, and hosted aggregators can all expose the identical compatible surface, which is what keeps your choice among them reversible.