Dokumentacja
API v1 — endpointy
GET/api/v1/voicesKatalog głosów: id, język, płeć, styl, licencja, próbka
GET/api/v1/voices/{voice}/avatarAwatar głosu (przesłany obraz lub wygenerowany gradient)
GET/api/v1/languagesObsługiwane języki: kod, nazwa, poziom, liczba głosów
POST/api/v1/ttsSynteza mowy → WAV lub MP3 (parametr format)
POST/api/v1/tts_streamSynteza strumieniowa (chunked PCM) dla niskich opóźnień — czysty strumień bez efektów post i bez mp3
POST/api/v1/voices/createUtwórz głos: name, audio_b64 (≤10 MB base64), ref_text (=audio słowo w słowo), consent="voice-data-consent,privacy", language? → voice id
GET/api/v1/voices/mineTwoje własne głosy (utworzone klony + kupione): voice (slug), name, language, kind, sample_url — wymagany klucz API
POST/api/v1/transcribeTranskrybuj krótki fragment: audio_b64, language? (pełna nazwa) → tekst. Czas trwania wlicza się do miesięcznego limitu minut transkrypcji planu
GET/api/v1/statusGotowość silnika (agenci w czasie rzeczywistym): ready, model_ready, engine_up, latency_ms
POST/api/v1/warmupRozgrzej silnik przed sesją połączenia (bez naliczania znaków)
GET /api/v1/voices — filtry: q (wyszukiwanie po nazwie/stylu), language (ru, en, de…), gender (male/female), limit (domyślnie 200, maks. 500), offset. Przekaż pole voice z odpowiedzi do POST /tts.
# GET /api/v1/voices?language=ru&gender=male&limit=200
{
"object": "list",
"total": 152,
"count": 152,
"voices": [
{
"voice": "de_at_f1",
"name": "Greta",
"language": "de-AT",
"gender": "female",
"style": "Jung",
"license": "commercial",
"badge": null, // null | "beta" | "soon" (soon = synthesis disabled)
"sample_url": "https://hancvoice.com/api/v1/voices/de_at_f1/sample", // permanent link, redirects to the current file
"avatar_url": "https://hancvoice.com/api/v1/voices/de_at_f1/avatar"
}
]
}
Awatary & języki. Avatar: 302 do obrazu lub gradient SVG — wstaw go bezpośrednio do <img>. Języki: tier = main (ready) | beta | soon.
# GET /api/v1/languages — supported languages (code, name, tier, voice count)
{
"object": "list",
"total": 24,
"languages": [
{
"code": "de",
"name": "German",
"native_name": "Deutsch",
"tier": "main",
"voice_count": 32
}
]
}
# GET /api/v1/voices/{voice}/avatar → 302 to image, or a generated SVG. Use directly in <img src>.
<img src="https://hancvoice.com/api/v1/voices/de_at_f1/avatar" width="64" />
Dostęp
Uwierzytelnianie
Wszystkie endpointy wymagają klucza API: nagłówka X-API-Key: <key> albo Authorization: Bearer <key> (z wyjątkiem GET /api/v1/voices, GET /api/v1/status, GET /api/v1/languages oraz GET /api/v1/voices/{voice}/avatar — otwarte). Klucz tworzysz w swoim koncie → sekcja „API”; API jest dostępne od planu Starter wzwyż (w przeciwnym razie 403). Synteza obciąża znaki planu przypisanego do klucza — przy zerowym saldzie zwraca 402. Limit zapytań zależy od planu: Starter — 30 żądań/min, Pro — 120, Business — 300, Scale — 600 (fallback 60); po przekroczeniu → 429, nagłówek Retry-After.
POST /api/v1/tts
Parametry
voiceID głosu z GET /api/v1/voices. ⚠️ Jeśli pole jest puste, synteza użyje domyślnego głosu (de_at_n1) i znaki nadal zostaną naliczone — zawsze podawaj ID jawnie.
texttekst do głosu; maksymalna długość zależy od planu przypisanego do klucza (wymagane)
languagede, en, ru, fr, es, it, pt, zh, ja, ko (także de-DE, en-US …) oraz pełne nazwy (German, English …). Plus Auto: silnik wykrywa język z tekstu — jedyny sposób, by wygenerować język beta własnym głosem.
instructemocja/styl po angielsku, np. "calm, friendly" (opc.)
emotionemocja głosu studio (dla głosów z nagranymi referencjami emocji): joyful, excited, tender, calm, sad, serious, tense, angry, afraid, surprised (opc.; bez parametru — neutral)
saturationnasycenie/ harmoniczne „kolorowanie” barwy głosu (post-processing): {"preset":"tube"|"tape"|"air","intensity":0–1} (opc.)
speedtempo mowy 0.5–2.0 (opc.) Wartości poza zakresem są ograniczane do najbliższej granicy; odpowiedź zawiera wtedy X-Effects-Failed: speed_clamped_to_….
gain_dbgłośność −24…+24 dB (opc.)
eqequalizer barwy głosu: {"bands":[{"hz":80,"db":4}, …]} (opc.)
effectpreset dźwięku: radio, audiobook, podcast, phone, cinematic, megaphone, vintage, deep, bright, warm, narrator_warm, intimate, spacious, whisper, concert; characters: robot, cartoon, chipmunk, monster, villain, echo_hall; studio: studio_announcer, studio_natural, studio_rich. Efekty premium (characters, studio, cinematic, concert, megaphone, vintage) — tylko w płatnych planach, w przeciwnym razie ignorowane (opc.)
seedliczba do deterministycznego powtórzenia tego samego voiceoveru (opc.)
cleantrue — neuralne odszumianie (oddzielnie od effect, opc.)
backgroundtło/ambiente: rain, thunder, sea, forest, birds, wind, stream, night, street, cafe, crowd, fire (opc.)
bg_levelgłośność tła 0.05–0.8 (opc., domyślnie 0.25)
lead_silence_mscisza na początku audio, ms (opc., dla agentów; domyślnie 0)
format„wav” (domyślnie) lub „mp3” (opc.)
response_formatWyjście telefoniczne (B2B/IVR): g711_alaw_8k, g711_ulaw_8k, g722_16k, opus, pcm_s16le_24k. Odpowiedź to strumień kodeka + nagłówek X-Audio-Format (opc.)
containertylko z response_format: wav (kontener, domyślnie) lub raw (surowe ramki dla SIP/RTP) (opc.)
Odpowiedź to binarny plik audio: audio/wav lub audio/mpeg (jeśli format=mp3); dla telephony response_format — odpowiedni kontener kodeka (zob. X-Audio-Format).
POST /api/v1/tts_stream
Synteza strumieniowa
Przyjmuje voice, text, language, instruct, speed, gain_db, eq, effect, background, bg_level, saturation, seed i segments (do 40 elementów: text, instruct do 200 znaków, silence 0–3000 ms). Odpowiedź: surowy PCM — 24 kHz, 16-bit, mono, little-endian (application/octet-stream, chunked); nie ma nagłówka WAV, ustaw samodzielnie częstotliwość próbkowania.
# POST /api/v1/tts_stream → PCM stream (application/octet-stream, chunked)
{
"voice": "de_at_f1",
"text": "Hallo! Das ist Streaming-Synthese.",
"language": "de"
}
POST /api/v1/voices/create
Tworzenie głosu
namenazwa głosu (wymagane)
audio_b64próbka nagrania w base64, ≤10 MB (wymagane)
ref_textTranskrypcja nagrania — słowo w słowo, maks. 2000 znaków (dłuższa → 400 ref_text_too_long). Jeśli tekst nie zgadza się z audio, głos brzmi zniekształcone.
consentciąg zgody — podaj dokładnie "voice-data-consent,privacy" (dane głosowe, GDPR); bez tego — 400 (wymagane)
languagejęzyk próbki, pełna nazwa (rosyjski, angielski…) lub kod ISO; domyślnie niemiecki (opc.)
Przekaż pole voice z odpowiedzi do POST /tts. Wartość voice poniżej to przykład ilustracyjny; prawdziwy identyfikator pojawia się w odpowiedzi. Tworzenie własnego głosu jest dostępne w płatnym planie; liczba własnych głosów jest nieograniczona — utworzenie jednego kosztuje 10.000 znaków z Twojego salda (przechowywanie i używanie jest bezpłatne).
# Response — 200 OK (voice value is an example)
{
"ok": true,
"voice": "usr_a1b2c3",
"name": "My voice",
"language": "German"
}
GET /api/v1/voices/mine
Twoje własne głosy
GET /api/v1/voices zwraca tylko publiczny katalog. Aby dostać TWOJE własne głosy — zarówno utworzone przez API, jak i wygenerowane na Twoim koncie/w studiu — uwierzytelnij się kluczem API i wywołaj ten endpoint. Zwraca Twoje własne klony (kind="own") oraz głosy kupione na Marketplace (kind="marketplace"). Przekaż pole voice (slug) do POST /api/v1/tts.
# GET /api/v1/voices/mine — your own voices (API key required)
curl https://hancvoice.com/api/v1/voices/mine \
-H "X-API-Key: $HANCVOICE_KEY"
# Response — 200 OK
{
"object": "list",
"count": 1,
"voices": [
{
"voice": "usr_a1b2c3",
"name": "My voice",
"language": "German",
"gender": null,
"kind": "own",
"sample_url": "https://hancvoice.com/voice-samples/usr_a1b2c3.wav",
"avatar_url": "https://hancvoice.com/generated-audio/voice-avatars/usr_a1b2c3.webp"
}
]
}
gender ma wartość null dla własnych głosów (nie jest zapisywane); sample_url może mieć wartość null, jeśli nie ma próbki. Podczas syntezy własnym głosem język jest pobierany z głosu i zastępuje parametr language w POST /tts.
Pełny flow do kopiuj-wklej — utwórz, wyświetl, syntezuj (zamień klucz przykładowy na własny z Konto → API):
# Full own-voice flow — create → list (mine) → synthesize.
# Example key below — replace it with your own key from Account → API.
KEY="sk-live-9f3c1a7b4e2d8c6f0a5b3e1d7c9f2a4b6d8e0c1a3f5b7d9e"
# 1) Create your voice (skip if you already have one in your account)
curl -X POST https://hancvoice.com/api/v1/voices/create \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"name":"My voice","ref_text":"exact transcript of the recording","audio_b64":"<24kHz sample, base64>","consent":"voice-data-consent,privacy"}'
# → {"ok":true,"voice":"usr_a1b2c3","name":"My voice","language":"German"}
# 2) List your own voices → take the "voice" (slug)
curl https://hancvoice.com/api/v1/voices/mine -H "X-API-Key: $KEY"
# 3) Synthesize with your voice
curl -X POST https://hancvoice.com/api/v1/tts \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"voice":"usr_a1b2c3","text":"Hallo, das ist meine eigene Stimme.","language":"de"}' --output out.wav
POST /api/v1/transcribe
Transkrypcja
audio_b64audio w base64; przeznaczone dla krótkiego fragmentu (wymagane)
languagetylko PEŁNA nazwa języka: Russian, English, German, French, Italian, Spanish, Portuguese, Chinese, Japanese, Korean — plus 14 języków beta (Bulgarian, Czech, Greek, Ukrainian, Polish i inne) jako wskazówka rozpoznawania, oraz dosłowne „auto” (kody ISO NIE są tu akceptowane, w przeciwieństwie do /tts; bez parametru — auto-detect) (opc.)
Znaki są rozliczane zgodnie z planem (≈ 1 min audio = 1000 znaków); obowiązuje miesięczny limit minut transkrypcji planu.
# Response — language = vom Engine erkannter ISO-Code (z. B. de, en, ru)
{
"text": "Transkribierter Text des Fragments.",
"language": "de"
}
GET /api/v1/status · POST /api/v1/warmup
Status i rozgrzewanie
GET /api/v1/status (bez klucza) — gotowość silnika do pracy w czasie rzeczywistym. POST /api/v1/warmup (z kluczem; NIE nalicza znaków) rozgrzewa silnik przed serią wywołań.
# GET /api/v1/status
{
"ready": true,
"model_ready": true,
"engine_up": true,
"latency_ms": 42
}
# POST /api/v1/warmup
{
"ok": true,
"warmed": true,
"warm_ms": 318
}
Odpowiedź
Nagłówki i pole code
Content-Typeaudio/wav lub audio/mpeg (zgodnie z parametrem formatu); dla /tts_stream — application/octet-stream
X-Effects-Failedefekty, które NIE zostały zastosowane (w silniku lub obcięte przez plan), oddzielone przecinkami — audio wraca bez nich
X-CacheHIT / MISS — czy odpowiedź pochodzi z pamięci podręcznej. Uwaga: z kluczem API HIT jest rozliczany jak MISS (cache oszczędza czas generowania, nie znaki).
Retry-Afterprzy 429 — po ilu sekundach ponowić żądanie
Pole code w treści błędu (czytelne maszynowo): plan_required — potrzebny wyższy plan; voice_limit — limit głosów planu; plan_quota — wyczerpano miesięczny limit minut transkrypcji; email_unverified — zweryfikuj swój e-mail; voice_conflict — nazwa głosu jest już zajęta (przy tworzeniu głosu).
Kody odpowiedzi
Błędy
200Sukces — treść odpowiedzi zawiera plik audio
400Uszkodzony JSON lub pusty tekst. Nieznany język zwraca 4xx silnika (np. 400) z kodem engine_bad_request — tak samo dla /v1/tts i /v1/tts_stream
401Brak lub nieprawidłowy klucz API (nagłówek X-API-Key / Authorization)
402Za mało znaków na saldzie klucza — doładuj plan
403Funkcja jest niedostępna w bieżącym planie (np. API — od Starter, własny głos — z płatnego planu) albo brak dostępu do głosu
409Konflikt (voice_conflict): głos o tej nazwie już istnieje — wybierz inną nazwę przy tworzeniu głosu
413Plik jest za duży: dla głosu niestandardowego audio ma >10 MB (base64)
429Przekroczono limit żądań (wg planu: Starter 30, Pro 120, Business 300, Scale 600 na minutę; /voices/create 5/min, /warmup 20/min). Uwzględnij nagłówek Retry-After. Kod: rate_limited.
500Błąd wewnętrzny (np. baza danych jest niedostępna przy GET /v1/voices) — spróbuj później.
502Silnik syntezy/transkrypcji nie odpowiedział (Bad Gateway) — odczekaj chwilę i spróbuj ponownie
503Silnik jest uśpiony/niedostępny albo usługa jest przeciążona — spróbuj ponownie za kilka sekund
Treść błędu to JSON { "error": "description", "code": "machine-readable" }. Możliwe wartości code: auth_required, plan_required, rate_limited, no_credits, voice_create_credits, bad_request, empty_text, text_too_long, ref_text_too_long, name_too_long, voice_limit, voice_conflict, voice_access, plan_quota, no_audio, engine_busy, engine_unavailable, engine_error, billing_unavailable, temporarily_unavailable. W razie niepowodzenia żadne znaki nie są naliczane — z wyjątkiem sytuacji, gdy klient przerwie stream (dostarczony dźwięk jest rozliczany proporcjonalnie).
Wszystkie kody błędów
Pełna lista kodów maszynowych w polu code: auth_required (401) · plan_required (403, API ze Starter) · text_too_long, bad_request, name_required, ref_text_required, ref_text_too_long, name_too_long, audio_b64_required, consent_required, voice_required (400) · voice_access · voice_not_found (404) · no_credits (402) · body_too_large, audio_too_large (413) · rate_limited (429, z Retry-After) · engine_bad_request (engine 4xx) · engine_error, engine_unavailable, engine_not_configured, temporarily_unavailable, mp3_failed, telephony_failed, transcribe_failed (5xx) · client_abort (499, klient rozłączył połączenie).
Drobny druk
Praktyczne szczegóły, które łatwo przeoczyć: treść żądania jest ograniczona do 2 MB dla /v1/tts i /v1/tts_stream (w przeciwnym razie 413) oraz do 30 MB base64 dla /v1/transcribe · speaker jest synonimem voice · znacznik pauzy ‖ (U+2016) umieszczony w tekście daje dokładnie 400 ms ciszy · instruct jest cicho przycinane do 500 znaków i lead_silence_ms jest ograniczone do 5000 · bez seed używana jest wartość 4242, więc domyślnie wynik jest powtarzalny (zmień seed sam, jeśli chcesz wariacji) · bez language zakładany jest niemiecki · GET /v1/languages akceptuje ?locale · limit jest liczony osobno dla każdego endpointu; własne limity: /voices/create 5/min, /warmup 20/min, /voices/mine 60/min, otwarte endpointy GET 120/min na IP · POST /v1/voices/clone jest aliasem /voices/create.
Katalog
Efekty i tła
Parametr effect — jeden preset na żądanie. Darmowe są dostępne dla wszystkich; premium — w płatnych planach.
Dostarczanie (darmowe)radio — suche nadawanie · audiobook — audiobook · narrator_warm — ciepły narrator · podcast — podcast · phone — telefon · intimate — blisko · spacious — przestrzennie · whisper — szept · deep — niżej · bright — jaśniej · warm — cieplej
Studio (premium)studio_announcer — zapowiedź studyjna · studio_natural — naturalne studio · studio_rich — bogate „droższe” · cinematic — kino · concert — sala · megaphone — megafon · vintage — vintage
Postacie (premium)robot — robot · cartoon — kreskówkowy · chipmunk — wiewiórka · monster — potwór · villain — złoczyńca · echo_hall — echo w sali
Tła (tło)Natura: rain (deszcz) · thunder (burza) · sea (morze) · forest (las) · birds (ptaki) · wind (wiatr) · stream (strumień) · night (noc). Miasto: street (ulica) · cafe (kawiarnia) · crowd (tłum). Przytulnie: fire (kominek). Głośność — bg_level 0.05–0.8
eq (barwa)8 pasm: 80, 160, 300, 600, 1500, 3500, 6500, 10500 Hz, każde −12…+12 dB. Przykład: {"bands":[{"hz":80,"db":-4},{"hz":3500,"db":3}]} — usuń dudnienie, dodaj klarowność
Limity
Limity
Tempo żądańzgodnie z planem klucza: Starter — 30/min, Pro — 120/min, Business — 300/min, Scale — 600/min. Endpointy z własnym twardym limitem, niezależnie od planu: POST /v1/voices/create — 5/min, POST /v1/warmup — 20/min, GET /v1/status — 60/min na IP, GET /v1/voices — 120/min na IP.
Długość tekstumaksymalna liczba znaków na POST /api/v1/tts zależy od planu klucza
Saldo znakówsynteza zużywa znaki z planu klucza; przy saldzie zero — 402
Transkrypcja≈1 min audio = 1000 znaków; obowiązują miesięczne minuty planu: Pro 100, Business 300, Scale 800 min. Free i Starter NIE obejmują transkrypcji — API zwraca 403 (plan_required). Wyczerpany limit → 403 (plan_quota).
Rozmiar plikutworzenie głosu: próbka ≤10 MB (base64), w przeciwnym razie 413
Przykład
Pełne żądanie
POST /api/v1/tts
{
"voice": "cml_de",
"text": "Heute ist das Wetter wunderbar.",
"language": "de",
"instruct": "calm, friendly",
"speed": 1.0,
"effect": "podcast",
"eq": { "bands": [ { "hz": 3500, "db": 3 } ] },
"background": "rain",
"bg_level": 0.2,
"format": "mp3"
}
→ 200 OK, Content-Type: audio/mpeg (binary file)