Key & quick start
The bot and API share the same character balance.
Get an API key
- Open @sonapro_bot.
- Choose 🔌 API → Create key.
- Send
sk_user_…in every request header.
X-API-Key: sk_user_…Important: never put the key in frontend code, public GitHub or chat. Creating a new key in the bot revokes the previous one.
First synthesis
The flow is asynchronous: create a job_id, poll it and download audio after done.
API="https://api.sonapro.app"
KEY="sk_user_…"
curl -X POST "$API/v1/tts" \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"text":"Hello!","voice":"vc_xxxxxxxxxx","language":"en","model":"sona-pro"}'
curl "$API/v1/tts/JOB_ID" -H "X-API-Key: $KEY"
curl "$API/v1/tts/JOB_ID/audio" -H "X-API-Key: $KEY" -o out.mp3Endpoints
Base URL: https://api.sonapro.app.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/tts | Create speech → job_id |
| GET | /v1/tts/{job_id} | Job status |
| GET | /v1/tts/{job_id}/audio | Download audio |
| GET | /v1/tts/{job_id}/link | Short public link |
| GET | /v1/tts/{job_id}/subtitles?format=srt|vtt|ass|json|zip | Subtitles; requires subtitles:true |
| GET | /v1/voices?language=en&collection=sona_v1 | Catalog; collection: library or sona_v1 |
| POST | /v1/voices/clone | Clone a voice → tmpl:N |
| GET/POST | /v1/voices/templates | List or create a template |
| PATCH/DEL | /v1/voices/templates/{num} | Edit or delete a template |
| GET | /v1/emotions | Current emotion list |
| GET/POST | /v1/pronunciation | List or save a pronunciation rule |
| DEL | /v1/pronunciation/{term} | Delete a rule |
| GET | /v1/me | Account, tariff and balance |
| POST | /v1/images | Generate an image |
| POST | /v1/images/edit | Generate with image references |
| GET | /v1/images/{image_id}/file | Download PNG/JPEG |
Voices & templates
Each template stores its own parameters.
ID formats and pricing
vc_…Library voice1 credit / charactersona_…SONA Voice v11.5 credits / charactertmpl:NPersonal template/clone1.5 credits / characterBuild a separate first-party picker with GET /v1/voices?collection=sona_v1. Every item in the combined catalog includes collection as sona_v1 or library. Filters compose, for example ?collection=sona_v1&language=uk.
One voice, multiple templates
A template stores its own speed, volume and emotion. The same voice can therefore have Neutral, Angry and Calm presets. The bot asks for them when creating a template and lets you edit them from its template card.
POST /v1/voices/templates
{"engine":"sona","voice":"sona_xxxxxxxxxxxx","name":"Taras · angry",
"speed":1.05,"volume":1.0,"emotion":"angry"}
PATCH /v1/voices/templates/7
{"emotion":"neutral","speed":1.0}A parameter sent explicitly with a synthesis request overrides the template preset for that request only.
Cloning
POST /v1/voices/clone accepts multipart fields clip, name, language, plus optional speed, volume and emotion. Use 3–10 seconds of clean speech without music.
Speech parameters
Fields accepted by POST /v1/tts. An asterisk marks required fields.
| Field | Type / range | Meaning |
|---|---|---|
text * | string | Text to synthesize |
voice * | vc_…, sona_…, tmpl:N | Voice or template |
language | auto, uk, en… | auto uses the voice language |
model | sona-fast / sona-pro / sona-hd | Synthesis model |
format | mp3 | Output format |
bitrate | 32000–192000 | MP3 bitrate; default 96000 |
sample_rate | 8000–48000 | Sample rate; default 44100 |
speed | 0.6–1.5 | SONA/clone speed |
volume | 0.5–2.0 | SONA/clone volume |
emotion | string | One delivery style for the request |
auto_stress | bool, default true | Internal Cyrillic capital vowel → U+0301 |
subtitles | bool | SRT/VTT/ASS and JSON timings |
name | string | Filename without extension |
Template vs request emotion
Using tmpl:N without emotion applies the stored template emotion. Sending emotion:"angry" overrides it for this one request.
Stress, pronunciation & emotions
A clone carries timbre; the model still reads the text. Pronunciation is therefore controlled through text.
Three levels of stress control
| Level | Example | When to use |
|---|---|---|
| 1. U+0301 mark | за́мок / замо́к | First hint for an ambiguous word |
| 2. Capital vowel | зАмок / замОк | Only shorthand: SONA normalizes it to the same U+0301 |
| 3. Phonetic replacement | Тарас → та-РАС | Only after both hints fail and the replacement passes a listening test |
U+0301 and a capital vowel are not independent fallbacks. The latter is merely converted to the former, so a model may ignore both.
Personal SONA dictionary: Cyrillic behavior
This is not a complete pronunciation lexicon or an automatic stress detector. It is an account's list of explicit exceptions: before synthesis SONA finds term in the transcript and literally substitutes replacement. You do not pass a dictionary ID to POST /v1/tts; saved rules are applied automatically.
| Property | SONA behavior |
|---|---|
| Cyrillic | Supported in both term and replacement. Sounds-like guidance may use ordinary Ukrainian or Russian letters. |
| Case | Тарас matches Тарас, тарас and ТАРАС. |
| Boundaries | Only a complete word or complete phrase matches. Тарас does not modify Тараса or Тарасові. |
| Inflections | Save each required word form separately: Тараса → та-РА-са, Тарасові → та-РА-со-ві. These demonstrate the format; listen-test every replacement. |
| Scope | Rules belong to the account, not one voice. They apply in the bot and API to all of its voices and templates. |
| Order | Longer phrases run before shorter words. The limit is 50 rules; term is limited to 60 and replacement to 160 characters. |
Keep a dictionary term in its ordinary spelling inside the script. Do not also add U+0301 or a capital-vowel stress mark: the dictionary runs after stress normalization, so that altered spelling no longer equals the saved term. The substituted text is what synthesis, subtitles and character accounting receive.
# add or update one rule
curl -X POST https://api.sonapro.app/v1/pronunciation \
-H "X-API-Key: $SONA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"term":"Тарас","replacement":"та-РАС"}'
# save inflected forms as separate rules
curl -X POST https://api.sonapro.app/v1/pronunciation \
-H "X-API-Key: $SONA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"term":"Тараса","replacement":"та-РА-са"}'
# list every account rule
curl https://api.sonapro.app/v1/pronunciation \
-H "X-API-Key: $SONA_API_KEY"
# delete a rule; percent-encode Cyrillic in the URL
curl -X DELETE https://api.sonapro.app/v1/pronunciation/%D0%A2%D0%B0%D1%80%D0%B0%D1%81 \
-H "X-API-Key: $SONA_API_KEY"Use it for names, brands, abbreviations and terms that are consistently mispronounced. If U+0301 solves a stress-only issue, a dictionary rule is unnecessary. Sounds-like spelling guides rather than guarantees pronunciation, so test a short take in the intended language first.
Verified rule: Тарас
For the Ukrainian Taras voice, the model said ТАрас and ignored the stress mark. The listen-tested та-РАС replacement produced the intended ТарАс.
curl -X POST https://api.sonapro.app/v1/pronunciation \
-H "X-API-Key: $SONA_API_KEY" -H "Content-Type: application/json" \
-d '{"term":"Тарас","replacement":"та-РАС"}'The rule matches a whole word, case-insensitively, for every synthesis on this API account. Never syllabify an entire script or invent IPA; listen-test each exception first.
Prompt for Claude / ChatGPT
Put this prompt before a script. The AI will inspect the whole text—not only the word “Тарас”—and return SONA-ready text.
You edit text for SONA speech synthesis.
Analyze the complete text in context and prepare it for natural machine narration.
Rules:
1. Preserve meaning, style, facts and language.
2. Keep natural punctuation and paragraphs; they control pauses.
3. Find words that a TTS engine may pronounce incorrectly. Pay special attention to:
- given names and surnames;
- place names;
- brands, products and company names;
- abbreviations;
- foreign words and loanwords;
- rare terms and homographs.
4. If only the stress is ambiguous, place U+0301 after the stressed vowel:
за́мок / замо́к, му́ка / мука́.
5. If a stress mark may be insufficient and you know the correct pronunciation with
high confidence, rewrite ONLY the problematic word phonetically:
- split it into readable parts with hyphens;
- write the stressed syllable in UPPERCASE;
- preserve the grammatical ending of the word form used in the text.
6. Do not limit the analysis to “Тарас”. Detect other risky words from context, but
do not invent a pronunciation when uncertain.
7. Format examples:
- Тарас → та-РАС
- OpenAI → оупен-ей-АЙ
- ChatGPT → чат-джі-пі-ТІ
- Renault → ре-НО
8. Do not syllabify ordinary words, insert IPA, or rewrite the entire script
phonetically. Preserve existing <emotion value="..."/> tags unchanged.
9. Return only the narration-ready text, without explanations, lists or comments.
My text:
"""
[PASTE TEXT]
"""Emotions in text
emotion selects one style for the whole request. Inline tags are a beta way to change it inside text.
<emotion value="excited"/> You will not believe what I learned!
<emotion value="sad"/> But then everything went wrong…
<emotion value="determined"/> We still will not give up.Full list · 58 emotions
neutral, happy, excited, enthusiastic, elated, euphoric, triumphant, amazed, surprised, flirtatious, curious, content, peaceful, serene, calm, grateful, affectionate, trust, sympathetic, anticipation, mysterious, angry, mad, outraged, frustrated, agitated, threatened, disgusted, contempt, envious, sarcastic, ironic, sad, dejected, melancholic, disappointed, hurt, guilty, bored, tired, rejected, nostalgic, wistful, apologetic, hesitant, insecure, confused, resigned, anxious, panicked, alarmed, scared, proud, confident, distant, skeptical, contemplative, determined
Image generation
Generate from text or from image references.
POST /v1/images | JSON: prompt, model, size, quality → image_id |
POST /v1/images/edit | multipart: prompt, model, 1–3 image files |
GET /v1/images/{image_id} | Job status |
GET /v1/images/{image_id}/file | Download file |
GET /v1/images?limit=20 | Account history |
Example
curl -X POST https://api.sonapro.app/v1/images \
-H "X-API-Key: $SONA_API_KEY" -H "Content-Type: application/json" \
-d '{"prompt":"A cinematic Crimean coast at sunrise","model":"sona-image","size":"1536x1024","quality":"high"}'Results & errors
Poll the status endpoint until a terminal state.
Job lifecycle
queued→processing→donequeued→processing→errorPoll every 1–2 seconds. Download audio, subtitles or images only after done.
HTTP codes
400 / 422 | Invalid input, unsupported voice, language or format |
401 | Missing, invalid or revoked API key |
402 | Insufficient credits |
404 | Job, template or file not found |
429 | Rate limit; retry after a delay |
503 | Engine is temporarily paused; show the returned maintenance message |