EN ▾
Get API key

What Does OpenAI-Compatible Mean for an API?

An API is called openai-compatible when you can point an OpenAI SDK at its URL, swap the key, and your existing code keeps working. The label describes the wire format, nothing more.

Updated

Two different machines joined by one standard connector, illustrating a shared API format

Key points

  • The label covers URL paths, JSON request and response shapes, Bearer auth and SSE streaming.
  • It says nothing about which model answers, how it behaves, or what it costs.
  • Switching usually means changing two values: base URL and API key.
  • Test streaming, tools, JSON mode and error codes before you rely on a provider.

The short answer

When a provider says its API is openai-compatible, it means that it accepts the same HTTP requests the OpenAI client libraries send and returns responses in the same shape. You keep your code, change the base URL and the key, and the call goes to a different server.

That is the whole promise. It is a statement about the interface, like saying two chargers use the same plug. It does not tell you what is on the other end of the cable. The model, its safety rules, its price and its limits are all decided by the provider, and they differ a lot.

What the label actually covers

In practice, OpenAI compatibility is a short list of concrete things. If a provider supports all of them, most client code runs unchanged.

  • Paths. Chat requests go to POST /v1/chat/completions and the model list comes from GET /v1/models.
  • Auth. The key travels in an Authorization: Bearer header.
  • Request body. A model string, a messages array of objects with role and content, and optional sampling fields such as temperature, top_p, stop and seed.
  • Response body. A choices array with the assistant message, a finish_reason, and a usage object with token counts.
  • Streaming. With stream: true the server sends Server-Sent Events, each carrying a small JSON delta, ending with a final marker.
  • Optional features. Tool calling, JSON mode and similar fields, where the provider chooses to support them.

Because so many tools were written against this format, it became a common target. Editors, agent frameworks, roleplay front ends and plain scripts all let you enter a custom base URL, and that is all they need.

Why one format became the common target

The chat completions format spread because it was simple and arrived early. A tool author who supports it once can reach many backends, and a backend author who supports it once can reach many tools. That is a good deal for both sides, so the format stuck, even among services that have nothing to do with the company that designed it.

For you as a developer this has a practical meaning. Your code does not need a different integration for every provider. You can move a prototype between endpoints in an afternoon, compare two models on the same prompts, or keep a second provider as a fallback when the first one is slow. The cost of changing your mind is low, and that makes it easier to try a new service without committing to it.

The flip side is that the shared surface hides real differences. Because switching is so easy, it is tempting to assume everything behind the URL is equivalent. It is not, and the sections below show where the gaps usually appear.

What it does not tell you

Here is where people get surprised. The label leaves out everything that determines whether the API is useful for your work.

The model behind it

A compatible endpoint can serve any model. Some serve open-weight models, some route to several vendors, some wrap a proprietary model. Compatibility does not mean the service is run by OpenAI, and it does not mean the model behaves like one of theirs. The model name you pass in model is just a string the provider defines.

Refusal behavior

Content rules belong to the model and the provider, not to the protocol. Two compatible APIs can answer the same prompt in opposite ways. If your use case is fiction, roleplay or other lawful adult content, check what the provider says about refusals before you wire anything up.

Feature depth

Some providers implement chat only. Others add tools, JSON mode, log probabilities or extra endpoints. A client that sends a field the server ignores will not always fail loudly, so a silent mismatch is possible.

Limits, pricing and errors

Rate limits, context length, maximum body size and price per token are all provider choices. Error bodies also differ in detail even when the HTTP status codes match, so retry logic should key on status codes and headers rather than on message text.

A quick compatibility test

You can verify a provider in a few minutes with three requests. Replace the key with your own. This example uses the base URL of this site.

curl https://api.kimicode.top/v1/models \
  -H "Authorization: Bearer YOUR_API_KEY"

curl https://api.kimicode.top/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "uncensored",
    "messages": [{"role": "user", "content": "Reply with the word ready."}]
  }'

The first call confirms the key and lists model IDs. The second checks the chat shape. Then test the parts your application depends on: add "stream": true and watch for incremental chunks, pass a tools array if you use function calling, and set response_format to {"type":"json_object"} if you need parseable output.

Also trigger an error on purpose, such as a bad key. You want to see a clean HTTP status and a JSON error body your client can handle.

The same call in Node

The JavaScript SDK takes the same two values. Here is a streaming call, which is the shape most chat interfaces use.

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.kimicode.top/v1",
  apiKey: process.env.API_KEY,
});

const stream = await client.chat.completions.create({
  model: "uncensored",
  stream: true,
  messages: [{ role: "user", content: "Name three uses of SSE." }],
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}

If this prints text word by word, the streaming path works end to end. The same loop works against any compatible provider, which is the entire point of the format.

What switching looks like in code

With the official Python SDK, the change is two constructor arguments. The rest of your program stays as it was.

from openai import OpenAI

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

resp = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Summarize SSE in one sentence."}],
)
print(resp.choices[0].message.content)

The Node SDK is the same idea with baseURL and apiKey options. Many tools read OPENAI_BASE_URL and OPENAI_API_KEY from the environment, so you can sometimes switch without touching code at all.

Remember to change the model string too. A request that names a model the new server does not host will fail, and that is the most common first error.

Where this site's API fits

This service is a hosted, text-only API that follows the OpenAI format. It runs one open-weight model, operated by an independent provider and tuned to answer without content refusals for lawful adult use. It is not the official API of any model vendor and it does not route between vendors. The model ID is uncensored.

It supports streaming over SSE with usage reported at the end, tool calling, JSON mode, and passes through temperature, top_p, stop, seed and the penalties. The context window is 100,000 tokens for prompt and completion together. It does not generate images or audio, and it does not offer embeddings or fine-tuning. One rule is fixed: no sexual content involving minors.

Billing is prepaid and metered: $0.15 per 1M input tokens and $0.50 per 1M output tokens, with no subscription. You can see the numbers on the pricing page, and the docs walk through a first request. If you want to try it without paying, new accounts can claim a $0.50 trial credit with one click on the API key page.

Common compatibility pitfalls

  1. Wrong base URL. The URL should end at /v1. Clients append /chat/completions themselves, so adding it to the base produces a 404.
  2. Unsupported parameters. If a library sends a field the server does not know, check whether it is rejected or silently dropped, then remove it.
  3. Streaming and concurrency. A streamed request holds a concurrency slot until the stream ends. If your app opens many streams, you can hit a 429 with code concurrency even though your per-minute count is low.
  4. Retry on 429. Treat 429 as a signal to wait. When a Retry-After header is present, honor it.
  5. Token counting. Do not assume another provider's tokenizer matches. Read the usage object in the response for the numbers you are billed on.

None of these are hard to fix once you know to look for them, and most come down to reading the first error message carefully.

Questions and answers

Is an OpenAI compatible API made by OpenAI?

No. The term describes the request and response format. Many independent providers follow it, and each runs its own models.

Can I use the OpenAI Python or Node SDK with it?

Yes. Set the base URL and API key in the client constructor, and use the model ID the provider gives you. For this service that is uncensored.

Will every OpenAI feature work on a compatible API?

Not necessarily. Providers choose which features to implement. Here you get chat completions, streaming, tool calling and JSON mode, but no images, audio or embeddings.

Does compatibility mean the same answers as another model?

No. Answers depend on the model and the provider's rules. Test with your own prompts instead of assuming similar behavior.

Your key is one form away

Create an account, copy the key, change the base URL. That is the whole setup.

Get API key