Which Model APIs Work With the OpenAI SDK?

Searching for "model apis api compatible with openai" usually means one thing: you want to keep your OpenAI client code and change only where it points. Compatibility comes in degrees, so here is what to check and a script that checks it for you.

One plug adapter linking several different sockets, representing OpenAI-compatible endpoints

Last updated

What compatible means in practice

The OpenAI SDKs are configurable. They accept a base_url and an API key, build a request in a known shape and parse the reply in a known shape. Any service that accepts that shape and answers in that shape will work with the SDK. That is the whole idea, and it is why so many providers copy the format.

The catch is that copying the shape of one method does not mean copying the others. An endpoint may handle /chat/completions well and skip tool calling, stream without a final usage chunk, or return errors in a different structure that your retry code does not recognize. The SDK will not warn you. It will simply raise an exception in production.

So treat compatibility as a list of separate features and test each one.

The features worth testing

Use this table as a checklist for any candidate. The right-hand column shows what this service documents, so you can see how the check reads in practice.

FeatureWhy it mattersThis service
Chat completionsThe core method most apps useYes, POST /v1/chat/completions
Responses methodNewer OpenAI clients use itYes, POST /v1/responses
Model listMany tools call it on startupYes, GET /v1/models
Streaming (SSE)Needed for chat UIsYes, usage arrives at the end
Tool callingAgents and function callsYes, including streamed tool calls
JSON modeStructured output for parsersYes, json_object
Sampling parametersTuning style and repetitiontemperature, top_p, stop, seed, penalties
Rate-limit signalsLets clients back off correctlyHTTP 429, codes rate_limited and concurrency
Balance visibilityAvoid surprise outagesX-Balance-USD header and a balance endpoint

Add two things the table cannot show: the context window and the model's behavior on your own prompts. Here the window is 100,000 tokens for prompt plus completion.

One script that tests any endpoint

The script below runs five checks against whatever base URL you give it: model list, a plain chat call, streaming, JSON mode and a forced tool call. The defaults point to this service, and two environment variables swap in another provider so you can run an identical test on each candidate.

import json
import os

from openai import OpenAI

BASE_URL = os.environ.get("API_BASE", "https://api.modelapis.cc/v1")
MODEL = os.environ.get("API_MODEL", "uncensored")
client = OpenAI(base_url=BASE_URL, api_key=os.environ["API_KEY"])
ASK = [{"role": "user", "content": "Reply with the single word: ready"}]


def check_models():
    assert client.models.list().data, "empty model list"


def check_chat():
    r = client.chat.completions.create(model=MODEL, messages=ASK, max_tokens=20)
    assert r.choices[0].message.content
    assert r.usage and r.usage.total_tokens > 0, "no usage block"


def check_stream():
    s = client.chat.completions.create(model=MODEL, messages=ASK, stream=True)
    text = "".join(c.choices[0].delta.content or "" for c in s if c.choices)
    assert text


def check_json():
    r = client.chat.completions.create(
        model=MODEL,
        messages=[{"role": "user", "content": "Return a JSON object with key ok set to true."}],
        response_format={"type": "json_object"},
    )
    assert json.loads(r.choices[0].message.content)


def check_tools():
    tools = [{"type": "function", "function": {
        "name": "get_time", "description": "Get the current time",
        "parameters": {"type": "object", "properties": {}}}}]
    r = client.chat.completions.create(
        model=MODEL, messages=ASK, tools=tools,
        tool_choice={"type": "function", "function": {"name": "get_time"}})
    assert r.choices[0].message.tool_calls, "no tool call returned"


for fn in (check_models, check_chat, check_stream, check_json, check_tools):
    try:
        fn()
        print("ok  ", fn.__name__)
    except Exception as e:
        print("FAIL", fn.__name__, type(e).__name__, str(e)[:100])

Run it with API_KEY=... python check.py. A failure on one line tells you exactly which feature to ask the provider about. A clean run does not prove quality, but it proves your client code will not break.

How to read the results

