Core
Transcriptions
Turn speech into text on OpenAI's own audio path. Billed per second of audio you send, rounded up, with the price published the same way every other model's is.
POST /v1/audio/transcriptions
The same path OpenAI uses, so an existing client needs a new base URL and nothing else. Send a file
as multipart/form-data, get text back.
Parameters
| Field | Type | Notes |
|---|---|---|
file | file | Required. The audio. Up to 20 MB. |
model | string | Required. A model with modality stt. See Models. |
language | string | ISO-639-1 code. Supplying it improves accuracy and costs nothing. |
prompt | string | Context to bias the transcription, such as proper nouns or place names. |
response_format | string | json (default), verbose_json, or text. |
Pricing
Billed per second of audio submitted, rounded up to the whole second. You pay for the audio you sent, not for what was left after silence was trimmed, so the cost is predictable from the file itself.
A three-minute voice note costs about $0.0009. The $1.00 minimum top-up covers roughly a thousand of them.
The price is on pricing.usd_per_million_input from GET /v1/models, alongside
pricing.unit: "second" — the same two fields text models publish, reading in a different unit.
Example
curl https://api.dawnstackai.com/v1/audio/transcriptions \
-H "Authorization: Bearer $DAWNSTACK_API_KEY" \
-F file=@voice-note.m4a \
-F model=whisper-large-v3-turbo \
-F language=swfrom openai import OpenAI
client = OpenAI(
api_key="sk-dawn-...",
base_url="https://api.dawnstackai.com/v1",
)
with open("voice-note.m4a", "rb") as f:
result = client.audio.transcriptions.create(
model="whisper-large-v3-turbo",
file=f,
language="sw",
)
print(result.text)The response
{
"text": "Habari yako rafiki.",
"dawnstack": {
"cost_micros": 25,
"billed_seconds": 5,
"request_id": "req_01J..."
}
}
billed_seconds is the number you were actually charged for, so the bill can be checked against the
file without a second call. The dawnstack block is additive — an OpenAI client ignores it.
With response_format: "verbose_json" you also get language, duration (the billed seconds), and
segments with per-segment start and end times. With response_format: "text" the body is the bare
transcript, text/plain, exactly as OpenAI returns it.
Limits
20 MB per file. A Worker has a fixed memory budget and the whole file passes through it. Longer audio needs an asynchronous path, which is not built yet — for now, split the file.
srt and vtt are not supported. Asking for either returns a 400 naming the parameter rather
than quietly giving you json. The segment timings needed to build them are in verbose_json
today, so you can generate subtitles yourself in the meantime.
Which languages actually work
Whisper is MIT licensed and is the strongest speech model we can serve without a licence problem. Its quality on African languages is not something we have measured yet, and we will not claim it until we have. Publishing that measurement — including if the answer is bad — is on the roadmap.
Passing language explicitly helps. Automatic detection is least reliable for exactly the languages
that are least represented in training data.