MAI Voice 2 API, MAI Transcribe 1.5 API: Pricing, Documentation

by Microsoft

MAI Voice 2 API provides developers with a robust, enterprise-ready infrastructure designed to programmatically generate highly expressive and lifelike speech across diverse applications. Operating through a unified endpoint, this advanced audio intelligence tool enables seamless text-to-speech conversion, instant high-fidelity voice cloning, and multilingual narration without requiring extensive fine-tuning or localized hardware setup. It features automatic language detection and nuanced prosody control, making it exceptionally suited for driving interactive virtual assistants, dynamic e-learning modules, accessibility voiceovers, and complex interactive voice response architectures.

Get API Key
MAI Voice API

Models Version

WELCOME BONUS

Get $5 Free Credit on First Payment

No strings attached — add funds and get $5 bonus instantly

Claim Your $5 →

MAI Voice 2 API Documentation

Generate expressive speech from text with Microsoft MAI-Voice-2 on Azure Speech. Asynchronous: submit returns a request_id; poll the status endpoint until the request is COMPLETED. The speech is returned as a 24 kHz mono MP3 file.

POST https://gateway.pixazo.ai/mai-voice-2/v1/text-to-speech

Authentication

All requests require an API key passed via header.

HeaderTypeRequiredDescription
Ocp-Apim-Subscription-KeystringYesYour API subscription key

Text to Speech - Microsoft MAI Voice 2

Request Code

POST https://gateway.pixazo.ai/mai-voice-2/v1/text-to-speech
Content-Type: application/json
Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY

{
  "text": "Hello from Pixazo. This is MAI Voice 2.",
  "voice": "en-US-Harper:MAI-Voice-2",
  "style": "excited",
  "styledegree": 1
}
import requests

url = "https://gateway.pixazo.ai/mai-voice-2/v1/text-to-speech"
headers = {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
}
data = {
  "text": "Hello from Pixazo. This is MAI Voice 2.",
  "voice": "en-US-Harper:MAI-Voice-2",
  "style": "excited",
  "styledegree": 1
}

resp = requests.post(url, json=data, headers=headers)
print(resp.json())
const res = await fetch("https://gateway.pixazo.ai/mai-voice-2/v1/text-to-speech", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
  },
  body: JSON.stringify({
  "text": "Hello from Pixazo. This is MAI Voice 2.",
  "voice": "en-US-Harper:MAI-Voice-2",
  "style": "excited",
  "styledegree": 1
})
});
console.log(await res.json());
curl -X POST 'https://gateway.pixazo.ai/mai-voice-2/v1/text-to-speech' \
  -H 'Content-Type: application/json' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY' \
  --data-raw '{"text": "Hello from Pixazo. This is MAI Voice 2.", "voice": "en-US-Harper:MAI-Voice-2", "style": "excited", "styledegree": 1}'

Output

