Skip to content
Lumean API

Templates are required for TTS

The voice lives in the template, not in the order. How to build a config, how to deviate from it for a single order, and why one flag matters more than it seems.

The first thing a voiceover integration trips over: there is no orders.voice_id field. The voice, model, output format, and fine-tuning settings live in the template; the order keeps only the text. You can't create a TTS order without template_id: task_type: "tts" will pass validation and fail at service resolution.

Two steps, in order

BASE=https://api.lumean.app/api/public

# 1. Template: service, model, voice, settings, created once
curl -s -X POST "$BASE/templates" -H "X-API-KEY: $KEY" -d '{
  "service_key": "elevenlabs",
  "name": "My TTS",
  "config": {
    "tts_settings": {
      "mode": "mode_v1",
      "model_id": "eleven_multilingual_v2",
      "voice_id": "<VOICE_ID>",
      "advanced_voice_settings": true,
      "voice_settings": { "stability": 0.5, "similarity_boost": 0.75, "use_speaker_boost": true, "speed": 1.0 }
    }
  }
}'
# → data.id = <TEMPLATE_UUID>

# 2. Order: the text goes in top-level input_text, NOT in task_data
curl -s -X POST "$BASE/orders" -H "X-API-KEY: $KEY" -H "Content-Type: application/json" \
  -d '{ "template_id": "<TEMPLATE_UUID>", "input_text": "Hello! This is a test voiceover." }'

task_data is the shape for orders without a template (sfx, music, voice_search): that is where the prompt goes. The standard channels for TTS text are input_text and a .txt file in input_files[]; see Speech text.

Gotcha

The automation scope preset does not include templates.write, only templates.read. The “create a template → order TTS” scenario can't be completed end to end with it: step 1 returns 403. Use the full preset or add the scope manually. See Authentication.

A template belongs to the account, not the key

A template created in the web dashboard works with the API, and vice versa: the owner is the account, not the key. GET /templates called with a key sees the same templates as the dashboard. Another account's template won't open with any key: you get 403 with reason: "template_access_denied".

403template_access_deniedtemplate_access_denied — no access to the template
What happened
A domain refusal of order creation: HTTP 403, body `{"success": false, "message": "…", "reason": "template_access_denied"}`. The order was not created.
What to do right now
Check that the template is visible to the key. A template is owned by the account, not by a specific key: a template created on the web works for the API and vice versa, but a template that belongs to another account will not open with any key. If the template is yours, the problem is scopes: `automation` does not include `templates.write`, but it does include `templates.read`.
Open the code page

What goes into config

The structure of config is defined by the service from service_key, and you don't need to guess it: the configuration reference returns type, default, nullable for each field and, depending on the type, either options or min/max/step.

The response is grouped into sections, but a section is not always a path in the config:

ServiceShown in the referenceWhat config / task_data accept
elevenlabs, heygen, lumimgtts_settings → model_id{"tts_settings": {"model_id": …}}
sfx, music, voice_searchsfx_settings → text{"text": …}, the wrapper is dropped

The conditional_overrides section describes restrictions that depend on your choices: for non-v3 ElevenLabs models the language list shrinks from 73 values to 29, and on the v3 family stability accepts only 0.0, 0.5, and 1.0. A value outside the schema → 422 when the template is created.

The flag without which three settings silently do nothing

similarity_boost, style, and use_speaker_boost take effect only with tts_settings.advanced_voice_settings: true. The flag defaults to false, and then only stability and speed reach the speech engine.

Careful

There will be no error. The three parameters are saved in the template and pass validation (exclude_when removes the rules from them, not the values), but they won't affect the sound: from the outside it looks like “the setting doesn't work”. Set the flag in the same tts_settings object.

One-off deviation — config_override

config_override in POST /orders is the only way to change parameters for a specific order without creating a new template. Its shape is the same object as config; it is applied on top of template.config for this order only.

{
  "template_id": "<TEMPLATE_UUID>",
  "input_text": "Same text, different voice.",
  "config_override": { "tts_settings": { "voice_id": "<OTHER_VOICE_ID>" } }
}

Three rules that can each cost you an evening of debugging:

  • Paths outside the service schema are silently dropped: a typo in a key is indistinguishable from “the setting wasn't applied”. No 422, no warning.
  • An explicit null erases the value; it does not mean “leave as is”: the merge uses array_replace_recursive. The only way to say “don't touch” is to omit the key.
  • It works only together with template_id: for template-less sfx/music the parameters are already in task_data.

Do

Send only the keys you're changing: {"tts_settings": {"speed": 1.1}}. The rest of the template config is preserved.

Don't

Send the entire shape with null in the fields you didn't fill in: voice_id and language_code will be erased for this order.

The generation_mode key (paragraph mode) sits not inside tts_settings but next to it, at the root: {"generation_mode": "paragraph"}. It isn't in the reference, which describes service settings. The mode affects the price: the minimum billable volume is calculated for each paragraph.

Editing a template: config is merged, not replaced

Gotcha

The OpenAPI description of the PUT/PATCH operation claims that “config is replaced entirely”. That is wrong: the config is deep-merged with the current one. The request body description of the same request says exactly the opposite, and the example and the 200 response agree with it. The practical consequence: a key you didn't send keeps its previous value. You can't reset it to the default by editing the template, only by recreating the template.

The second trap of the same request: service_key and config go together. Validation doesn't accept one without the other, so even when you aren't changing the service, you have to repeat its key. PUT and PATCH behave the same way, and an edit doesn't affect orders that have already been created.

If a TTS order isn't created

SymptomCause
422, reason: "service_not_found"task_type: "tts" was sent instead of template_id
422 with a field in errorsThe template was deleted (deletion is irreversible), or config failed schema validation
Not all settings were appliedadvanced_voice_settings: false or a typo in config_override

Feed this page to an AI

Open .mdllm.md

Updated 09/04/2026 · spec 0.0.1