Miso One API
Generate multi-voice dialogue audio with the Miso One API.
Overview
The Miso One API turns a written multi-speaker script into an audio file. Send a dialogue request, receive a task ID, then poll the task until the audio result is ready.
Miso One currently authenticates with your logged-in web session. Include your session cookie when calling the API from a browser session or a trusted tool that can access that session.
Authentication
Cookie: <session cookie>If the session is missing or expired, the API returns an auth error.
Create a dialogue task
POST /api/ai/generate
Content-Type: application/json
Cookie: <session cookie>Request body
{
"mediaType": "speech",
"presetId": "miso-one",
"options": {
"dialogue": [
{ "voice": "Adam", "text": "[excited] Did you hear the news?" },
{ "voice": "Brian", "text": "[laughs] Tell me everything." }
],
"language_code": "en"
}
}| Field | Type | Required | Description |
|---|---|---|---|
mediaType | string | yes | Always "speech" |
presetId | string | yes | Always "miso-one" |
options.dialogue | array | yes | Ordered speaker lines. Each item needs voice and text. |
options.language_code | string | no | Language hint such as "en", "zh", "ja", or "ko". |
options.stability | number | no | Voice stability setting. Omit this field to use the default value. |
prompt | string | no | Optional note saved with the task. |
Dialogue line format
{
"voice": "Adam",
"text": "[excited] The launch went perfectly."
}Use one dialogue line per speaker turn. The total spoken text in a single request can include up to 5,000 characters.
Poll task status
The create endpoint returns immediately with a task object. Use the task id to check progress.
POST /api/ai/query
Content-Type: application/json
Cookie: <session cookie>Query body
{
"taskId": "task_xxx"
}Pending response
{
"code": 0,
"message": "ok",
"data": {
"id": "task_xxx",
"status": "processing",
"mediaType": "speech",
"presetId": "miso-one",
"displayModel": "Miso One",
"prompt": null,
"taskInfo": null
}
}Completed response
When status is "success", parse data.taskInfo. It contains an audios array with the generated audio URL.
{
"code": 0,
"message": "ok",
"data": {
"id": "task_xxx",
"status": "success",
"mediaType": "speech",
"presetId": "miso-one",
"displayModel": "Miso One",
"taskInfo": "{\"audios\":[{\"id\":\"task_xxx-0\",\"audioUrl\":\"https://cdn.example.com/audio.mp3\"}]}"
}
}Task statuses:
| Status | Meaning |
|---|---|
pending | The task has been created. |
processing | The audio is still being generated. |
success | The audio is ready in taskInfo.audios. |
failed | The task failed. Check taskInfo.errorCode. |
canceled | The task was canceled. |
Supported voices
| Voice | Character |
|---|---|
| Adam | Warm, expressive male |
| Brian | Natural, conversational male |
| Roger | Clear, authoritative male |
| Rachel | Calm, professional female |
| Antoni | Smooth, focused male |
| Bella | Bright, energetic female |
| Elli | Friendly, approachable female |
| Josh | Deep, confident male |
| Arnold | Firm, grounded male |
| Clyde | Relaxed, casual male |
| Domi | Clear, neutral female |
| Freya | Warm, empathetic female |
| Grace | Light, pleasant female |
| Nicole | Soft, thoughtful female |
| Sam | Versatile, neutral |
| Sarah | Crisp, professional female |
Emotion tags
Add emotion tags at the start of a line to guide delivery:
[excited] Great news!
[whispers] Can you keep a secret?
[laughs] That is hilarious.
[sighs] I was not expecting that.Credit cost
Dialogue generation uses dynamic credit billing based on total spoken text:
| Rule | Value |
|---|---|
| Min | 30 credits per generation |
| Rate | 500 credits per 1,000 characters |
| Limit | 5,000 characters per request |
curl example
APP_URL="https://misooneai.com"
TASK_RESPONSE=$(curl "$APP_URL/api/ai/generate" \
-H "Content-Type: application/json" \
-H "Cookie: <your-session-cookie>" \
-d '{
"mediaType": "speech",
"presetId": "miso-one",
"options": {
"dialogue": [
{ "voice": "Adam", "text": "[excited] The launch went perfectly." },
{ "voice": "Rachel", "text": "Incredible. What happens next?" },
{ "voice": "Adam", "text": "We scale." }
],
"language_code": "en"
}
}')
echo "$TASK_RESPONSE"Then poll the returned task ID:
curl "$APP_URL/api/ai/query" \
-H "Content-Type: application/json" \
-H "Cookie: <your-session-cookie>" \
-d '{"taskId":"task_xxx"}'JavaScript example
const createResponse = await fetch('/api/ai/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
mediaType: 'speech',
presetId: 'miso-one',
options: {
dialogue: [
{ voice: 'Adam', text: '[excited] The launch went perfectly.' },
{ voice: 'Rachel', text: 'Incredible. What happens next?' },
],
language_code: 'en',
},
}),
});
const createPayload = await createResponse.json();
if (createPayload.code !== 0) {
throw new Error(createPayload.message);
}
const taskId = createPayload.data.id;
const queryResponse = await fetch('/api/ai/query', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ taskId }),
});
const queryPayload = await queryResponse.json();
const taskInfo = queryPayload.data.taskInfo
? JSON.parse(queryPayload.data.taskInfo)
: {};
const audioUrl = taskInfo.audios?.[0]?.audioUrl;Errors
All API responses use the same envelope:
{
"code": -1,
"message": "generate ai task failed",
"data": {
"errorCode": "auth_required"
}
}Common error codes:
| Error code | Meaning |
|---|---|
auth_required | The user is not logged in or the session expired. |
insufficient_credits | The account does not have enough credits. |
invalid_input | The request body is missing required fields. |
content_policy | The dialogue content was rejected. |