Guide · Speech APIs

Use Fourier TTS with an OpenAI-compatible speech client.

Already using OpenAI's speech API? Change three values and your code speaks Hindi, English, Gujarati, Tamil or Telugu with Fourier TTS. Just set response_format: we don't do MP3, and without it you get raw 48 kHz PCM.

By Frequency · Updated 16 October 2026.

Read the API docs

Only the base URL, the model and the voice change.

The base URL, the model and the voice. Keep the key on your server, never in a browser or mobile app.

Setting Mira value
Base URL https://sandbox.voice.miraiminds.co/v1
Request path /audio/speech, under that base URL
Model mira-tts (the older mira-tts-v51 still works as an alias)
Voice ashu, neha, shruti or sameer; neha if you leave it out
Output Always set response_format
Input Up to 2,000 characters

Fourier TTS costs ₹1.80 per 1,000 characters. Building a whole phone agent? Those cost ₹1 a minute on our volume plan; see AI calling.

For a key, open Developers in the sandbox and press Create key. The sk_live_ key shows once and works across the v2 API. The same handler also sits at POST /v2/tts, which takes text in place of input.

Your first request saves a WAV file.

This saves a WAV file and spends a few paise. Put your key in MIRA_API_KEY first.

curl --fail-with-body \
  https://sandbox.voice.miraiminds.co/v1/audio/speech \
  -H "Authorization: Bearer $MIRA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "mira-tts",
    "voice": "neha",
    "response_format": "wav",
    "input": "नमस्ते, आपका ऑर्डर तैयार है।"
  }' \
  --output speech.wav

If it fails, --fail-with-body writes the error into speech.wav, so check before you press play.

Pick the format and sample rate you need.

response_format You get Streams?
pcm Raw signed 16-bit little-endian mono, no header Yes
mulaw (also ulaw, pcm_mulaw) Raw G.711 μ-law, one byte per sample Yes
alaw (also pcm_alaw) Raw G.711 A-law, one byte per sample Yes
wav A playable 16-bit mono file No, it comes when synthesis ends

sample_rate takes 8000, 16000, 22050, 24000, 44100 or 48000, with μ-law and A-law at 8000 or 16000 only. Defaults are 48000 for pcm and wav, 8000 for μ-law and A-law. A rate in the format, like pcm_16000, wins; a conflicting sample_rate gets a 400.

On a phone line, ask for the line’s format and forward chunks as they come. Most lines carry 8 kHz μ-law, so ulaw_8000 needs no decoding or resampling.

You can stream with the OpenAI Python SDK.

import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["MIRA_API_KEY"],
    base_url="https://sandbox.voice.miraiminds.co/v1",
)

with client.audio.speech.with_streaming_response.create(
    model="mira-tts",
    voice="ashu",
    response_format="pcm",
    input="चलिए, आपका order कल deliver होगा।",
    extra_body={"sample_rate": 16000},
) as response:
    print(response.headers.get("x-sample-rate"), response.headers.get("x-audio-encoding"))
    with open("speech_16k.pcm", "wb") as out:
        for chunk in response.iter_bytes():
            out.write(chunk)  # raw s16le mono at 16 kHz; feed a player here instead

We ran this with openai 1.109.1 against the sandbox on 16 October 2026. It printed 16000 pcm_s16le and wrote 16 kHz raw PCM.

Play chunks as they arrive, or there’s no point streaming. For live conversations, the WebSocket endpoint is better: one connection per call, text as your model writes it, and one message to stop when the caller interrupts.

The headers tell you how to play the audio.

Every 200 carries these:

Header Meaning
X-Request-Id Request ID (tts_…), as in your request log
X-Chars-Billed Characters billed
X-Cost-Paise Cost, once it completes
X-Sample-Rate Sample rate you got
X-Audio-Encoding pcm_s16le, mulaw or alaw
X-Mira-Model The build that made it, like miraiminds/mira-tts-v53

Raw audio has no header, so read X-Sample-Rate and X-Audio-Encoding before you play it. Get them wrong and you hear noise, or the wrong speed. Note X-Mira-Model when you compare releases. GET /v2/tts/requests lists every request with first_byte_ms, total_ms and cost.

Existing adapters often trip on OpenAI’s defaults.

Adapters often bake in OpenAI’s defaults. Check yours doesn’t:

  • reject neha or shruti as unknown voices,
  • ask for MP3 unless you override it,
  • assume a rate, like 24 kHz, instead of reading X-Sample-Rate,
  • buffer the whole response even though we stream it.

On Pipecat, use pipecat-mirai instead of the OpenAITTSService workaround; see the Pipecat guide. Anywhere else, listen to what actually plays.

These are the errors you might see, and the fixes.

Errors carry X-Request-Id. Quote it when you ask us for help.

  • 400 invalid_request: fix the field it names, such as empty input, an unknown voice or a format we don’t do.
  • 401 unauthorized: check the Authorization: Bearer sk_live_… header.
  • 402 insufficient_balance: top up. Nothing was made or charged.
  • 404 model_not_found: use mira-tts.
  • 429 at_capacity or rate_limited: wait for Retry-After, then resend.
  • 502 upstream_error: retry. 503 fleet_offline: wait for Retry-After. Neither is charged.

Cap retries on a live call: a sentence that plays after the moment has passed is worse than none. Our request log keeps only the first 48 characters of each input. The latency guide helps you tell a slow request from a playback problem.

Sources

These are the references this guide is built on.

References reviewed on . Measurement dates and experimental limits are stated in the article. Check current API and runtime documentation when integrating.

Questions

These are the questions developers ask us most.

What base URL and model should an OpenAI speech client use?

Base URL https://sandbox.voice.miraiminds.co/v1 and model mira-tts. Voices are ashu, neha, shruti and sameer. Always set response_format.

Can I keep an OpenAI client's default MP3 output?

No. mp3 returns a 400 listing what works: pcm, wav, mulaw (or ulaw) and alaw, plus forms like pcm_16000 and ulaw_8000. Leave the format out and you get raw 48 kHz PCM.

How do I get audio at 8 or 16 kHz through the OpenAI SDK?

Pass sample_rate in the SDK's extra_body, or use a format with the rate in it, like pcm_16000. X-Sample-Rate on the response confirms it.

Will any framework with an OpenAI TTS adapter work unchanged?

Not always. The request shape matches, but the defaults may not. Check the adapter's voice list, default format and assumed sample rate. On Pipecat, use pipecat-mirai instead of OpenAITTSService.

Still deciding? Ask us.

Fifteen minutes with the team that builds it. Bring your script, or your hardest call.

Book 15 minutes

Book a call

15 minutes with Sneh Mehta

Finding a time for us…

  1. AI agents from ₹1 a minute: on our volume plan, ₹1,00,000 a month. Pay as you go is ₹5 a minute. Prices exclude GST.