A podcast intro, a customer call, a scene with two characters: send the whole conversation in one request, give every line its own voice (and dialect, if you like), and get back a single audio file.
Create a dialogue
Send segments instead of text. Each segment is one line with its own voiceId:
import base64
import os
import requests
dialogue = {
"quality": "pro",
"dialectId": "saudi",
"segments": [
{"voiceId": "sara", "text": "هلا فيك! كيف أقدر أساعدك اليوم؟"},
{"voiceId": "fahad", "text": "هلا، أبي أغير موعد التوصيل لو سمحتي."},
{"voiceId": "sara", "text": "أكيد، أي يوم يناسبك؟"},
{"voiceId": "fahad", "text": "بكرة العصر يكون ممتاز."},
],
}
response = requests.post(
"https://api.menavoice.ai/api/tts",
headers={"x-api-key": os.environ["MENAVOICE_API_KEY"]},
json=dialogue,
timeout=180,
)
response.raise_for_status()
with open("call.mp3", "wb") as f:
f.write(base64.b64decode(response.json()["audio"]))import { writeFile } from "node:fs/promises";
const response = await fetch("https://api.menavoice.ai/api/tts", {
method: "POST",
headers: {
"x-api-key": process.env.MENAVOICE_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
quality: "pro",
dialectId: "saudi",
segments: [
{ voiceId: "sara", text: "هلا فيك! كيف أقدر أساعدك اليوم؟" },
{ voiceId: "fahad", text: "هلا، أبي أغير موعد التوصيل لو سمحتي." },
{ voiceId: "sara", text: "أكيد، أي يوم يناسبك؟" },
{ voiceId: "fahad", text: "بكرة العصر يكون ممتاز." },
],
}),
});
const result = await response.json();
if (!response.ok) throw new Error(result.error);
await writeFile("call.mp3", Buffer.from(result.audio, "base64"));curl -X POST https://api.menavoice.ai/api/tts \
-H "x-api-key: $MENAVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"quality": "pro",
"dialectId": "saudi",
"segments": [
{"voiceId": "sara", "text": "هلا فيك! كيف أقدر أساعدك اليوم؟"},
{"voiceId": "fahad", "text": "هلا، أبي أغير موعد التوصيل لو سمحتي."},
{"voiceId": "sara", "text": "أكيد، أي يوم يناسبك؟"},
{"voiceId": "fahad", "text": "بكرة العصر يكون ممتاز."}
]
}' | jq -r .audio | base64 --decode > call.mp3The response has the same shape as a single-voice request. voice lists every voice that spoke, and characters is the total of all lines:
{
"audio": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjYwLjE2LjEwMAAAAAAAAAAA...",
"mimeType": "audio/mpeg",
"voice": "sara, fahad",
"characters": 109
}Segment fields
| Field | Required | Description |
|---|---|---|
text | Yes | What this speaker says. |
voiceId | Yes | The voice for this line. A missing or unknown studio voice falls back to Layla. |
dialectId | No | The dialect for this line. Falls back to the request's top-level dialectId. |
quality and the top-level dialectId apply to the whole dialogue. When segments is present, text is ignored.
How it sounds
- Each line is spoken in its own voice, and the takes are joined into one MP3 with a short, even pause between them.
- Consecutive lines by the same voice in the same dialect are read together in one take, so a speaker's sentences flow naturally.
- Lines that are empty or only whitespace are skipped.
Limits and cost
- Up to 40 lines per request.
- Up to 5,000 characters across all lines together.
- You pay for the characters of all lines, exactly as if they were one text. Line breaks and the pauses between speakers are free.
Cloned voices in a dialogue
With "quality": "clone", every voiceId must be a voice in your voice library, such as your own cloned voice or a saved community voice. If any speaker isn't, the request fails with 400 Pick a voice from your voice library for every speaker. Dialect steering doesn't apply to cloned voices.
In the web app
On the Text to Speech page, click Add speaker to start a new line with its own voice and dialect. A script can have up to 40 lines, and the web app sends them as one dialogue request.

