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

FieldTypeNotes
modelstringRequired. A model with modality tts. See Models.
inputstringRequired. The text to speak. Up to 4,096 characters.
voicestringVoice name, model-specific.
response_formatstringmp3 (default), opus, flac, wav, pcm.
speednumber0.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.mp3
from 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.