Reference

Changelog

Every change to the public API that could affect your code. Model ids, prices, response fields and error shapes, newest first.

Breaking changes are marked. Everything else is additive.

6 August 2026

All of this came from one customer integrating against us and writing down what they found. If you hit something similar, tell us.

Fixed — max_completion_tokens is honoured. OpenAI’s newer spelling for max_tokens was not recognised, and unrecognised fields were silently dropped, so a request that capped output at 5 tokens produced a full-length reply and a full-length bill. Send either spelling. Sending both with different values is now a 400, because two contradictory caps have no correct silent winner.

Breaking — an unknown parameter is now a 400 instead of being ignored. This is what the docs promised and the code did not do. If you are sending a field we do not implement, you will now see unsupported_parameter naming it rather than a 200 that quietly did something else.

user, store, metadata, service_tier, safety_identifier and n: 1 are the exception: accepted and ignored, because none of them can change your output or your bill. logit_bias and n > 1 are refused, because they would. See Not supported yet.

Additive — input_modalities on GET /v1/models. ["text"] or ["text", "image"]. Vision models publish modality: "text", because modality says which endpoint serves the model and a vision model is still a chat model billed per token, so filtering on it for image support found nothing. Filter on input_modalities instead.

Fixed — sending an image to a model that cannot read one is now a 400. It was forwarded to the model and billed, and came back as a confused text answer. Seven models accept images; see Images.

Fixed — tool_calls is omitted on ordinary replies rather than sent as an empty array. Our supplier returns [] on non-tool responses and we were passing it through. OpenAI omits the key entirely, and strict typed deserializers treat absent and empty as different things.

Fixed — published speed figures no longer include a cold start. The nightly benchmark took two samples and reported the median, and the median of two values is their mean, so one cold load was averaged into the published number. One model advertised 8787ms to first token against 89 to 362ms for the rest of the catalogue. The first of the two nightly probes is now discarded as a warm-up, which is where a cold load lands.

3 August 2026

Additive — a streamed response now reports what it cost. The include_usage frame carries a dawnstack block alongside usage, matching the non-streaming response:

"dawnstack": { "cost_micros": 1, "cost_usd": 0.000001, "request_id": "req_8f2a1c" }

Until now only the non-streaming response reported a cost, so a streaming client had no way to learn what a call cost without recomputing it from GET /v1/models. The figure is priced from the token counts in the same frame by the same function that settles the charge, so it is what you are billed, not an approximation of it. It rides on the usage frame, so you still have to send stream_options: {"include_usage": true} to see it. See Streaming.

31 July 2026

Speech, on OpenAI’s own paths. POST /v1/audio/transcriptions and POST /v1/audio/speech are live. An existing OpenAI audio client needs a new base URL and nothing else.

Two models: whisper-large-v3-turbo (MIT) for transcription, kokoro-82m (Apache-2.0) for synthesis. See Transcriptions and Speech.

Additive — pricing.unit now returns second and character, not only token. Transcription bills per second of audio submitted, rounded up; synthesis bills per character of input. If you parse GET /v1/models, do not assume unit is token — it always carried the unit, and now it carries three of them.

Additive — modality on GET /v1/models. text, stt or tts, so you can pick the right endpoint before calling one.

Additive — context_window is now null for speech models rather than 0. Audio models have no context window; their limits are file size and duration. Text models are unaffected.

30 July 2026

Breaking — dawnstack.credits is now dawnstack.cost_micros and dawnstack.cost_usd. Credits were US dollars multiplied by 100,000 and nothing else, so the unit carried no information the dollar figure did not. The additive block now reads:

"dawnstack": { "cost_micros": 2, "cost_usd": 0.000002, "request_id": "req_8f2a1c" }

One micro-dollar is $0.000001. An existing balance was migrated exactly; nothing changed in value. See Pricing and billing.

Breaking — errors on /v1 now use OpenAI’s envelope. They previously returned {"ok": false, "error": {"code", "message"}}, which has no type and puts message one level from where the SDKs read it, so e.message was empty on every failure. Now:

{ "error": { "message": "…", "type": "insufficient_quota", "param": null, "code": "INSUFFICIENT_BALANCE" } }

If you wrote a workaround for empty error messages, you can delete it. See Errors.

Fixed — tool calls now stream. delta.tool_calls was dropped by the frame rewriter, so a streamed tool call arrived as an empty stream ending in finish_reason: "stop". If you concluded tool calling did not work with stream: true, it does now. finish_reason is also no longer flattened to "stop", so length and tool_calls come through.

Added — stream_options: { include_usage: true }. It was silently stripped before, so a stream never carried token counts. See Streaming.

Added — GET /v1/models/{id}, OpenAI’s retrieve-model endpoint. client.models.retrieve() used to 404.

Added — response headers. Retry-After and X-RateLimit-Reset on 429, WWW-Authenticate on 401, and the leading delta: {"role": "assistant"} frame on every stream.

Changed — x-request-id is the header name everywhere. The playground used x-dawnstack-request-id.

Changed — session-authenticated requests to /v1/chat/completions are now rate limited at 20 a minute per account. They were unlimited. Key-authenticated requests are unaffected at 60 a minute.

Changed — the docs. This reference replaced a single page. Old #anchor links still land on the reference, though not on the exact section.

30 July 2026, earlier

Changed — prices fell 53% to 86% on output across the catalogue, at unchanged margin, when supply moved to a different provider. The catalogue grew from 9 models to 45.

Changed — GET /v1/models is now public. It required an API key, so nobody could read the catalogue or the prices before signing up and no third-party tool could discover us. It also now publishes supported_parameters, quantization, the maker, and measured speed.

Fixed — tools and response_format were being silently dropped. The request schema listed five fields and everything else was stripped, so a caller who sent tools got a 200 with prose and no explanation. The full OpenAI parameter set is forwarded now, and tool_calls is returned in the response. If you tried tool calling before this date and it appeared to do nothing, that is why.

26 July 2026

POST /v1/chat/completions went live.