Properties
| Name | Type | Description |
|---|---|---|
| model | string | Default model for every item that doesn’t set its own. |
| voice | string | Default voice for every item that doesn’t set its own. With no voice anywhere (or `default` / `auto` / a language tag), each item gets the voice the server picks for its language, as POST speech does. |
| gender | string | With no voice named: prefer a voice of this gender. |
| language | string | Default language. Omit to infer per item from its own text; text with no clear sign of its language is read in the item voice’s own. |
| speed | number | |
| response_format | string | Default audio encoding for every item that doesn’t set its own. Every item is a COMPLETE file — real sizes in its header, not the streaming placeholder — so the result is directly playable and directl |
| pauses | object | Default for every item; an item’s own `pauses` override it field by field. Pauses placed between engine calls, in milliseconds. Long text is synthesized in several calls (by sentence: about 120 charac |
| items | array | Up to 64 items, answered on this one connection. For more than that (or for work you don’t want to hold a socket open for), create an async job with POST /v1/audio/batches instead. |
| stream | boolean | true (default): `application/x-ndjson` — one JSON object per line, written the moment that item finishes, so you can start using results before the batch is done. false: one buffered `application/json |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/ditto-audio/json-schema/ditto-audio-speech-batch-dto-schema.json",
"title": "SpeechBatchDto",
"x-generated": "2026-11-05",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/ditto-audio-openapi.json#/components/schemas/SpeechBatchDto",
"type": "object",
"properties": {
"model": {
"type": "string",
"enum": [
"kokoro",
"xtts",
"pocket"
],
"description": "Default model for every item that doesn’t set its own."
},
"voice": {
"type": "string",
"description": "Default voice for every item that doesn’t set its own. With no voice anywhere (or `default` / `auto` / a language tag), each item gets the voice the server picks for its language, as POST speech does."
},
"gender": {
"type": "string",
"enum": [
"female",
"male",
"neutral"
],
"description": "With no voice named: prefer a voice of this gender."
},
"language": {
"type": "string",
"description": "Default language. Omit to infer per item from its own text; text with no clear sign of its language is read in the item voice’s own."
},
"speed": {
"type": "number",
"default": 1,
"minimum": 0.5,
"maximum": 2
},
"response_format": {
"type": "string",
"enum": [
"mp3",
"mp3_64",
"mp3_160",
"wav",
"wav24",
"wav32f",
"flac",
"flac24",
"pcm",
"pcm_f32",
"aiff",
"caf",
"au",
"mulaw",
"alaw"
],
"default": "mp3",
"description": "Default audio encoding for every item that doesn’t set its own. Every item is a COMPLETE file — real sizes in its header, not the streaming placeholder — so the result is directly playable and directly saveable. Hi-fidelity formats bill at 1.2× the normal rate, multiplied by the model’s own weighting — the audio is identical, but the bytes are several times larger. `mp3` (the default), `mp3_64`, `mulaw` and `alaw` are unchanged at 1×. Each format’s exact multiplier is in GET /v1/audio/format and in the `X-Ditto-Audio-Cost-Multiplier` response header."
},
"pauses": {
"description": "Default for every item; an item’s own `pauses` override it field by field. Pauses placed between engine calls, in milliseconds. Long text is synthesized in several calls (by sentence: about 120 characters a call for xtts and pocket, 60 for Pocket Japanese and 75 for Pocket Korean; one sentence a call for kokoro) and joined; inside a call the model places every pause itself. Omit a field (or the whole object) and that join gets the pause the model itself leaves at that kind of boundary, scaled by `speed`. A value you set is exact: not scaled by `speed`. The pause is what a listener hears between the two words: whatever silence each side already ends or starts with counts toward it. The clip also ends with its last boundary's pause, so clips can be concatenated. Defaults at speed 1 (ms): `xtts`: sentence 540 (460 after ?, 500 after !), clause 330 (after a comma), paragraph 810; `kokoro`: sentence 430 (420 after ?, 440 after !), clause 150 (after a comma), paragraph 640; `pocket`: sentence 770 (850 after ?, 670 after !), clause 240 (after a comma), paragraph 1160.",
"allOf": [
{
"$ref": "#/$defs/PausesDto"
}
]
},
"items": {
"maxItems": 64,
"description": "Up to 64 items, answered on this one connection. For more than that (or for work you don’t want to hold a socket open for), create an async job with POST /v1/audio/batches instead.",
"type": "array",
"items": {
"$ref": "#/$defs/SpeechBatchItemDto"
}
},
"stream": {
"type": "boolean",
"default": true,
"description": "true (default): `application/x-ndjson` — one JSON object per line, written the moment that item finishes, so you can start using results before the batch is done. false: one buffered `application/json` envelope `{ results, summary }` with results in REQUEST order."
}
},
"required": [
"items"
],
"$defs": {
"PausesDto": {
"type": "object",
"properties": {
"sentence": {
"type": "number",
"minimum": 0,
"maximum": 5000,
"description": "Milliseconds after a sentence (. ! ? …). Setting it sends every sentence as its own engine call, so EVERY sentence boundary gets exactly this pause instead of the model’s own."
},
"clause": {
"type": "number",
"minimum": 0,
"maximum": 5000,
"description": "Milliseconds where a sentence too long for one engine call is cut at a comma, semicolon, colon or dash. Commas inside a call are paced by the model and are not affected."
},
"paragraph": {
"type": "number",
"minimum": 0,
"maximum": 5000,
"description": "Milliseconds at a blank line in `input`."
}
}
},
"SpeechBatchItemDto": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Your own correlation id, echoed back on this item’s result. Never interpreted by us and never required to be unique — results also carry `index`, which always identifies the item unambiguously."
},
"model": {
"type": "string",
"enum": [
"kokoro",
"xtts",
"pocket"
],
"description": "Overrides the batch default for this item."
},
"voice": {
"type": "string",
"description": "Overrides the batch default for this item. Omit both and the server picks the voice for the item’s language."
},
"gender": {
"type": "string",
"enum": [
"female",
"male",
"neutral"
],
"description": "Overrides the batch default for this item: with no voice named, prefer this gender."
},
"input": {
"type": "string",
"maxLength": 8000,
"description": "The text to speak. The only required field."
},
"language": {
"type": "string",
"description": "Overrides the batch default for this item. See GET /v1/audio/languages."
},
"speed": {
"type": "number",
"minimum": 0.5,
"maximum": 2,
"description": "Overrides the batch default for this item."
},
"response_format": {
"type": "string",
"enum": [
"mp3",
"mp3_64",
"mp3_160",
"wav",
"wav24",
"wav32f",
"flac",
"flac24",
"pcm",
"pcm_f32",
"aiff",
"caf",
"au",
"mulaw",
"alaw"
],
"description": "Overrides the batch default for this item — each result is its own complete file, so a batch may mix formats freely. Billed at this item’s own rate."
},
"pauses": {
"description": "Overrides the batch default for this item, field by field. Pauses placed between engine calls, in milliseconds. Long text is synthesized in several calls (by sentence: about 120 characters a call for xtts and pocket, 60 for Pocket Japanese and 75 for Pocket Korean; one sentence a call for kokoro) and joined; inside a call the model places every pause itself. Omit a field (or the whole object) and that join gets the pause the model itself leaves at that kind of boundary, scaled by `speed`. A value you set is exact: not scaled by `speed`. The pause is what a listener hears between the two words: whatever silence each side already ends or starts with counts toward it. The clip also ends with its last boundary's pause, so clips can be concatenated. Defaults at speed 1 (ms): `xtts`: sentence 540 (460 after ?, 500 after !), clause 330 (after a comma), paragraph 810; `kokoro`: sentence 430 (420 after ?, 440 after !), clause 150 (after a comma), paragraph 640; `pocket`: sentence 770 (850 after ?, 670 after !), clause 240 (after a comma), paragraph 1160.",
"allOf": [
{
"$ref": "#/$defs/PausesDto"
}
]
}
},
"required": [
"input"
]
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
This JSON Schema
curl "https://apis.io/api/v1/json-schemas/ditto-audio-speech-batch-dto"
All schemas
curl "https://apis.io/api/v1/json-schemas?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.