Ukrainian text to speech API: set language uk and price a script

Cartesia Sonic 3.6 lists Ukrainian. Send language uk to Sume TTS 1.0, handle the 409 voice mismatch, and price a 5,000-character script at $0.24.

4 min readSume
All posts

Cartesia's Sonic 3.6 page (read 2026-10-05) lists Ukrainian among its 44 languages. Sume TTS 1.0 always runs on Sonic 3.6, so the language list on that page is the one that applies to POST /v1/tts-1.0/generate. The catch for Ukrainian is that Sume only infers Korean and Japanese from the script. Cyrillic text with no language field is treated as English.

The one field you must set

Send language: "uk" on every Ukrainian request. The field takes 2 to 16 characters, and an omitted value defaults to English. Pick a voice whose primary language is Ukrainian. If you pick a voice that Sume knows is set to another language, the request does not fail silently. It returns 409 tts_voice_language_mismatch, and you retry with confirm_language_mismatch: true once you have listened to a sample and decided to accept it.

Code

The helper below submits an async job and polls it, as described in the jobs guide. Set VOICE_ID to a voice UUID or a voi_ library id.

import os, time, requests
B = "https://api.sume.com/v1"
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}

def run(path, body, key=None):
    h = {**H, **({"Idempotency-Key": key} if key else {})}
    r = requests.post(B + path, json={**body, "mode": "async"}, headers=h)
    r.raise_for_status()
    job = r.json()["data"]["job"]["id"]
    while not requests.get(f"{B}/jobs/{job}/status", headers=H).json()["data"]["terminal"]:
        time.sleep(3)
    res = requests.get(f"{B}/jobs/{job}/result", headers=H)
    res.raise_for_status()
    return res.json()["data"]["result"]

res = run("/tts-1.0/generate", {
    "transcript": "Доброго ранку! Ваше замовлення вже в дорозі.",
    "voice": {"id": os.environ["VOICE_ID"]},
    "language": "uk",
})
print(res["audio_url"], res["language"])

What it costs

TTS 1.0 bills $0.0475 per 1,000 characters, which is $47.50 per million. Every character counts, including spaces and punctuation, and Cyrillic letters count one each. The quote rounds up to a whole cent per request. A 5,000-character script is 5 x $0.0475 = $0.2375, so it quotes at $0.24. The 1,000-character case is 5 cents, not 4.75.

Limits that matter for long scripts

  • One request takes at most 20,000 characters, so a Ukrainian script above that needs splitting at a sentence boundary.
  • Audio that comes out longer than 1,200 seconds fails with tts_duration_exceeded, and no credit is captured.
  • The result echoes language and voice, so log them next to the audio URL and you can reproduce the take.

Check before you ship

Listen to the first take yourself or ask a native speaker. Sume does not score pronunciation. If a place name or brand is read wrongly, a pronunciation dictionary (pronunciation_dict_id) is the field to use. Run one short sample first: a 150-character line costs 1 cent after rounding.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume