Introduction
Send an audio URL and, optionally, the spoken language, a list of key terms and three switches: written-form numbers, filler words and per-channel transcription. The task returns the transcript as text plus a structured transcript with word-level timings, the detected language and the audio length; no file is produced. SpicyAPI applies no content filter: unfiltered speech is transcribed as spoken. You are billed per second of audio.
| Field | Value |
|---|---|
| Input | Audio |
| Output | Text |
| Required field |
|
| Optional fields | language (25 codes), |
| Result | Transcript as text, plus output.transcript with word timings, language and duration; per channel with multichannel |
| Billed quantity | Seconds of audio; uploads are held at their length, URLs at the two-hour maximum |
| Typical time | About 3 seconds for a 10-second clip, about 15 seconds for an hour |
| Retention | Uploaded audio is deleted after one day; the transcript is erased with prompt data |
Request parameters
| Parameter | Required | Description |
|---|---|---|
audio_url | Yes | The audio to transcribe: an uploaded MP3 or WAV, or a public URL to MP3, WAV, M4A, FLAC, OGG, Opus, AAC, MP4 or MKV. 1 second to 2 hours. at least 1 characters |
language | No | The spoken language as a language code. Leave it empty to detect the language automatically; speech in any supported language is transcribed either way. |
text_normalization | No | When on, spoken numbers, prices, dates and units are written in digits — "$1,250" and "March 14" instead of the words. Needs language. Default: |
keyterms | No | Up to 100 words or short phrases (50 characters each) to bias the transcript toward — names, brands, jargon. Does not change the price. Default: |
filler_words | No | When on, filler words such as um and uh are kept in the transcript; off (default) removes them. Does not change the price. Default: |
multichannel | No | When on, each channel of a multichannel file (up to 8) is transcribed independently and returned on its own line, in channel order. Default: |
Pricing
$0.00003 / second of audio
Billed per second of audio. When the task is created, the hold matches the length of audio you uploaded, or the price of the two-hour maximum for an audio URL; you pay for the actual length and the rest of the hold is freed. A failed request is not charged.
Use cases
Voice notes and audio stories
Unfiltered speech is transcribed as spoken, so voice messages, roleplay recordings and audio stories can be searched, captioned or edited as text.
Call recordings
Recordings with each side on its own channel come back as one line per side when multichannel is on. With it off, our tests returned only one of the two sides, so turn it on for split-channel calls.
Checking generated speech
Run a text-to-speech result back through it and compare the transcript with the script: skipped words, a truncated ending or a tag read out loud show up at once.
Names, brands and numbers
List unusual names as key terms and turn on text normalization, and the transcript spells the names your way and writes prices and dates as $1,250 or March 14.
Prompt guide & pro tips
Point
audio_urlat the audioUpload an MP3 or WAV, or pass a public URL that answers with the audio itself — a player page or share link that returns HTML fails. From 1 second to 2 hours.
Add what you know
Set language if you know it, list names and brand words in keyterms, and turn on
text_normalizationif you want numbers written as digits.text_normalizationneeds language.Read the text from the task
The transcript arrives as text on the task result, and output.transcript lists every word with its start and end time. With multichannel on there is one line per channel, in channel order. Copy it into your own storage if you need it later.
What it returns
The transcript as text on the task result, plus output.transcript: the detected language and language code, the audio length in seconds, and every word with its start and end time in seconds. With multichannel on, output.transcript.channels holds the same for each channel. No file is produced and nothing enters media storage. Speaker labels are not included.
Sending audio
audio_url takes an uploaded MP3 or WAV, or a public URL to MP3, WAV, M4A, FLAC, OGG, Opus, AAC, MP4 or MKV, from 1 second to 2 hours. The URL has to answer with the audio itself. Raw audio without a file header (PCM, μ-law, A-law) is not accepted.
Language and numbers
Leave language empty and the language is detected; speech in any of the 25 supported languages is transcribed either way. Set it and turn on text_normalization to get numbers, prices, dates and units in written form — in our test "one thousand two hundred fifty dollars on March fourteenth" became "$1,250 on March 14". text_normalization needs language.
Key terms and filler words
keyterms takes up to 100 terms of up to 50 characters, one per row. In our test "Xandrelle" and "Qorvessa" came back as "Xandrel" and "Corvessa" without them and exactly right with them. filler_words keeps um and uh, which are removed by default.
Several channels
Turn on multichannel for recordings with each speaker on their own channel. Each channel is transcribed separately and returned on its own line, in channel order. Leave it off only when every channel carries the same sound: in our tests a stereo file with a different speaker on each side came back with one of the two speakers missing.
Billing
Billed per second of audio. When the task is created, the hold matches the length of audio you uploaded, or the price of the two-hour maximum for an audio URL; you pay for the actual length and the rest of the hold is freed. None of the options changes the price. Failed requests are not charged.
Content
SpicyAPI adds no content filter. In our tests unfiltered speech came back word for word, with no asterisks, bleeps or gaps.
SpicyAPI adds no content filter: speech is transcribed as spoken rather than masked or refused. You are responsible for the rights to the audio you send and for the consent of the people recorded.
API quick start
# Generate the idempotency key once; reuse it when retrying after a lost response.
export SPICY_IDEMPOTENCY_KEY="${SPICY_IDEMPOTENCY_KEY:-$(uuidgen)}"
curl -X POST https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
-d '{
"model": "xai/grok-stt/speech-to-text",
"input": {
"audio_url": "https://example.com/reference.mp3"
}
}'
# Copy data.taskId from the response into TASK_ID, then poll the status.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.spicyapi.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
-H "Authorization: Bearer $SPICY_API_KEY"
See the API reference for authentication, the complete schema, polling, and error handling.





