Addis AI

Text-to-SpeechNew

Discover voices, estimate cost, generate speech, and manage durable audio clips.

Addis Voices 2 turns Amharic and Afaan Oromo text into durable audio clips. It is billed by generated duration at 5 ETB per minute and does not stream partial audio.

Maintaining a Voice 1 integration?

The original Text-to-Speech API is deprecated and hidden from the primary navigation. Open the Legacy Text-to-Speech guide →

Discover voices

Query the catalog rather than copying an arbitrary ID into production configuration. am-hamen is the canonical Amharic example.

const voices = await addis.voices.list({ language: "am" });
for (const voice of voices) {
  console.log(voice.id, voice.name, voice.isAvailable);
}
voices = addis.voices.list(language="am")
for voice in voices:
    print(voice["id"], voice["name"], voice["is_available"])
curl "https://api.addisassistant.com/api/v1/voice/voices?language=am" \
  -H "x-api-key: $ADDIS_API_KEY"

The catalog is dynamic. Filter for the requested language and store only IDs currently marked available. Each entry includes the voice ID, name, descriptor, language, gender, style, tags, preview URL, default status, and availability.

Catalog filters

FilterNode.jsPythonValues
Languagelanguagelanguageam or om
Gendergendergenderfemale or male
SearchsearchsearchName, ID, descriptor, style, or tag text
Include unavailable voicesincludeUnavailableinclude_unavailablefalse by default

Browse current voice IDs

The playable catalog below is synchronized with the current backend availability list and developer-platform previews, and was verified on July 23, 2026. Your application should still call voices.list() because availability can change without a documentation release.

Voice catalog

Current playable voices

Preview the current catalog and copy the exact ID into your request. Live availability still comes from voices.list().

28playable previews
Language

Showing 6 of 19 Amharic voices

  • Hamen

    Warm conversational delivery

    female
    am-hamenConversational
  • Yohannes

    Low-key reflective tone

    male
    am-yohanes-calmNarration
  • Tesfa

    Confident, forward-leaning read

    male
    am-tesfaCommercial
  • Muaz

    Clear expressive delivery

    male
    am-muazCommercial
  • Roba

    Energetic bright tone

    male
    am-robaCommercial
  • Nejat

    Smooth measured elegance

    female
    am-nejatConversational

Preview a voice

const preview = await addis.voices.preview("am-hamen");
console.log(preview.audioUrl);
preview = addis.voices.preview("am-hamen")
print(preview["audio_url"])
curl https://api.addisassistant.com/api/v1/voice/voices/am-hamen/preview \
  -H "x-api-key: $ADDIS_API_KEY"

Preview URLs are signed and can expire. Fetch fresh preview metadata instead of storing the URL permanently.

Estimate cost

Estimate before generation when a user must approve spend or the application is close to its available balance.

const input = {
  text: "ሰላም፣ ይህ የአዲስ ድምፅ ሁለት ሙከራ ነው።",
  voiceId: "am-hamen",
  language: "am" as const,
  outputFormat: "mp3_44100" as const,
};

const estimate = await addis.voice.estimate(input);
if (!estimate.canGenerate) throw new Error("Insufficient balance");
console.log(estimate.estimatedCost, estimate.currency);
input = {
    "text": "ሰላም፣ ይህ የአዲስ ድምፅ ሁለት ሙከራ ነው።",
    "voice_id": "am-hamen",
    "language": "am",
    "output_format": "mp3_44100",
}

estimate = addis.voice.estimate(**input)
if not estimate["can_generate"]:
    raise RuntimeError("Insufficient balance")
print(estimate["estimated_cost"], estimate["currency"])
curl https://api.addisassistant.com/api/v1/voice/estimate \
  -H "x-api-key: $ADDIS_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "text":"ሰላም፣ ይህ የአዲስ ድምፅ ሁለት ሙከራ ነው።",
    "voice_id":"am-hamen",
    "language":"am",
    "output_format":"mp3_44100"
  }'

The estimate reports the pricing unit, price per minute, estimated duration, billable duration, cost, current balance, projected balance, currency, and whether generation is currently allowed.

Generate and save a clip

const clip = await addis.voice.generate({
  ...input,
  clientRequestId: crypto.randomUUID(),
});

await clip.toFile("speech.mp3");
console.log(clip.id, clip.audioUrl, clip.usage);
clip = addis.voice.generate(
    **input,
    client_request_id="order-123",
)

clip.to_file("speech.mp3")
print(clip.id, clip.audio_url, clip.usage)
curl https://api.addisassistant.com/api/v1/voice/generations \
  -H "x-api-key: $ADDIS_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "text":"ሰላም፣ ይህ የአዲስ ድምፅ ሁለት ሙከራ ነው።",
    "voice_id":"am-hamen",
    "language":"am",
    "output_format":"mp3_44100",
    "client_request_id":"order-123"
  }' | tee voice.json

