OpenAI Drop-In Replacement API: What Swaps and What Breaks
Blog

OpenAI Drop-In Replacement API: What Swaps and What Breaks

An OpenAI drop-in replacement means changing two lines: base_url and key. See which endpoints and parameters carry over, and which ones break.

Tessera 7 min read OpenAITesseraOpenAI-compatible APIdrop-in replacementLocalAI

OpenAI Drop-In Replacement API: What Swaps and What Breaks

An OpenAI drop-in replacement is an API that speaks OpenAI’s protocol, so you switch providers by changing two things: the base_url and the API key, with no new SDK and no rewritten request or response parsing. It works cleanly for chat, embeddings, audio, tools, and streaming, but not for the Assistants API, the Responses API, batch jobs, image generation, or vision inputs.

The word “drop-in” does a lot of quiet work in that sentence. It is true for the surface you actually call and false for the surface you do not, and most migration surprises come from that gap. This page maps the gap exactly: which endpoints and parameters carry over untouched, which ones break, and what to test before you send production traffic.

Tessera is an OpenAI-compatible gateway for open-source models with EU and LATAM data residency and flat monthly pricing, so the examples below use it as the concrete target. The compatibility rules are the same whichever compatible endpoint you point at.

The two-line swap

The OpenAI Python SDK exposes base_url as a constructor argument (OpenAI Python SDK). Point it at a compatible endpoint and update the key:

from openai import OpenAI

client = OpenAI(
    base_url="https://api.tesseraai.cloud/v1",
    api_key="sk-tessera-...",
)

resp = client.chat.completions.create(
    model="Qwen/Qwen3.6-35B-A3B",
    messages=[{"role": "user", "content": "Hello"}],
)

That is the whole migration for a chat workload. The same client also handles embeddings and audio against the same base URL, so a retrieval pipeline moves with no new SDK:

emb = client.embeddings.create(
    model="Qwen3-Embedding-8B",
    input=["first chunk", "second chunk"],
)

with open("call.wav", "rb") as f:
    text = client.audio.transcriptions.create(
        model="whisper-large-v3",
        file=f,
    )

The same pattern works in the Node SDK (baseURL), in LangChain (openai_api_base), and in any library that reads the OpenAI base URL from an environment variable. For a full, phased migration plan see the migrate-from-OpenAI guide; for a pricing-and-provider comparison see the OpenAI API alternatives guide.

Compatibility matrix: what carries over

The table reflects Tessera’s documented surface. Other compatible providers differ, so confirm each one against its own docs.

OpenAI featureEndpointDrop-in?
Chat completions/v1/chat/completionsYes, with SSE streaming, tools, JSON mode, response_format=json_schema
Embeddings/v1/embeddingsYes, string or array input
Audio transcription/v1/audio/transcriptionsYes, multipart upload, json/text/verbose_json
Text to speech/v1/audio/speechYes, mp3/wav/opus output
Function and tool calling/v1/chat/completionsYes: auto, none, required, parallel calls
StreamingSSEYes, identical data: {...} frames ending in data: [DONE]
Structured outputsjson_schemaYes, strict validation
Reranking/v1/rerankTessera extension (Cohere-compatible), not an OpenAI endpoint
Responses API/v1/responsesNo
Assistants, Threads, Runs/v1/assistantsNo
Batch API/v1/batchNo
Fine-tuning/v1/fine-tuningNo
Vision and image inputn/aNo
Image generationDALL-E, SoraNo
Realtime voiceWebSocketNo
Moderations/v1/moderationsStub only (always returns not flagged)

If your code touches only the “Yes” rows, the swap is genuinely two lines. If it depends on a “No” row, that part needs a redesign, not a redirect. The most common blockers in practice are apps built on the Assistants API (stateful threads and tool orchestration handled server-side) and anything that calls image generation. Both assume features that live in OpenAI’s product, not in the wire format that compatible providers implement.

Parameters that behave differently

Even on supported endpoints, a few parameters carry subtle differences worth a test:

  • max_tokens counts output tokens only. Input context does not eat into the budget, which can change truncation behavior.
  • seed is accepted but does not guarantee identical output across model versions.
  • n is accepted but always returns a single completion, so code that reads choices[1] and beyond needs a fallback.
  • logprobs, top_logprobs, and logit_bias are not supported, which matters if you rank tokens or steer sampling with bias terms.
  • Model names map through. Most OpenAI model strings resolve to Qwen/Qwen3.6-35B-A3B, so passing an old model name still returns a response, just from an open-source model.