An ok on every line means the SDK parsed every response shape without errors. A failure on check_tools alone usually means the endpoint ignores tools or the model does not call them reliably. A failure on check_json often means the answer came back wrapped in prose or a code fence. A failure on check_stream can be a proxy that buffers events, a missing final chunk or an endpoint that sends no delta content at all.

Run the script twice. The first run tells you about support, the second, with a few seconds of delay, about stability. Also run it from the machine where your app will live, because networks and proxies change what streaming looks like.

Testing the Responses method

Newer OpenAI client code increasingly calls the Responses method instead of chat completions. This service accepts POST /v1/responses, so the same client can use either. Not every compatible provider implements it, which makes it worth a separate check:

from openai import OpenAI

client = OpenAI(base_url="https://api.modelapis.cc/v1", api_key="YOUR_API_KEY")

r = client.responses.create(
    model="uncensored",
    input="List three checks for an OpenAI-compatible endpoint.",
)
print(r.output_text)

If a provider returns 404 here but passes the chat test, your older code is fine and newer SDK features that rely on this method will not be. Decide which of your tools need it before you choose.

Where compatible endpoints usually differ

Error handling

Rate limits are the most common surprise. This API answers with HTTP 429 and an error code of rate_limited for too many requests per minute, or concurrency for too many at once. On temporary overload it returns 429 with Retry-After: 5. Another provider may use different codes or none, so test your backoff logic against each.

Limits

A full key here allows 8 concurrent requests and 300 requests per minute, and a trial key allows 2 and 60. A streamed request holds its concurrency slot until the stream ends, which matters for chat apps. Request bodies are capped at 8 MB.

Model naming

Some services accept any string as a model name and quietly map it. Others reject unknown names. Here you pass uncensored, and the documentation lists the details.

Behavior

Two compatible endpoints can answer the same prompt very differently. This service runs one open-weight model tuned to answer without content refusals for lawful adult use, with a hard limit on sexual content involving minors. A mainstream vendor's model will refuse more. Neither is wrong, but they suit different products.

A practical way to decide is to write down three requirements that must hold (for example streaming, tool calls and a 429 you can recognize), run the script on each candidate and rule out any that fail. Among the survivors, compare price on your own token mix and behavior on your own prompts. That order saves time, because feature gaps are quick to find and cost comparisons are not worth doing for an endpoint that cannot run your code.

When another option is the better fit

We do not try to be the answer to every query. Pick something else when:

  • You need image, audio or video generation, embeddings or fine-tuning. This service is text only.
  • You need the output of one particular vendor's model. We are not the official API of any vendor and we do not route across vendors.
  • Your policy requires an enterprise contract or a specific compliance certification. We do not make claims about either here.

Pick this endpoint when you want an open-weight chat model without content refusals for lawful adult use, an OpenAI-shaped interface and per-token billing. The rates are $0.15 per 1M input tokens and $0.50 per 1M output tokens, detailed on the pricing page.

Try it with a trial key

Create an account with Google or with email and password, then open the API key page. New users can claim $0.50 of trial credit with one click. It lasts 7 days and needs no card, which is plenty to run the script above many times.

Once your results are in, compare them side by side. Keep the output of each run and add the columns that matter to you: refusals on your sample prompts, time to first token on your network, and the cost of the same prompt set at each provider's current prices.

Common questions

Is OpenAI-compatible the same as OpenAI?

No. It means the endpoint accepts the same request format, so OpenAI SDKs work after changing the base URL and key. The model behind it can be completely different.

Which base URL do I use for the OpenAI SDK here?

Use https://api.modelapis.cc/v1 as the base URL, your key as the Bearer token and uncensored as the model ID.

Does streaming work with the SDK's stream option?

Yes. Set stream to true and read the server-sent events as usual; usage is sent at the end of the stream.

How do I check my balance from code?

Read the X-Balance-USD response header on any call, or request GET /v1/balance or the OpenAI-style credit_grants path under /v1/dashboard/billing.

Access your key instantly

Sign up, retrieve your key, update your base URL. That’s all.

Create keyView documentation