{
  "request_id": "microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Webhook (Optional)

Instead of polling, you can receive a Webhook callback when the request reaches a terminal state. Provide a Webhook URL via header on the submit request.

HeaderRequiredDescription
X-Webhook-URLTo enableHTTPS URL to receive the Webhook callback.
X-Webhook-ModeNoterminal (default, one callback on COMPLETED/ERROR) or sync (per-poll callbacks).

Example: enable Webhook

curl -X POST 'https://gateway.pixazo.ai/mai-voice-2/v1/text-to-speech' \
  -H 'Content-Type: application/json' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY' \
  -H 'X-Webhook-URL: https://your-server.com/webhook' \
  --data-raw '{"text": "Hello from Pixazo. This is MAI Voice 2.", "voice": "en-US-Harper:MAI-Voice-2", "style": "excited", "styledegree": 1}'

Callback Payload (success)

{
  "request_id": "microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "microsoft-mai-voice-2",
  "output": {
    "media_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/{request_id}/output.mp3",
    "media_type": "audio/mpeg"
  },
  "created_at": "2026-07-31T11:34:16.102Z",
  "completed_at": "2026-07-31T11:34:20.123Z"
}

Failure callback shape

{
  "request_id": "microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "ERROR",
  "model_id": "microsoft-mai-voice-2",
  "error": "Description of the failure"
}

Delivery semantics

  • terminal mode: one Webhook callback when the request is COMPLETED or ERROR.
  • sync mode: a Webhook callback on each status change.
  • Callbacks are idempotent on request_id — de-duplicate on it.
  • Respond 200 within a few seconds; the Webhook endpoint must be HTTPS.

Request Parameters

ParameterRequiredTypeDefaultAllowed values / rangeDescription
textYesstring1–8000 charactersThe text to speak. Billing counts these characters, rounded up to the next 1000.
voiceNostringen-US-Harper:MAI-Voice-2any prebuilt MAI-Voice-2 voice idWhich voice speaks the text. 47 prebuilt MAI-Voice-2 voices are available across 18 locales; every id ends in :MAI-Voice-2, for example es-MX-Valeria:MAI-Voice-2. See Voices and Styles below.
styleNostring— (neutral)voice-specific — e.g. excited, happy, sad, angry, whispering, shoutingSpeaking style, applied as the SSML mstts:express-as style. The supported set varies by voice and some voices support no styles at all. Microsoft specifies that when the style is missing or invalid the whole expressive block is ignored and the voice uses its default neutral speech.
styledegreeNonumber10.01–2 inclusiveIntensity of the chosen style; applies only when style is set. 1 is the predefined style intensity and 2 doubles it. Microsoft specifies that if the value is missing or the voice does not support it, the attribute is ignored.

Text limits

  • text is required and must be a non-empty string of at most 8000 characters. Longer text is rejected at submit.
  • Send plain text, not SSML — voice, style and styledegree are applied for you.
  • Cost scales with the number of characters you submit (see Pricing).

Voices and Styles

47 prebuilt MAI-Voice-2 voices are available across 18 locales (de-DE, en-AU, en-US, es-ES, es-MX, fr-FR, hi-IN, hu-HU, it-IT, ko-KR, nl-NL, pt-BR, pt-PT, ro-RO, ru-RU, th-TH, tr-TR, zh-CN). Pass the full voice id in voice; every id ends in :MAI-Voice-2. The current list is maintained by Microsoft in the MAI-Voice documentation.

Example voiceLocaleGender
en-US-Harper:MAI-Voice-2en-USFemale
en-US-Ethan:MAI-Voice-2en-USMale
en-AU-Lisa:MAI-Voice-2en-AUFemale
es-MX-Valeria:MAI-Voice-2es-MXFemale
fr-FR-Marc:MAI-Voice-2fr-FRMale
hi-IN-Kavya:MAI-Voice-2hi-INFemale
zh-CN-Mei:MAI-Voice-2zh-CNFemale

Styles

Supported styles are per voice. Most voices support the expressive set angry, confused, determined, disgusted, embarrassed, excited, fearful, happy, hopeful, jealous, joyful, regretful, relieved, sad, shouting, softvoice, surprised, whispering. Some voices instead support a narrative set (adventurous, caring, empathy, curious, encouraging, excited, friendly, cheerful, nostalgic, reflective, sad, disappointed, serious), and a few voices support no styles at all. Check the voice you are using against Microsoft’s per-voice style table before relying on a style.

Output

The completed request returns output.media_url, a 24 kHz mono MP3 (audio/mpeg). Fetch that URL to download the audio.

{
  "text": "Welcome to Microsoft Build. MAI Voice 2 supports multilingual expressive synthesis.",
  "voice": "en-US-Harper:MAI-Voice-2",
  "style": "happy",
  "styledegree": 1.2
}

Example Request

{
  "text": "Hello from Pixazo. This is MAI Voice 2.",
  "voice": "en-US-Harper:MAI-Voice-2",
  "style": "excited",
  "styledegree": 1
}

Example Response

{
  "request_id": "microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Request Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
Ocp-Apim-Subscription-KeyYesYour API subscription key.
X-Webhook-URLNoEnable Webhook callbacks (see Webhook section).

Response Handling

Status CodeMeaning
202Accepted — request queued; returns request_id and polling_url.
400Bad request — missing text, text longer than 8000 characters, or a malformed JSON body.
401Unauthorized — missing or invalid subscription key.
402Insufficient balance.
429Too many requests.
500Internal server error.

A failure during synthesis is reported through the status endpoint as status: "ERROR", not as a synchronous error. Failed requests are not billed.

Retrieving Results

Poll the status endpoint with the request_id from the submit response until status is COMPLETED (or FAILED/ERROR), then fetch output.media_url for the audio.

curl 'https://gateway.pixazo.ai/v2/requests/status/microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY'

Completed response

{
  "request_id": "microsoft-mai-voice-2_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "microsoft-mai-voice-2",
  "output": {
    "media_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/{request_id}/output.mp3",
    "media_type": "audio/mpeg"
  },
  "created_at": "2026-07-31T11:34:16.102Z",
  "completed_at": "2026-07-31T11:34:20.123Z"
}

Response Fields

FieldTypeDescription
request_idstringUnique request identifier.
statusstringQUEUED, PROCESSING, COMPLETED, FAILED, or ERROR.
model_idstringThe model that handled the request.
output.media_urlstringURL of the generated MP3 audio file.
output.media_typestringaudio/mpeg.
created_atstringRequest creation timestamp.
completed_atstringCompletion timestamp.
errorstringError message when status is FAILED/ERROR.

Status Values & Flow

QUEUEDPROCESSINGCOMPLETED (success) or FAILED/ERROR (failure).

Pricing

Billed at $0.022 per 1000 characters of input text, rounded up to the next 1000 characters. Billing is based on the text you submit, not on the length of the audio produced.

Characters submittedBilled units (1000 chars)Cost
2501$0.022
10001$0.022
10012$0.044
8000 (maximum)8$0.176

Because the character count is known when you submit, the cost of a request is determined at submit time. Failed requests are not billed.

MAI Voice 2 API Pricing

ResolutionPrice (USD)
Per 1,000 characters of input text$0.022
2. MAI Transcribe 1.5

MAI Transcribe 1.5 API Documentation

Transcribe audio into text with Microsoft's MAI-Transcribe-1.5 model, with automatic language detection across 43 languages. Asynchronous: submit returns a request_id; poll the status endpoint until the request is COMPLETED. The transcript is returned as a JSON file.

POST https://gateway.pixazo.ai/mai-transcribe/v1/speech-to-text

Authentication

All requests require an API key passed via header.

HeaderTypeRequiredDescription
Ocp-Apim-Subscription-KeystringYesYour API subscription key

Speech to Text - Microsoft MAI Transcribe

Request Code

POST https://gateway.pixazo.ai/mai-transcribe/v1/speech-to-text
Content-Type: application/json
Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY

{
  "audio_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/doc-assets/audio/speech-17s.mp3",
  "locales": ["en"],
  "transcribe_style": "verbatim",
  "phrase_list": ["Acme Corp", "Dr. Yamada"]
}
import requests

url = "https://gateway.pixazo.ai/mai-transcribe/v1/speech-to-text"
headers = {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
}
data = {
  "audio_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/doc-assets/audio/speech-17s.mp3",
  "locales": ["en"],
  "transcribe_style": "verbatim",
  "phrase_list": ["Acme Corp", "Dr. Yamada"]
}

resp = requests.post(url, json=data, headers=headers)
print(resp.json())
const res = await fetch("https://gateway.pixazo.ai/mai-transcribe/v1/speech-to-text", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Ocp-Apim-Subscription-Key": "YOUR_SUBSCRIPTION_KEY"
  },
  body: JSON.stringify({
  "audio_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/doc-assets/audio/speech-17s.mp3",
  "locales": ["en"],
  "transcribe_style": "verbatim",
  "phrase_list": ["Acme Corp", "Dr. Yamada"]
})
});
console.log(await res.json());
curl -X POST 'https://gateway.pixazo.ai/mai-transcribe/v1/speech-to-text' \
  -H 'Content-Type: application/json' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY' \
  --data-raw '{"audio_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/doc-assets/audio/speech-17s.mp3", "locales": ["en"], "transcribe_style": "verbatim", "phrase_list": ["Acme Corp", "Dr. Yamada"]}'

