Referenz
API v1 — Endpunkte
GET/api/v1/voicesStimmenkatalog: id, Sprache, Geschlecht, Stil, Lizenz, Beispiel
GET/api/v1/voices/{voice}/avatarStimmen-Avatar (hochgeladenes Bild oder generierter Verlauf)
GET/api/v1/languagesUnterstützte Sprachen: Code, Name, Tier, Stimmenzahl
POST/api/v1/ttsSprachsynthese → WAV oder MP3 (Parameter format)
POST/api/v1/tts_streamStreaming-Synthese (chunked PCM) für niedrige Latenz — reiner Stream ohne Post-Effekte und ohne mp3
POST/api/v1/voices/createStimme erstellen: name, audio_b64 (≤10 MB base64), ref_text (=Audio Wort für Wort), consent="voice-data-consent,privacy", language? → voice id
GET/api/v1/voices/mineIhre eigenen Stimmen (erstellte Klone + gekaufte): voice (slug), name, language, kind, sample_url — API-Schlüssel erforderlich
POST/api/v1/transcribeTranskription eines kurzen Fragments: audio_b64, language? (voller Name) → Text. Die Dauer zählt zum monatlichen Transkriptionsminuten-Limit des Tarifs
GET/api/v1/statusEngine-Bereitschaft (Echtzeit-Agenten): ready, model_ready, engine_up, latency_ms
POST/api/v1/warmupEngine vor einer Anrufsitzung aufwärmen (ohne Zeichen abzurechnen)
GET /api/v1/voices — Filter: q (Suche nach Name/Stil), language (ru, en, de…), gender (male/female), limit (Standard 200, max. 500), offset. Übergeben Sie das Feld voice aus der Antwort an 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"
}
]
}
Avatare & Sprachen. Avatar: 302 zum Bild oder ein SVG-Verlauf — direkt in <img> nutzbar. Sprachen: tier = main (bereit) | 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" />
Zugang
Authentifizierung
Alle Endpunkte benötigen einen API-Schlüssel: den Header X-API-Key: <Schlüssel> oder Authorization: Bearer <Schlüssel> (außer GET /api/v1/voices, GET /api/v1/status, GET /api/v1/languages und GET /api/v1/voices/{voice}/avatar — offen). Der Schlüssel wird im Konto erstellt → Bereich „API“; die API ist ab dem Starter-Tarif und höher verfügbar (sonst 403). Die Synthese rechnet Zeichen vom Tarif des Schlüssels ab — bei Null-Guthaben wird 402 zurückgegeben. Ratenlimit nach Tarif: Starter — 30 Anfragen/Min., Pro — 120, Business — 300, Scale — 600 (Fallback 60); Überschreitung → 429, Header Retry-After.
POST /api/v1/tts
Parameter
voiceStimmen-ID aus GET /api/v1/voices. ⚠️ Ohne dieses Feld synthetisiert der Dienst mit der Standardstimme (de_at_n1) und bucht Zeichen ab — die ID immer explizit angeben.
textzu vertonender Text; die max. Länge hängt vom Tarif des Schlüssels ab (erforderlich)
languagede, en, ru, fr, es, it, pt, zh, ja, ko (auch de-DE, en-US …) sowie vollständige Namen (German, English …). Zusätzlich Auto: Die Engine erkennt die Sprache am Text — der einzige Weg, mit einer eigenen Stimme in einer Beta-Sprache zu synthetisieren.
instructEmotion/Stil auf Englisch, z. B. "calm, friendly" (opt.)
emotionEmotion einer Studiostimme (für Stimmen mit aufgenommenen Emotions-Referenzen): joyful, excited, tender, calm, sad, serious, tense, angry, afraid, surprised (opt.; ohne Parameter — neutral)
saturationSättigung/harmonische „Einfärbung“ des Timbres (Nachbearbeitung): {"preset":"tube"|"tape"|"air","intensity":0–1} (opt.)
speedSprechtempo 0.5–2.0 (opt.) Werte außerhalb des Bereichs werden auf die nächste Grenze begrenzt; die Antwort trägt dann X-Effects-Failed: speed_clamped_to_….
gain_dbLautstärke −24…+24 dB (opt.)
eqTimbre-Equalizer: {"bands":[{"hz":80,"db":4}, …]} (opt.)
effectKlang-Preset: radio, audiobook, podcast, phone, cinematic, megaphone, vintage, deep, bright, warm, narrator_warm, intimate, spacious, whisper, concert; Charaktere: robot, cartoon, chipmunk, monster, villain, echo_hall; Studio: studio_announcer, studio_natural, studio_rich. Premium-Effekte (Charaktere, Studio, cinematic, concert, megaphone, vintage) — nur in kostenpflichtigen Tarifen, sonst ignoriert (opt.)
seedeine Zahl für eine deterministische Wiederholung derselben Vertonung (opt.)
cleantrue — neuronale Rauschunterdrückung (getrennt von effect, opt.)
backgroundHintergrund/Atmosphäre: rain, thunder, sea, forest, birds, wind, stream, night, street, cafe, crowd, fire (opt.)
bg_levelHintergrundlautstärke 0.05–0.8 (opt., Standard 0.25)
lead_silence_msStille am Anfang des Audios, ms (opt., für Agenten; Standard 0)
format"wav" (Standard) oder "mp3" (opt.)
response_formatTelefonie-Ausgabe (B2B/IVR): g711_alaw_8k, g711_ulaw_8k, g722_16k, opus, pcm_s16le_24k. Die Antwort ist der Codec-Stream + Header X-Audio-Format (opt.)
containernur mit response_format: wav (Container, Standard) oder raw (rohe Frames für SIP/RTP) (opt.)
Die Antwort ist eine binäre Audiodatei: audio/wav oder audio/mpeg (wenn format=mp3); bei Telefonie-response_format der jeweilige Codec-Container (siehe X-Audio-Format).
POST /api/v1/tts_stream
Streaming-Synthese
Akzeptiert voice, text, language, instruct, speed, gain_db, eq, effect, background, bg_level, saturation, seed sowie segments (bis 40 Elemente: text, instruct bis 200 Zeichen, silence 0–3000 ms). Antwort: roher PCM — 24 kHz, 16 Bit, mono, little-endian (application/octet-stream, chunked); ohne WAV-Kopf — Abtastrate selbst setzen.
# 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
Stimme erstellen
nameStimmenname (erforderlich)
audio_b64Beispielaufnahme in base64, ≤10 MB (erforderlich)
ref_textTranskript der Aufnahme — Wort für Wort, max. 2000 Zeichen (länger → 400 ref_text_too_long). Weicht der Text vom Audio ab, klingt die Stimme unverständlich.
consentZustimmungs-String — übergeben Sie genau "voice-data-consent,privacy" (Stimmdaten, DSGVO); ohne ihn — 400 (erforderlich)
languageSprache des Beispiels, voller Name (Russian, English…) oder ISO-Code; Standard German (opt.)
Übergeben Sie das Feld voice aus der Antwort an POST /tts. Der Wert voice unten ist ein illustratives Beispiel; die echte Kennung kommt in der Antwort. Das Erstellen einer eigenen Stimme ist ab einem kostenpflichtigen Tarif verfügbar; die Anzahl eigener Stimmen ist unbegrenzt — die Erstellung kostet 10.000 Zeichen aus dem Guthaben (Speicherung und Nutzung sind kostenlos).
# Response — 200 OK (voice value is an example)
{
"ok": true,
"voice": "usr_a1b2c3",
"name": "My voice",
"language": "German"
}
GET /api/v1/voices/mine
Ihre eigenen Stimmen
GET /api/v1/voices liefert nur den öffentlichen Katalog. Um Ihre EIGENEN Stimmen zu erhalten — sowohl per API erstellte als auch die in Ihrem Konto/Studio generierten — authentifizieren Sie sich mit dem API-Schlüssel und rufen Sie diesen Endpunkt auf. Er gibt Ihre eigenen Klone (kind="own") und auf dem Marketplace gekaufte Stimmen (kind="marketplace") zurück. Übergeben Sie das Feld voice (slug) an 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 ist bei eigenen Stimmen null (nicht gespeichert); sample_url kann null sein, wenn kein Beispiel vorliegt. Beim Synthetisieren mit einer eigenen Stimme wird die Sprache aus der Stimme genommen und überschreibt den Parameter language in POST /tts.
Vollständiger Ablauf zum Kopieren — erstellen, auflisten, synthetisieren (den Beispiel-Schlüssel durch Ihren eigenen aus „Konto → API“ ersetzen):
# 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
Transkription
audio_b64Audio in base64; ausgelegt für ein kurzes Fragment (erforderlich)
languagenur der VOLLE Sprachname: Russian, English, German, French, Italian, Spanish, Portuguese, Chinese, Japanese, Korean — plus 14 Beta-Sprachen (Bulgarisch, Tschechisch, Griechisch, Ukrainisch, Polnisch u. a.) als Erkennungshinweis, sowie das Literal "auto" (ISO-Codes werden hier NICHT akzeptiert, anders als bei /tts; ohne Parameter — automatische Erkennung) (opt.)
Zeichen werden nach Tarif abgerechnet (≈1 Min. Audio = 1000 Zeichen); das monatliche Transkriptionsminuten-Limit des Tarifs gilt.
# 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 und Aufwärmen
GET /api/v1/status (ohne Schlüssel) — Engine-Bereitschaft für Echtzeit. POST /api/v1/warmup (mit Schlüssel; rechnet KEINE Zeichen ab) wärmt die Engine vor einer Anrufserie auf.
# 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
}
Antwort
Header und das Feld code
Content-Typeaudio/wav oder audio/mpeg (je nach Parameter format); für /tts_stream — application/octet-stream
X-Effects-FailedEffekte, die NICHT angewendet wurden (an der Engine oder vom Tarif gekappt), kommagetrennt — das Audio kommt ohne sie zurück
X-CacheHIT / MISS — ob die Antwort aus dem Cache kam. Hinweis: Bei einem API-Schlüssel wird ein Cache-HIT wie ein MISS abgerechnet (der Cache spart Generierungszeit, nicht Zeichen).
Retry-Afterbei 429 — nach wie vielen Sekunden die Anfrage zu wiederholen ist
Das Feld code im Fehlerkörper (maschinenlesbar): plan_required — ein höherer Tarif ist nötig; voice_limit — das Stimmenlimit des Tarifs; plan_quota — das monatliche Transkriptionsminuten-Limit ist aufgebraucht; email_unverified — bestätigen Sie Ihre E-Mail; voice_conflict — der Stimmenname ist bereits vergeben (beim Erstellen einer Stimme).
Antwortcodes
Fehler
200Erfolg — der Antwortkörper enthält die Audiodatei
400Kaputtes JSON oder leerer Text. Eine der Engine unbekannte Sprache liefert den 4xx-Status der Engine (z. B. 400) mit Code engine_bad_request — gleich bei /v1/tts und /v1/tts_stream
401Fehlender oder ungültiger API-Schlüssel (Header X-API-Key / Authorization)
402Nicht genügend Zeichen im Guthaben des Schlüssels — Tarif aufladen
403Die Funktion ist im aktuellen Tarif nicht verfügbar (z. B. API — ab Starter, Transkription — ab Pro) oder kein Zugriff auf die Stimme
409Konflikt (voice_conflict): eine Stimme mit diesem Namen existiert bereits — wählen Sie beim Erstellen einen anderen Namen
413Datei zu groß: für eine eigene Stimme ist das Audio >10 MB (base64)
429Anfragelimit überschritten (Tarif: Starter 30, Pro 120, Business 300, Scale 600 pro Minute; für /voices/create 5/Min., /warmup 20/Min.). Header Retry-After beachten. Code: rate_limited.
500Interner Fehler (z. B. Datenbank nicht erreichbar bei GET /v1/voices) — später erneut versuchen.
502Der Synthese-/Transkriptions-Motor hat nicht geantwortet (Bad Gateway) — kurz warten und erneut versuchen
503Die Engine schläft/ist nicht verfügbar oder der Dienst ist überlastet — in einigen Sekunden erneut versuchen
Der Fehler-Body ist JSON { "error": "Beschreibung", "code": "maschinenlesbar" }. Mögliche code-Werte: 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. Bei Misserfolg werden keine Zeichen abgebucht — Ausnahme: Abbruch des Streams durch den Client (anteilige Abrechnung des gelieferten Audios).
Alle Fehlercodes
Vollständige Liste der Maschinen-Codes im Feld code: auth_required (401) · plan_required (403, API ab 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, mit Retry-After) · engine_bad_request (4xx der Engine) · engine_error, engine_unavailable, engine_not_configured, temporarily_unavailable, mp3_failed, telephony_failed, transcribe_failed (5xx) · client_abort (499, Verbindung vom Client abgebrochen).
Feinheiten
Praktische Details, die man leicht übersieht: Anfragekörper bei /v1/tts und /v1/tts_stream max. 2 MB (sonst 413), bei /v1/transcribe max. 30 MB base64 · speaker ist ein Synonym für voice · der Pausenmarker ‖ (U+2016) direkt im Text ergibt exakt 400 ms Stille · instruct wird still auf 500 Zeichen gekürzt, lead_silence_ms auf 5000 begrenzt · ohne seed wird 4242 gesetzt, die Ausgabe ist also standardmäßig reproduzierbar (für Variation den Seed selbst wechseln) · ohne language gilt Deutsch · GET /v1/languages versteht ?locale · das Ratenlimit gilt pro Endpunkt getrennt; eigene Limits: /voices/create 5/Min., /warmup 20/Min., /voices/mine 60/Min., offene GET-Endpunkte 120/Min. je IP · POST /v1/voices/clone ist ein Alias von /voices/create.
Katalog
Effekte und Hintergründe
Der Parameter effect — ein Preset pro Anfrage. Kostenlose sind für alle verfügbar; Premium — in kostenpflichtigen Tarifen.
Vortrag (free)radio — trockener Äther · audiobook — Hörbuch · narrator_warm — warmer Erzähler · podcast — Podcast · phone — Telefon · intimate — nah · spacious — weiträumig · whisper — Flüstern · deep — tiefer · bright — heller · warm — wärmer
Studio (Premium)studio_announcer — Sprecher-Äther · studio_natural — natürliches Studio · studio_rich — satt „teuer“ · cinematic — Kino · concert — Saal · megaphone — Megafon · vintage — Vintage
Charaktere (Premium)robot — Roboter · cartoon — cartoonhaft · chipmunk — Streifenhörnchen · monster — Monster · villain — Bösewicht · echo_hall — Echohalle
Hintergründe (background)Natur: rain (Regen) · thunder (Gewitter) · sea (Meer) · forest (Wald) · birds (Vögel) · wind (Wind) · stream (Bach) · night (Nacht). Stadt: street (Straße) · cafe (Café) · crowd (Menge). Gemütlich: fire (Kamin). Lautstärke — bg_level 0.05–0.8
eq (Timbre)8 Bänder: 80, 160, 300, 600, 1500, 3500, 6500, 10500 Hz, je −12…+12 dB. Beispiel: {"bands":[{"hz":80,"db":-4},{"hz":3500,"db":3}]} — Dröhnen entfernen, Klarheit hinzufügen
Kontingente
Limits
Anfragerategemäß Tarif des Schlüssels: Starter — 30/Min., Pro — 120/Min., Business — 300/Min., Scale — 600/Min. Ausnahmen mit eigenem Limit, unabhängig vom Tarif: POST /v1/voices/create — 5/Min., POST /v1/warmup — 20/Min., GET /v1/status — 60/Min. pro IP, GET /v1/voices — 120/Min. pro IP.
Textlängedie max. Zeichen pro POST /api/v1/tts hängt vom Tarif des Schlüssels ab
Zeichen-Guthabendie Synthese rechnet Zeichen vom Tarif des Schlüssels ab; bei Null-Guthaben — 402
Transkription≈1 Min. Audio = 1000 Zeichen; es gilt das monatliche Minutenkontingent des Tarifs: Pro 100, Business 300, Scale 800 Min. Free und Starter enthalten KEINE Transkription — Antwort 403 (plan_required). Kontingent aufgebraucht → 403 (plan_quota).
DateigrößeStimmenerstellung: Beispiel ≤10 MB (base64), sonst 413
Beispiel
Vollständige Anfrage
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)