None of these throws on a healthy request. That is exactly why they are easy to miss: the call succeeds, the shape is right, and only a behavioral test catches the difference.

Self-hosted versus managed drop-ins

OpenAI-compatible endpoints come in two shapes, and the trade-off is operational, not protocol-level.

Self-hosted runtimes give you the same /v1 surface on your own hardware. LocalAI and Ollama both expose OpenAI-compatible routes, and vLLM serves one in front of open-weight models pulled from Hugging Face. You own the GPUs, the model downloads, the scaling, and the uptime. That is the right call when data can never leave your network or you already run an inference team.

Managed gateways give you the same surface without the operations. Tessera runs open-source models on datacenter GPUs with high-bandwidth memory, behind one OpenAI-compatible endpoint, so there is no Docker image to maintain and no capacity to plan. The cost is less low-level control; the benefit is that the swap really is two lines and stays that way. Most teams reaching for a drop-in want the second shape, because the whole point of compatibility is to stop managing infrastructure.

How to test before you cut over

A base_url change is fast, which makes it tempting to ship without checking. Run this short list against a staging key first:

  1. Enumerate the endpoints you call. Grep the codebase for every OpenAI method in use and check each against the matrix above. One Assistants call is enough to block the migration.
  2. Replay real traffic. Send a sample of production prompts to the new endpoint and diff the responses. The format will match; the content will not, because the model is different.
  3. Re-run your evals. Score the new model on your own task, not a public leaderboard. This is the step that decides whether the swap is viable.
  4. Check streaming and tools end to end. Confirm your client handles the data: [DONE] terminator and that tool-call arguments parse as expected.
  5. Load-test at your real concurrency. Throughput on open-source models differs from OpenAI’s; size it before launch.

This list is deliberately shorter than a full migration runbook. For the end-to-end process, including rollout and rollback, the migrate-from-OpenAI guide covers each phase.

The part teams forget: the model is not GPT

A drop-in API matches OpenAI’s wire format, not its weights. Tessera serves open-source models only: Qwen3.6-35B-A3B for chat, Qwen3-Embedding-8B for embeddings, Qwen3-Reranker-4B for rerank, Whisper large-v3 for transcription, and Kokoro 82M for speech. No GPT or Claude models run behind the endpoint.

That means the protocol is identical but the outputs are not. Prompts tuned tightly to one model version may need light re-tuning, and you should re-run your evals on the new model before cutover. This is the single most important thing to test, and it is the one a base_url change cannot do for you. Token throughput on open-source models is its own topic; the Qwen 3.6 benchmarks cover it.

Why teams swap in the first place

The wire-format compatibility is the means, not the motive. The usual reasons to point your SDK somewhere else:

  • Cost predictability. Token metering makes bills move with usage. Flat monthly pricing does not. See why metered bills swing in OpenAI bill variance and the flat-rate model in private AI pricing.
  • Data residency. If personal data cannot leave the EU or LATAM, the endpoint has to sit in-region. Tessera hosts in the EU and LATAM; where to host LLM inference with EU data residency goes deeper.
  • Open-source models. No proprietary lock-in to a single vendor’s roadmap or deprecation schedule.

None of these requires a rewrite. That is the quiet value of a compatible API: it turns a strategic decision about cost, residency, or model choice into a configuration change.

FAQ

Do I need to rewrite my code to use a drop-in replacement?

No. For supported endpoints you change the base_url and API key. Request and response shapes stay identical, so the OpenAI SDK, LangChain, and similar libraries keep working without code changes.

Is Tessera a true drop-in replacement for OpenAI?

For the endpoints it supports (chat completions, embeddings, audio transcription, speech, tools, streaming, structured outputs) yes. It does not implement the Assistants API, Responses API, Batch API, fine-tuning, vision, or image generation, so workloads using those are not drop-in.

Will my prompts produce the same answers?

No. A drop-in API copies OpenAI’s format, not its models. Tessera runs open-source models such as Qwen3.6-35B-A3B, so outputs differ. Re-run your evaluations on the target model before switching production traffic.

Can I keep using LangChain or the official OpenAI SDK?

Yes. Both read the base URL from configuration, so they point at a compatible endpoint without code changes. Set openai_api_base in LangChain or base_url in the OpenAI client.

What is the base URL for the swap?

https://api.tesseraai.cloud/v1, used as the base_url in the OpenAI client. See the migrating from OpenAI docs for endpoint-level detail.