Guides

Migrating from OpenAI

Two lines of configuration and a model id. What carries over unchanged, what differs, and the three things worth checking before you switch traffic.

The base URL and the key. Keep the openai SDK, keep your request and response handling, keep your streaming loop and your tool-calling round trip.

from openai import OpenAI

client = OpenAI(
    api_key=os.environ["DAWNSTACK_API_KEY"],
    base_url="https://api.dawnstackai.com/v1",
)
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.DAWNSTACK_API_KEY,
  baseURL: "https://api.dawnstackai.com/v1",
});
# Most tools read these, so often no code change at all.
export OPENAI_API_KEY="$DAWNSTACK_API_KEY"
export OPENAI_BASE_URL="https://api.dawnstackai.com/v1"

What carries over unchanged

Chat completions, streaming, tool calling and the round trip, structured output, the sampling parameters, logprobs, the usage object, finish_reason, Idempotency-Key, and the error shape.

What you have to change

The model id. There is no gpt-4o here. Pick from Models, or use an alias and let the choice move as better models appear.

If you were usingA reasonable starting point
A small fast model for classification or extractionllama-3.1-8b
A general-purpose mid-size modelllama-3.3-70b, gpt-oss-120b
A reasoning modelSee the models marked as reasoning on Models
Anything where the prompt is not Englishdawn-multilingual, or read the per-language cost on the models page

These are starting points, not equivalences. Run your own evaluation.

Three things to check before you switch traffic

  1. Capabilities are per model and measured. Check Can do on Models before assuming tools or response_format will work. Sending one to a model that does not declare it is a 400 rather than a quiet fallback to prose.
  2. Reasoning tokens are billed and can dominate a short reply. If you are moving a high-volume, short-answer workload, compare per request rather than per token.
  3. Language cost is not flat. Swahili and Amharic tokenize less efficiently than English, so the same sentence costs more. We publish the multiplier per model rather than hiding it in an average.

What is missing

Embeddings, images, moderations, the Responses API, assistants and batches. n > 1 is not supported. Audio is present: /v1/audio/transcriptions and /v1/audio/speech both work on the paths your client already calls. The full list is on Not supported yet. If your app uses embeddings alongside chat, keep that half where it is; nothing stops you pointing two clients at two providers.

Errors

402 means an empty balance rather than a billing problem with a card on file, and it carries type: "insufficient_quota" so an SDK’s own handling still fires. There is no organisation-level quota and no per-model rate limit: the limit is 60 requests a minute per key. See Errors and Rate limits.