Core
Speech
Turn text into audio on OpenAI's own path. Billed per input character, so the price is known before you send it. Repeated phrases cost a quarter.
POST /v1/audio/speech
JSON in, audio out. The same path and the same field names OpenAI uses.
Parameters
| Field | Type | Notes |
|---|---|---|
model | string | Required. A model with modality tts. See Models. |
input | string | Required. The text to speak. Up to 4,096 characters. |
voice | string | Voice name, model-specific. |
response_format | string | mp3 (default), opus, flac, wav, pcm. |
speed | number | 0.25 to 4. Defaults to 1. |
Pricing
Billed per character of input, which means the price is fully determined before you send the
request — no estimate, no reservation, no refund. Multiply the length of your text by
pricing.usd_per_million_input from GET /v1/models, where pricing.unit reads character.
Repeated phrases cost a quarter
The same text, in the same voice, at the same speed and format always produces the same audio. So we keep it, and serving it back costs you 25% of the generation price.
This is aimed squarely at the case it came from: a shop bot that says “your order is confirmed” a thousand times a day should pay to generate it once.
Every response carries the outcome, so the discount is checkable rather than asserted:
x-dawnstack-cached: hit # served from cache, billed at 25%
x-dawnstack-cached: miss # generated, billed in full
x-dawnstack-cost-micros: 6 # what this request cost
The cache is keyed on the text, voice, model, format and speed together — change any one of them and you get a fresh generation, because any one of them changes the audio.
It is shared across all accounts. That is what makes it worth having, and it is safe because synthesis is a pure function of inputs you supplied yourself: a hit returns audio you could have generated, and reveals only that the same sentence had been requested before.
Example
curl https://api.dawnstackai.com/v1/audio/speech \
-H "Authorization: Bearer $DAWNSTACK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "kokoro-82m",
"input": "Your order is confirmed.",
"response_format": "mp3"
}' \
--output confirmed.mp3from openai import OpenAI
client = OpenAI(
api_key="sk-dawn-...",
base_url="https://api.dawnstackai.com/v1",
)
response = client.audio.speech.create(
model="kokoro-82m",
input="Your order is confirmed.",
response_format="mp3",
)
response.write_to_file("confirmed.mp3")The response
The raw audio bytes, with the content type matching response_format — not JSON containing a URL,
and not a link you have to fetch separately. Write the body to a file and play it.
Limits
4,096 characters per request. This is also the ceiling on what a single call can cost.
One model today. Kokoro-82M, Apache-2.0 licensed. Open-weight text-to-speech is thinner ground than transcription and African-language coverage is worse; we would rather ship one model we can serve honestly than a list padded with ones we cannot.
Streaming is not supported yet. The full audio is generated, then returned.