Output

{
  "request_id": "microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Webhook (Optional)

Instead of polling, you can receive a Webhook callback when the request reaches a terminal state. Provide a Webhook URL via header on the submit request.

HeaderRequiredDescription
X-Webhook-URLTo enableHTTPS URL to receive the Webhook callback.
X-Webhook-ModeNoterminal (default, one callback on COMPLETED/ERROR) or sync (per-poll callbacks).

Example: enable Webhook

curl -X POST 'https://gateway.pixazo.ai/mai-transcribe/v1/speech-to-text' \
  -H 'Content-Type: application/json' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY' \
  -H 'X-Webhook-URL: https://your-server.com/webhook' \
  --data-raw '{"audio_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/doc-assets/audio/speech-17s.mp3", "locales": ["en"], "transcribe_style": "verbatim", "phrase_list": ["Acme Corp", "Dr. Yamada"]}'

Callback Payload (success)

{
  "request_id": "microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "microsoft-mai-transcribe",
  "output": {
    "media_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/{request_id}/output.json",
    "media_type": "application/json"
  },
  "created_at": "2026-07-31T11:34:16.102Z",
  "completed_at": "2026-07-31T11:34:20.123Z"
}

Failure callback shape

{
  "request_id": "microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "ERROR",
  "model_id": "microsoft-mai-transcribe",
  "error": "Description of the failure"
}

Delivery semantics

  • terminal mode: one Webhook callback when the request is COMPLETED or ERROR.
  • sync mode: a Webhook callback on each status change.
  • Callbacks are idempotent on request_id — de-duplicate on it.
  • Respond 200 within a few seconds; the Webhook endpoint must be HTTPS.

Request Parameters

ParameterRequiredTypeDefaultAllowed values / rangeDescription
audio_urlYesstringhttp(s) URL; WAV, MP3 or FLAC, under 50 MBPublic URL of the audio to transcribe. The file is fetched by the gateway, so the URL must be reachable without authentication.
localesNoarray of string— (multilingual auto-detect)ISO language codes, e.g. ["en"], ["hi"], ["zh"]Optional. Force recognition into a single language. Omit it and the model runs in multilingual mode across the 43 supported languages.
transcribe_styleNostring— (readability-optimised)verbatimOptional. Set to verbatim to preserve the original spoken content including filler words and disfluencies. The default output is cleaned up for readability.
phrase_listNoarray of stringlist of short phrases, e.g. ["Contoso", "Jessie"]Names, product terms, acronyms or jargon that appear in the audio. Biases recognition towards this vocabulary, which improves accuracy on proper nouns and domain terminology.

Audio limits

  • The audio file must be under 50 MB and in WAV, MP3 or FLAC format.
  • audio_url must be an http or https URL and must be publicly reachable.
  • Speaker diarization is not supported — the transcript is not split by speaker.
  • Prompt-tuning is not supported. Use phrase_list to bias recognition instead.
  • Cost scales with the length of the audio (see Pricing).

Transcript Format

The completed request returns output.media_url, a JSON file containing the transcript. Fetch that URL to read the result.

{
  "text": "From Pixazo, this is MAI Voice 2 running through our own gateway.",
  "phrases": [
    {
      "offsetMilliseconds": 0,
      "durationMilliseconds": 5856,
      "text": "From Pixazo, this is MAI Voice 2 running through our own gateway.",
      "locale": "en",
      "confidence": 0
    }
  ],
  "duration_ms": 5860
}
FieldTypeDescription
textstringThe full transcript, with punctuation and capitalisation.
phrasesarray of objectRecognised segments in order. Each entry has text, offsetMilliseconds, durationMilliseconds, locale (the language detected for that segment) and confidence.
duration_msnumberLength of the transcribed audio in milliseconds. This is the quantity you are billed on.

Timestamps are returned per phrase, not per word: each entry in phrases carries offsetMilliseconds and durationMilliseconds.

Example Request

{
  "audio_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/doc-assets/audio/speech-17s.mp3",
  "locales": ["en"],
  "transcribe_style": "verbatim",
  "phrase_list": ["Acme Corp", "Dr. Yamada"]
}

Example Response

{
  "request_id": "microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "QUEUED",
  "polling_url": "https://gateway.pixazo.ai/v2/requests/status/microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

Request Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
Ocp-Apim-Subscription-KeyYesYour API subscription key.
X-Webhook-URLNoEnable Webhook callbacks (see Webhook section).

Response Handling

Status CodeMeaning
202Accepted — request queued; returns request_id and polling_url.
400Bad request — missing audio_url, a non-http(s) URL, or an audio format that could not be determined from the URL and was not supplied.
401Unauthorized — missing or invalid subscription key.
402Insufficient balance.
429Too many requests.
500Internal server error.

An unreachable audio_url, an oversized file, or audio containing no detectable speech is reported through the status endpoint as status: "ERROR", not as a synchronous error. Failed requests are not billed.

Retrieving Results

Poll the status endpoint with the request_id from the submit response until status is COMPLETED (or FAILED/ERROR), then fetch output.media_url for the transcript.

curl 'https://gateway.pixazo.ai/v2/requests/status/microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' \
  -H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY'

Completed response

{
  "request_id": "microsoft-mai-transcribe_019dxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "status": "COMPLETED",
  "model_id": "microsoft-mai-transcribe",
  "output": {
    "media_url": "https://pub-582b7213209642b9b995c96c95a30381.r2.dev/v1/{request_id}/output.json",
    "media_type": "application/json"
  },
  "created_at": "2026-07-31T11:34:16.102Z",
  "completed_at": "2026-07-31T11:34:20.123Z"
}

Response Fields

FieldTypeDescription
request_idstringUnique request identifier.
statusstringQUEUED, PROCESSING, COMPLETED, FAILED, or ERROR.
model_idstringThe model that handled the request.
output.media_urlstringURL of the transcript JSON file.
output.media_typestringapplication/json.
created_atstringRequest creation timestamp.
completed_atstringCompletion timestamp.
errorstringError message when status is FAILED/ERROR.

Status Values & Flow

QUEUEDPROCESSINGCOMPLETED (success) or FAILED/ERROR (failure).

Pricing

Billed at $0.006 per minute of audio ($0.36 per audio hour), rounded up to the next whole minute. Billing is based on the length of the audio you submit, not on the size of the transcript.

Audio lengthBilled minutesCost
20 seconds1$0.006
90 seconds2$0.012
10 minutes10$0.06
1 hour60$0.36

A hold is placed when the request is submitted, because the audio length is not known until transcription completes. The hold is reduced to the real cost once the duration is known, and released in full if the request fails.

MAI Transcribe 1.5 API Pricing

ResolutionPrice (USD)
Per minute of audio (rounded up to the next full minute)$0.006

⚡ Performance

Live usage measured on Pixazo's gateway, split by model version. Generation time is how long a generation takes end-to-end (lower is better). Success rate is the percent of generations that complete (higher is better).

Show data for the last
Generations
100last 30d
~3 per day
Success rate
100.0%
of completed generations
Generation time
15.0savg
p95 15.0s
Requests
Aug 3max 100Sep 1
MAI Voice 2Avg 3/day
Generation Time
Aug 3max 15.0sSep 1
MAI Voice 2Avg 15.0s
Error Rate
Aug 3max 5.0%Sep 1
MAI Voice 2Avg 0.0%

〰 Uptime

Percent of generations that succeeded over the selected period, per model version.

Avg. Success Rate (30d)
100.00%
across all generations of this model family
Uptime
Aug 3max 100%Sep 1
SuccessfulAvg 100.00%