Skip to main content

MiniMax Speech 2.8 Turbo text-to-speech, optimized for speed and cost, reads a script in one of 472 system voices with a chosen emotion. It returns a 32 kHz mono MP3 by default, with speed, pitch, volume and sound tags like (sighs).

From $0.072/1,000 characters

Workbench

Send a request

Quickstart

Examples use the selected endpoint’s public parameter definitions. Replace the API key and example media, then send the request from your server.

SDKs & integrations
POSThttps://api.spicyapi.ai/api/v1/jobs/createTask

API authentication

Keep the API key in the server environment variable SPICY_API_KEY. Use Bearer authentication and Content-Type: application/json for JSON requests.

Authorization: Bearer $SPICY_API_KEY
# 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": "minimax/speech-2.8-turbo/text-to-speech",
  "input": {
    "text": "Welcome back. Your files finished rendering a minute ago and are ready to download.",
    "emotion": "neutral",
    "language": "auto",
    "voice_id": "Calm_Woman",
    "output_format": "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"

Generated from this model’s input schema — the same one the API validates every request against.

Input parameters

Place these fields inside the request body’s input object. Names and types match the API. Do not assume a default when none is specified.

textstringRequired

The words to be spoken, exactly as written. Sound tags in parentheses such as (sighs) or (laughs) are performed as sounds, not read aloud. Billed per 1,000 characters, including spaces and punctuation. Up to 5,000 characters.

Default
Not specified
Constraints
minLength:1
maxLength:5000
pronunciation_dictarray<object>Optional

Up to 100 {alias, pronunciation} pairs. Every occurrence of alias in text is read as pronunciation: plain words (Omg → Oh my god) or IPA in parentheses such as (rɪˈzjuːm). alias cannot contain a slash. Does not change the price; only text is billed.

Default
Not specified
Constraints
maxItems:100
english_normalizationbooleanOptional

When on, numbers, dates and abbreviations in English text are read the way a person would say them, such as 1990 as “nineteen ninety”. Off by default. Does not change the price.

Default
false
audio_channelsstringOptional

Output channels: mono (default) or stereo. Does not change the price.

Default
Not specified
Allowed values
"mono""stereo"
bitrateintegerOptional

MP3 bitrate in bits per second: 32000, 64000, 128000 or 256000. Defaults to 128000 and only applies when output_format is mp3. Does not change the price.

Default
Not specified
Allowed values
3200064000128000256000
sample_rateintegerOptional

Sample rate of the audio in Hz: 8000, 16000, 22050, 24000, 32000, 44100. Defaults to 32000. Does not change the price.

Default
Not specified
Allowed values
80001600022050240003200044100
output_formatstringOptional

File format: mp3 (default), wav, flac, or pcm, which is raw 16-bit little-endian samples with no header at the chosen sample_rate and audio_channels. Browsers cannot play pcm; pick wav to get the same samples in a playable file. Does not change the price.

Default
"mp3"
Allowed values
"mp3""wav""flac""pcm"
languagestringOptional

A hint that improves pronunciation for one of 40 languages. Defaults to auto, which detects the language from the script.

Default
"auto"
Allowed values
"auto""zh""yue""en""ar""ru""es""fr""pt""de""tr""nl""uk""vi""id""ja""it""ko""th""pl""ro""el""cs""fi""hi""bg""da""he""ms""fa""sk""sv""hr""fil""hu""no""sl""ca""nn""ta""af"
volumenumberOptional

Loudness multiplier from 0.1 to 10; 1 is the normal level. Does not change the price.

Default
1
Constraints
minimum:0.1
maximum:10
pitchintegerOptional

Pitch shift in semitones, from -12 to 12; 0 keeps the voice's own pitch. Does not change the price.

Default
0
Constraints
minimum:-12
maximum:12
speednumberOptional

Speaking rate from 0.5 (slower) to 2 (faster); 1 is the voice's normal pace. Does not change the price.

Default
1
Constraints
minimum:0.5
maximum:2
emotionstringOptional

One of seven fixed emotions — neutral, happy, sad, angry, fearful, disgusted or surprised — applied to the whole reading. Defaults to neutral.

Default
"neutral"
Allowed values
"neutral""happy""sad""angry""fearful""disgusted""surprised"
voice_idstringOptional

One of 472 system voices. Defaults to Calm_Woman. There is no cloning and no upload of a reference voice.

Default
"Calm_Woman"
Allowed values
"Wise_Woman""Friendly_Person""Inspirational_girl""Deep_Voice_Man""Calm_Woman""Casual_Guy""Lively_Girl""Patient_Man""Young_Knight""Determined_Man""Lovely_Girl""Decent_Boy""Imposing_Manner""Elegant_Man""Abbess""Sweet_Girl_2""Exuberant_Girl""English_expressive_narrator""English_radiant_girl""English_magnetic_voiced_man""English_compelling_lady1""English_Aussie_Bloke""English_captivating_female1""English_Upbeat_Woman""English_Trustworth_Man""English_CalmWoman""English_UpsetGirl""English_Gentle-voiced_man""English_Whispering_girl_v3""English_Diligent_Man""English_Graceful_Lady""English_Husky_MetalHead""English_ReservedYoungMan""English_PlayfulGirl""English_ManWithDeepVoice""English_GentleTeacher""English_MaturePartner""English_FriendlyPerson""English_MatureBoss""English_Debator""whisper_man""English_Abbess""English_LovelyGirl""whisper_woman_1""English_Steadymentor""English_Deep-VoicedGentleman""English_DeterminedMan""English_Wiselady""English_CaptivatingStoryteller""English_AttractiveGirl""English_DecentYoungMan""English_SentimentalLady""English_ImposingManner""English_SadTeen""English_ThoughtfulMan""English_PassionateWarrior""English_DecentBoy""English_WiseScholar""English_Soft-spokenGirl""English_SereneWoman""English_ConfidentWoman""English_PatientMan""English_Comedian""English_GorgeousLady""English_BossyLeader""English_LovelyLady""English_Strong-WilledBoy""English_Deep-tonedMan""English_StressedLady""English_AssertiveQueen""English_AnimeCharacter""English_Jovialman""English_WhimsicalGirl""English_CharmingQueen""English_Kind-heartedGirl""English_FriendlyNeighbor""English_Sweet_Female_4""English_Magnetic_Male_2""English_Lively_Male_11""English_Friendly_Female_3""English_Steady_Female_1""English_Lively_Male_10""English_Magnetic_Male_12""English_Steady_Female_5""English_Insightful_Speaker""English_patient_man_v1""English_Persuasive_Man""English_Explanatory_Man""English_intellect_female_1""English_energetic_male_1""English_witty_female_1""English_Lucky_Robot""English_Cute_Girl""English_Sharp_Commentator""English_Honest_Man""angry_pirate_1""massive_kind_troll""movie_trailer_deep""peace_and_ease""moss_audio_6dc281eb-713c-11f0-a447-9613c873494c""moss_audio_c12a59b9-7115-11f0-a447-9613c873494c""moss_audio_076697ad-7144-11f0-a447-9613c873494c""moss_audio_737a299c-734a-11f0-918f-4e0486034804""moss_audio_19dbb103-7350-11f0-ad20-f2bc95e89150""moss_audio_7c7e7ae2-7356-11f0-9540-7ef9b4b62566""moss_audio_570551b1-735c-11f0-b236-0adeeecad052""moss_audio_ad5baf92-735f-11f0-8263-fe5a2fe98ec8""moss_audio_cedfd4d2-736d-11f0-99be-fe40dd2a5fe8""moss_audio_a0d611da-737c-11f0-ad20-f2bc95e89150""moss_audio_4f4172f4-737b-11f0-9540-7ef9b4b62566""moss_audio_62ca20b0-7380-11f0-99be-fe40dd2a5fe8""conversational_female_1_v1""conversational_female_2_v1""socialmedia_female_1_v1""BritishChild_male_1_v1""BritishChild_female_1_v1""Chinese (Mandarin)_Reliable_Executive""Chinese (Mandarin)_News_Anchor""Chinese (Mandarin)_Unrestrained_Young_Man""Chinese (Mandarin)_Mature_Woman""Arrogant_Miss""Chinese (Mandarin)_Kind-hearted_Antie""Robot_Armor""hunyin_6""Chinese (Mandarin)_HK_Flight_Attendant""Chinese (Mandarin)_Humorous_Elder""Chinese (Mandarin)_Gentleman""Chinese (Mandarin)_Warm_Bestie""Chinese (Mandarin)_Stubborn_Friend""Chinese (Mandarin)_Sweet_Lady""Chinese (Mandarin)_Southern_Young_Man""Chinese (Mandarin)_Wise_Women""Chinese (Mandarin)_Gentle_Youth""Chinese (Mandarin)_Warm_Girl""Chinese (Mandarin)_Male_Announcer""Chinese (Mandarin)_Kind-hearted_Elder""Chinese (Mandarin)_Cute_Spirit""Chinese (Mandarin)_Radio_Host""Chinese (Mandarin)_Lyrical_Voice""Chinese (Mandarin)_Straightforward_Boy""Chinese (Mandarin)_Sincere_Adult""Chinese (Mandarin)_Gentle_Senior""Chinese (Mandarin)_Crisp_Girl""Chinese (Mandarin)_Pure-hearted_Boy""Chinese (Mandarin)_Soft_Girl""Chinese (Mandarin)_IntellectualGirl""Chinese (Mandarin)_Warm_HeartedGirl""Chinese (Mandarin)_Laid_BackGirl""Chinese (Mandarin)_ExplorativeGirl""Chinese (Mandarin)_Warm-HeartedAunt""Chinese (Mandarin)_BashfulGirl""Arabic_CalmWoman""Arabic_FriendlyGuy""Cantonese_ProfessionalHost(F)""Cantonese_GentleLady""Cantonese_ProfessionalHost(M)""Cantonese_PlayfulMan""Cantonese_CuteGirl""Cantonese_KindWoman""Cantonese_Narrator""Cantonese_WiselProfessor""Cantonese_IndifferentStaff""Dutch_kindhearted_girl""Dutch_bossy_leader""French_Male_Speech_New""French_Female_News Anchor""French_CasualMan""French_MovieLeadFemale""French_FemaleAnchor""French_MaleNarrator""French_Female Journalist""French_Female_Speech_New""German_FriendlyMan""German_SweetLady""German_PlayfulMan""Indonesian_SweetGirl""Indonesian_ReservedYoungMan""Indonesian_CharmingGirl""Indonesian_CalmWoman""Indonesian_ConfidentWoman""Indonesian_CaringMan""Indonesian_BossyLeader""Indonesian_DeterminedBoy""Indonesian_GentleGirl""Italian_BraveHeroine""Italian_Narrator""Italian_WanderingSorcerer""Italian_DiligentLeader""Italian_ReliableMan""Italian_AthleticStudent""Italian_ArrogantPrincess""Japanese_Whisper_Belle""Japanese_IntellectualSenior""Japanese_DecisivePrincess""Japanese_LoyalKnight""Japanese_DominantMan""Japanese_SeriousCommander""Japanese_ColdQueen""Japanese_DependableWoman""Japanese_GentleButler""Japanese_KindLady""Japanese_CalmLady""Japanese_OptimisticYouth""Japanese_GenerousIzakayaOwner""Japanese_SportyStudent""Japanese_InnocentBoy""Japanese_GracefulMaiden""Korean_PowerfulGirl""Korean_BossyMan""Korean_SweetGirl""Korean_CheerfulBoyfriend""Korean_EnchantingSister""Korean_ShyGirl""Korean_ReliableSister""Korean_StrictBoss""Korean_SassyGirl""Korean_ChildhoodFriendGirl""Korean_PlayboyCharmer""Korean_ElegantPrincess""Korean_BraveFemaleWarrior""Korean_BraveYouth""Korean_CalmLady""Korean_EnthusiasticTeen""Korean_SoothingLady""Korean_IntellectualSenior""Korean_LonelyWarrior""Korean_MatureLady""Korean_InnocentBoy""Korean_CharmingSister""Korean_AthleticStudent""Korean_BraveAdventurer""Korean_CalmGentleman""Korean_WiseElf""Korean_CheerfulCoolJunior""Korean_DecisiveQueen""Korean_ColdYoungMan""Korean_MysteriousGirl""Korean_QuirkyGirl""Korean_ConsiderateSenior""Korean_CheerfulLittleSister""Korean_DominantMan""Korean_AirheadedGirl""Korean_ReliableYouth""Korean_FriendlyBigSister""Korean_GentleBoss""Korean_ColdGirl""Korean_HaughtyLady""Korean_CharmingElderSister""Korean_IntellectualMan""Korean_CaringWoman""Korean_WiseTeacher""Korean_ConfidentBoss""Korean_AthleticGirl""Korean_PossessiveMan""Korean_GentleWoman""Korean_CockyGuy""Korean_ThoughtfulWoman""Korean_OptimisticYouth""Portuguese_AnxiousMan""Portuguese_Matureresearcher""Portuguese_Optimisticyouth""Portuguese_CuteElf""Portuguese_EnergeticGirl""Portuguese_FunnyGuy""Portuguese_Nuttylady""Portuguese_Deep-tonedMan""Portuguese_SentimentalLady""Portuguese_BossyLeader""Portuguese_Wiselady""Portuguese_Strong-WilledBoy""Portuguese_Deep-VoicedGentleman""Portuguese_UpsetGirl""Portuguese_PassionateWarrior""Portuguese_AnimeCharacter""Portuguese_ConfidentWoman""Portuguese_AngryMan""Portuguese_CaptivatingStoryteller""Portuguese_Godfather""Portuguese_ReservedYoungMan""Portuguese_SmartYoungGirl""Portuguese_Kind-heartedGirl""Portuguese_Pompouslady""Portuguese_Grinch""Portuguese_Debator""Portuguese_SweetGirl""Portuguese_AttractiveGirl""Portuguese_ThoughtfulMan""Portuguese_PlayfulGirl""Portuguese_GorgeousLady""Portuguese_LovelyLady""Portuguese_SereneWoman""Portuguese_SadTeen""Portuguese_MaturePartner""Portuguese_Comedian""Portuguese_NaughtySchoolgirl""Portuguese_Narrator""Portuguese_ToughBoss""Portuguese_Fussyhostess""Portuguese_Dramatist""Portuguese_Steadymentor""Portuguese_Jovialman""Portuguese_CharmingQueen""Portuguese_SantaClaus""Portuguese_Rudolph""Portuguese_Arnold""Portuguese_CharmingSanta""Portuguese_Ghost""Portuguese_HumorousElder""Portuguese_CalmLeader""Portuguese_GentleTeacher""Portuguese_EnergeticBoy""Portuguese_ReliableMan""Portuguese_SereneElder""Portuguese_GrimReaper""Portuguese_AssertiveQueen""Portuguese_WhimsicalGirl""Portuguese_StressedLady""Portuguese_FriendlyNeighbor""Portuguese_CaringGirlfriend""Portuguese_PowerfulSoldier""Portuguese_FascinatingBoy""Portuguese_RomanticHusband""Portuguese_StrictBoss""Portuguese_InspiringLady""Portuguese_PlayfulSpirit""Portuguese_ElegantGirl""Portuguese_CompellingGirl""Portuguese_PowerfulVeteran""Portuguese_SensibleManager""Portuguese_ThoughtfulLady""Portuguese_TheatricalActor""Portuguese_FragileBoy""Portuguese_ChattyGirl""Portuguese_Conscientiousinstructor""Portuguese_RationalMan""Portuguese_WiseScholar""Portuguese_FrankLady""Portuguese_DeterminedManager""Portuguese_CharmingLady""Russian_HandsomeChildhoodFriend""Russian_BrightHeroine""Russian_AmbitiousWoman""Russian_ReliableMan""Russian_CrazyQueen""Russian_PessimisticGirl""Russian_AttractiveGuy""Russian_Bad-temperedBoy""Spanish_FriendlyNeighbor""Spanish_FragileBoy""Spanish_UpsetGirl""Spanish_Soft-spokenGirl""Spanish_CharmingQueen""Spanish_Nuttylady""Spanish_ElegantGirl""Spanish_FascinatingBoy""Spanish_FunnyGuy""Spanish_PlayfulSpirit""Spanish_TheatricalActor""Spanish_SereneWoman""Spanish_MaturePartner""Spanish_CaptivatingStoryteller""Spanish_Narrator""Spanish_WiseScholar""Spanish_Kind-heartedGirl""Spanish_DeterminedManager""Spanish_BossyLeader""Spanish_ReservedYoungMan""Spanish_ConfidentWoman""Spanish_ThoughtfulMan""Spanish_Strong-WilledBoy""Spanish_SophisticatedLady""Spanish_RationalMan""Spanish_AnimeCharacter""Spanish_Deep-tonedMan""Spanish_Fussyhostess""Spanish_SincereTeen""Spanish_FrankLady""Spanish_Comedian""Spanish_Debator""Spanish_ToughBoss""Spanish_Wiselady""Spanish_Steadymentor""Spanish_Jovialman""Spanish_SantaClaus""Spanish_Rudolph""Spanish_Intonategirl""Spanish_Arnold""Spanish_Ghost""Spanish_HumorousElder""Spanish_EnergeticBoy""Spanish_WhimsicalGirl""Spanish_StrictBoss""Spanish_ReliableMan""Spanish_SereneElder""Spanish_AngryMan""Spanish_AssertiveQueen""Spanish_CaringGirlfriend""Spanish_PowerfulSoldier""Spanish_PassionateWarrior""Spanish_ChattyGirl""Spanish_RomanticHusband""Spanish_CompellingGirl""Spanish_PowerfulVeteran""Spanish_SensibleManager""Spanish_ThoughtfulLady""Turkish_CalmWoman""Turkish_Trustworthyman""Ukrainian_CalmWoman""Ukrainian_WiseScholar""Vietnamese_Serene_Man""Vietnamese_female_4_v1""Vietnamese_male_1_v2""Vietnamese_kindhearted_girl""Thai_Optimistic_girl""Thai_male_1_sample8""Thai_Tender_Woman""Thai_male_2_sample2""Thai_female_1_sample1""Thai_female_2_sample2""Polish_male_1_sample4""Polish_male_2_sample3""Polish_female_1_sample1""Polish_female_2_sample3""Romanian_male_1_sample2""Romanian_male_2_sample1""Romanian_female_1_sample4""Romanian_female_2_sample1""Greek_female_1_sample1""greek_male_1a_v1""Greek_female_2_sample3""czech_male_1_v1""czech_female_5_v7""czech_female_2_v2""finnish_male_3_v1""finnish_female_4_v1""finnish_male_1_v2""hindi_male_1_v2""hindi_female_2_v1""hindi_female_1_v2""Bulgarian_male_2_v1""Bulgarian_female_1_v1""Danish_male_1_v1""Danish_female_1_v1""Hebrew_male_1_v1""Hebrew_female_1_v1""Malay_male_1_v1""Malay_female_1_v1""Malay_female_2_v1""Persian_male_1_v1""Persian_female_1_v1""Slovak_male_1_v1""Slovak_female_1_v1""Swedish_male_1_v1""Swedish_female_1_v1""Croatian_male_1_v1""Croatian_female_1_v1""Filipino_male_1_v1""Filipino_female_1_v1""Hungarian_male_1_v1""Hungarian_female_1_v1""Norwegian_male_1_v1""Norwegian_female_1_v1""Slovenian_male_1_v1""Slovenian_female_1_v2""Catalan_male_1_v1""Catalan_female_1_v1""Nynorsk_male_1_v1""Nynorsk_female_1_v1""Tamil_male_1_v1""Tamil_female_1_v1""Afrikaans_male_1_v1""Afrikaans_female_1_v1"

Track the task

HTTP 202 means the task was accepted, not completed. Save the returned taskId and query that task. Do not create another task while waiting for its result.

Accepted response
HTTP/1.1 202 Accepted
Location: /api/v1/jobs/recordInfo?taskId=job_01k3m8x9q2z4v7n5p6r8s0t1w3

{
  "code": 200,
  "msg": "success",
  "request_id": "req_example_create",
  "data": {
    "taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "state": "queued",
    "estimatedCost": "0.750000"
  }
}

The accepted response includes the estimate so your app can show the same amount in task history and billing.

Read the job
curl --get "https://api.spicyapi.ai/api/v1/jobs/recordInfo" \
  --data-urlencode "taskId=$TASK_ID" \
  -H "Authorization: Bearer $SPICY_API_KEY"

Start polling at about 2 seconds and gradually increase the interval. Stop at a terminal state. After a connection failure, query the original taskId. Retry creation only with the original idempotency key and body.

Or let the callback find you
import { verifyWebhook } from "@spicyapi/sdk";

// express.raw keeps the bytes we signed; express.json never matches.
app.post("/hooks/spicy", express.raw({ type: "application/json" }), (req, res) => {
  const { payload } = verifyWebhook({
    rawBody: req.body,
    timestamp: req.header("X-Webhook-Timestamp"),
    signature: req.header("X-Webhook-Signature"),
    payloadVersion: Number(req.header("X-Webhook-Payload-Version")),
    secret: process.env.SPICY_WEBHOOK_SECRET,
  });
  res.status(200).end();
  void handleFinishedTask(payload);
});

Pass callBackUrl when you create the task and the finished record is POSTed to you — no polling loop at all. Every delivery carries X-Webhook-Timestamp, X-Webhook-Signature and X-Webhook-Payload-Version. The signature is a base64 HMAC-SHA256 over taskId.timestamp.sha256(body), so it must be checked against the raw bytes: parsing the JSON and re-serialising it changes them and the check will fail. Failed deliveries are retried, so the same taskId can arrive twice — make the handler idempotent. Answer 2xx first and do the work afterwards; a slow handler is treated as a failed delivery.

Read the result

Consume output only when state is succeeded. On failure, use errorCode, errorMessage and request_id to investigate. Example costs and states do not represent an actual bill.

Completed response example
{
  "code": 200,
  "msg": "success",
  "request_id": "req_example_record",
  "data": {
    "taskId": "job_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "model": "minimax/speech-2.8-turbo/text-to-speech",
    "state": "succeeded",
    "output": {
      "assets": [
        {
          "key": "tasks/2026/08/28/job_01k3m8x9q2z4v7n5p6r8s0t1w3/3f7a1c9e5b2d48f0a6c1e3d5b7f9a1c3.mp3",
          "mime": "audio/mpeg",
          "url": "https://example.r2.cloudflarestorage.com/results/job_01k3m8x9q2z4v7n5p6r8s0t1w3/result.mp3?X-Amz-Signature=SIGNATURE_FROM_RESPONSE",
          "expiresAt": "2026-08-28T12:20:08.000Z"
        }
      ]
    },
    "cost": "0.750000",
    "settled": true,
    "createdAt": "2026-08-28T12:00:00Z",
    "completedAt": "2026-08-28T12:00:30Z"
  }
}

For each available asset, open or download assets[].url directly without an API Authorization header. The signed URL expires at expiresAt; poll the task again to refresh it while the asset remains within its retention period. A pending or unavailable asset has no URL. Treat signed URLs as private.

SDKs & integrations

Use SpicyAPI in your app, terminal, AI assistant or visual workflow. Choose a setup guide below.

Use it in ComfyUI

Install the SpicyAPI nodes from ComfyUI Manager or with the command below, then search for MiniMax Speech 2.8 Turbo · Text to Speech on the canvas. The node has the same options as this page and shows its price before it runs.

cd ComfyUI/custom_nodes
git clone https://github.com/spicyapi-ai/comfyui-spicyapi