curl --location "$(jq -r '.data.audio_url' voice.json)" \
  --output speech.mp3

The cURL example requires jq. A generation response contains clip metadata and a signed audio_url. A first response may also include an audio data URL; an idempotent replay can omit that inline field, so use the signed URL or SDK file helper.

Output formats

FormatUse
mp3_44100Compact delivery for web, mobile, and downloads.
wav_44100Uncompressed editing and audio pipelines.
pcm_16000Speech pipelines expecting 16 kHz PCM in a WAV container.

Choose the format before estimating because output choice can affect generated duration and storage behavior.

Idempotency and retries

clientRequestId in Node.js and client_request_id in Python identifies one logical generation.

  • Reuse it when retrying the same request after a timeout or uncertain response.
  • Generate a new value for different text, voice, language, or output format.
  • Do not retry a validation error unchanged.
  • For a generation-in-progress response, wait for the reported retry interval before checking again.

Voice settings

speed is currently applied. stability, similarity, and style are accepted for compatibility but ignored by the current provider. The response reports ignored settings in meta.ignoredVoiceSettings or meta["ignored_voice_settings"].

Do not build user-facing behavior that assumes an ignored control changes the generated clip.

Usage and clip history

const usage = await addis.voice.usage();
const page = await addis.voice.clips.list({ limit: 20 });

const clip = await addis.voice.clips.get(page.data[0].id);
await clip.toFile("saved-clip.mp3");
await addis.voice.clips.delete(clip.id);
usage = addis.voice.usage()
page = addis.voice.clips.list(limit=20)

clip = addis.voice.clips.get(page.data[0]["id"])
clip.to_file("saved-clip.mp3")
addis.voice.clips.delete(clip.id)
curl https://api.addisassistant.com/api/v1/voice/usage \
  -H "x-api-key: $ADDIS_API_KEY"

curl https://api.addisassistant.com/api/v1/voice/clips \
  -H "x-api-key: $ADDIS_API_KEY"

curl -X DELETE https://api.addisassistant.com/api/v1/voice/clips/CLIP_ID \
  -H "x-api-key: $ADDIS_API_KEY"

Addis Voices 2 usage is billed at 5 ETB per generated minute. Use the estimate before generation when a user must approve spend, and use the usage response to display current ETB balance and total spend.

Errors

Common failures include unavailable voice IDs, unsupported formats, insufficient balance, idempotency conflicts, generation still in progress, rate limiting, and transient provider errors.

Refresh the voice catalog after an unavailable-voice error. Log the clip ID, request ID, and client request ID, but never the API key or sensitive full text.

Best Practices

Ensure high-quality output and reliable billing with these production patterns.

Script & Punctuation

Natural pauses: Use Ethiopic punctuation and complete sentences.
Consistent script: Transliterate mixed terms explicitly when pronunciation matters.

Voice Selection

Discover: Query and filter the catalog instead of hardcoding a voice count.
Preview: Listen before saving a voice as the application default.

Cost & Retries

Estimate first: Estimate when a user must approve spend.
Idempotency: Reuse a client request ID only when retrying the same logical generation.

Clip Delivery

Persist IDs: Store durable clip IDs instead of expiring signed URLs.
Completed audio: Split very long text at natural boundaries; Addis Voices 2 does not stream partial audio.

Migrate from Legacy Text-to-Speech

Addis Voices 2 uses the same Addis AI API key as the legacy API, so no credential migration is required. HTTP header names are case-insensitive: the SDK reads ADDIS_API_KEY, and raw requests send it through x-api-key.

AreaLegacy Text-to-SpeechAddis Voices 2
Endpoint/api/v1/audio/api/v1/voice/generations
AuthenticationExisting Addis AI API key in X-API-KeyThe same API key through the SDK or x-api-key; no credential change
Requesttext, language, and optional streamtext, voice_id, language, output_format, and optional client_request_id
Voice selectionLanguage selects the legacy engineQuery the voice catalog, preview an available voice, then send its exact ID
ResponseBase64 WAV JSON or a legacy audio streamDurable clip metadata and a signed audio_url; partial streaming is not supported
SDKlegacy.audio.generate() or legacy.audio.stream()voice.generate(), voices.list(), estimates, usage, and clip management
PricingExisting Voice 1 account pricing remains unchanged5 ETB per generated minute, with a pre-generation estimate

For a new integration, follow Generate and save a clip. Existing applications can keep using the complete Legacy Text-to-Speech guide while migrating one use case at a time. Review Pricing before switching production traffic.

Contract last verified:

On this page