Referencia
API v1 — endpoints
GET/api/v1/voicesCatálogo de voces: id, idioma, género, estilo, licencia, muestra
GET/api/v1/voices/{voice}/avatarAvatar de voz (imagen subida o degradado generado)
GET/api/v1/languagesIdiomas compatibles: código, nombre, nivel, número de voces
POST/api/v1/ttsSíntesis de voz → WAV o MP3 (parámetro format)
POST/api/v1/tts_streamSíntesis en streaming (PCM fragmentado) para baja latencia — un flujo limpio sin posprocesado y sin mp3
POST/api/v1/voices/createCrear una voz: name, audio_b64 (≤10 MB base64), ref_text (=audio palabra por palabra), consent="voice-data-consent,privacy", language? → voice id
GET/api/v1/voices/mineTus propias voces (clones creados + compradas): voice (slug), name, language, kind, sample_url — se requiere clave API
POST/api/v1/transcribeTranscribir un fragmento corto: audio_b64, language? (nombre completo) → text. La duración cuenta para el límite mensual de minutos de transcripción del plan
GET/api/v1/statusDisponibilidad del motor (agentes en tiempo real): ready, model_ready, engine_up, latency_ms
POST/api/v1/warmupCalienta el motor antes de una sesión de llamada (sin cobrar caracteres)
GET /api/v1/voices — filtros: q (buscar por nombre/estilo), language (ru, en, de…), gender (male/female), limit (200 por defecto, máximo 500), offset. Pasa el campo voice de la respuesta a 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"
}
]
}
Avatares y idiomas. Avatar: 302 a la imagen o a un degradado SVG — colócalo directamente en <img>. Idiomas: tier = principal (listo) | beta | pronto.
# 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" />
Acceso
Autenticación
Todos los endpoints requieren una clave API: la cabecera X-API-Key: <key> o Authorization: Bearer <key> (excepto GET /api/v1/voices, GET /api/v1/status, GET /api/v1/languages y GET /api/v1/voices/{voice}/avatar — abiertos). La clave se crea en tu cuenta → la sección “API”; la API está disponible desde el plan Starter en adelante (de lo contrario 403). La síntesis cobra caracteres al plan de la clave — con saldo cero devuelve 402. El límite de tasa depende del plan: Starter — 30 solicitudes/min, Pro — 120, Business — 300, Scale — 600 (fallback 60); si se supera → 429, la cabecera Retry-After.
POST /api/v1/tts
Parámetros
voiceID de voz de GET /api/v1/voices. ⚠️ Si falta el campo, la síntesis usa la voz predeterminada (de_at_n1) y aun así se cobran caracteres — pasa siempre el ID explícitamente.
texttexto a voz; la longitud máxima depende del plan de la clave (obligatorio)
languagede, en, ru, fr, es, it, pt, zh, ja, ko (también de-DE, en-US …) y nombres completos (German, English …). Además Auto: el motor detecta el idioma del texto — la única forma de sintetizar un idioma beta con tu propia voz.
instructemoción/estilo en inglés, por ejemplo "calm, friendly" (opt.)
emotionemoción studio-voice (para voces con referencias emocionales grabadas): alegre, emocionado, tierno, calmado, triste, serio, tenso, enfadado, asustado, sorprendido (opcional; sin el parámetro — neutral)
saturationsaturación/“coloración” armónica del timbre (posprocesado): {"preset":"tube"|"tape"|"air","intensity":0–1} (opcional)
speedtempo del habla 0.5–2.0 (opcional) Los valores fuera del rango se ajustan al límite más cercano; la respuesta lleva entonces X-Effects-Failed: speed_clamped_to_….
gain_dbvolumen −24…+24 dB (opcional)
eqecualizador del timbre: {"bands":[{"hz":80,"db":4}, …]} (opcional)
effectpreset de sonido: 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. Efectos Premium (characters, studio, cinematic, concert, megaphone, vintage) — solo en planes de pago, de lo contrario se ignoran (opcional)
seedun número para repetir de forma determinista la misma locución (opcional)
cleantrue — reducción de ruido neuronal (separada de effect, opcional)
backgroundfondo/ambiente: rain, thunder, sea, forest, birds, wind, stream, night, street, cafe, crowd, fire (opcional)
bg_levelvolumen del fondo 0.05–0.8 (opcional, predeterminado 0.25)
lead_silence_mssilencio al inicio del audio, ms (opcional, para agentes; predeterminado 0)
format"wav" (predeterminado) o "mp3" (opcional)
response_formatSalida de telefonía (B2B/IVR): g711_alaw_8k, g711_ulaw_8k, g722_16k, opus, pcm_s16le_24k. La respuesta es el flujo del códec + cabecera X-Audio-Format (opcional)
containersolo con response_format: wav (contenedor, predeterminado) o raw (frames sin procesar para SIP/RTP) (opcional)
La respuesta es un archivo de audio binario: audio/wav o audio/mpeg (si format=mp3); para un response_format de telefonía, el contenedor del códec correspondiente (ver X-Audio-Format).
POST /api/v1/tts_stream
Síntesis en streaming
Acepta voice, text, language, instruct, speed, gain_db, eq, effect, background, bg_level, saturation, seed y segments (hasta 40 elementos: text, instruct hasta 200 caracteres, silence 0–3000 ms). Respuesta: PCM sin procesar — 24 kHz, 16 bits, mono, little-endian (application/octet-stream, por fragmentos); no hay cabecera WAV, configure usted la frecuencia de muestreo.
# 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
Crear una voz
namenombre de la voz (obligatorio)
audio_b64grabación de muestra en base64, ≤10 MB (obligatorio)
ref_textTranscripción de la grabación — palabra por palabra, máx. 2000 caracteres (más largo → 400 ref_text_too_long). Si el texto no coincide con el audio, la voz suena confusa.
consentcadena de consentimiento — pasa exactamente "voice-data-consent,privacy" (datos de voz, GDPR); sin ella — 400 (obligatorio)
languageidioma de muestra, nombre completo (ruso, inglés…) o código ISO; alemán por defecto (opt.)
Pasa el campo voice de la respuesta a POST /tts. El valor voice de abajo es un ejemplo ilustrativo; el identificador real viene en la respuesta. Crear tu propia voz está disponible en un plan de pago; el número de tus propias voces es ilimitado — crear una cuesta 10.000 caracteres de tu saldo (guardarla y usarla es gratis).
# Response — 200 OK (voice value is an example)
{
"ok": true,
"voice": "usr_a1b2c3",
"name": "My voice",
"language": "German"
}
GET /api/v1/voices/mine
Tus propias voces
GET /api/v1/voices devuelve solo el catálogo público. Para obtener TUS propias voces — tanto las creadas por la API como las generadas en tu cuenta/estudio — autentícate con tu clave API y llama a este endpoint. Devuelve tus propios clones (kind="own") y voces compradas en el Marketplace (kind="marketplace"). Pasa el campo voice (slug) a 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 es null para voces propias (no se guarda); sample_url puede ser null si no existe muestra. Al sintetizar con tu propia voz, el idioma se toma de la voz y anula el parámetro language en POST /tts.
Flujo completo de copiar y pegar — crear, listar, sintetizar (sustituye la clave de ejemplo por la tuya desde Cuenta → 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
Transcripción
audio_b64audio en base64; pensado para un fragmento corto (obligatorio)
languagesolo el nombre COMPLETO del idioma: ruso, inglés, alemán, francés, italiano, español, portugués, chino, japonés, coreano — además de 14 idiomas beta (búlgaro, checo, griego, ucraniano, polaco y otros) como pista de reconocimiento, y el literal "auto" (los códigos ISO NO se aceptan aquí, a diferencia de /tts; sin el parámetro — autodetección) (opt.)
Los caracteres se cobran según el plan (≈1 min de audio = 1000 caracteres); se aplica el límite mensual de minutos de transcripción del plan.
# 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
Estado y calentamiento
GET /api/v1/status (sin clave) — preparación del motor en tiempo real. POST /api/v1/warmup (con una clave; no cobra caracteres) calienta el motor antes de una serie de llamadas.
# 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
}
Respuesta
Cabeceras y el campo code
Content-Typeaudio/wav o audio/mpeg (según el parámetro format); para /tts_stream — application/octet-stream
X-Effects-Failedefectos que NO se aplicaron (en el motor o recortados por el plan), separados por comas — el audio vuelve sin ellos
X-CacheHIT / MISS — indica si la respuesta proviene de la caché. Nota: con una API key, un HIT de la caché se factura como un MISS (la caché ahorra tiempo de generación, no caracteres).
Retry-Afteren 429 — en cuántos segundos reintentar la solicitud
El campo code en el cuerpo del error (legible por máquina): plan_required — se necesita un plan superior; voice_limit — el límite de voces del plan; plan_quota — el límite mensual de minutos de transcripción se ha agotado; email_unverified — verifica tu correo electrónico; voice_conflict — el nombre de la voz ya está en uso (al crear una voz).
Códigos de respuesta
Errores
200Éxito — el cuerpo de la respuesta contiene el archivo de audio
400JSON incorrecto o texto vacío. Un idioma desconocido devuelve el 4xx del motor (p. ej. 400) con code engine_bad_request — lo mismo en /v1/tts y /v1/tts_stream
401API key faltante o inválida (X-API-Key / encabezado Authorization)
402No hay suficientes caracteres en el saldo de la clave — recarga el plan
403La función no está disponible en el plan actual (p. ej. API — desde Starter, voz personalizada — desde un plan de pago) o no hay acceso a la voz
409Conflicto (voice_conflict): ya existe una voz con este nombre — elige otro nombre al crear una voz
413Archivo demasiado grande: para una voz personalizada el audio es >10 MB (base64)
429Límite de solicitudes superado (por plan: Starter 30, Pro 120, Business 300, Scale 600 por minuto; /voices/create 5/min, /warmup 20/min). Respeta el encabezado Retry-After. Código: rate_limited.
500Error interno (p. ej., la base de datos no está disponible en GET /v1/voices) — inténtalo más tarde.
502El motor de síntesis/transcripción no respondió (Bad Gateway) — espera un momento y vuelve a intentarlo
503El motor está en reposo/no disponible o el servicio está sobrecargado — reintenta en unos segundos
El cuerpo del error es JSON { "error": "description", "code": "machine-readable" }. Valores posibles de 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. En caso de fallo no se cobran caracteres — excepto cuando el cliente interrumpe un stream (el audio entregado se factura de forma proporcional).
Todos los códigos de error
Lista completa de códigos máquina en el campo code: auth_required (401) · plan_required (403, API desde 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, con 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, el cliente cerró la conexión).
Nota
Detalles prácticos que son fáciles de pasar por alto: el cuerpo de la solicitud tiene un límite de 2 MB para /v1/tts y /v1/tts_stream (413 en otro caso) y de 30 MB en base64 para /v1/transcribe · speaker es un sinónimo de voice · el marcador de pausa ‖ (U+2016) colocado en el texto produce exactamente 400 ms de silencio · instruct se recorta silenciosamente a 500 caracteres y lead_silence_ms tiene un máximo de 5000 · sin seed se usa el valor 4242, así que el resultado es reproducible por defecto (cambia tú mismo la seed si quieres variación) · sin language se asume alemán · GET /v1/languages acepta ?locale · el límite de frecuencia se cuenta por endpoint por separado; límites propios: /voices/create 5/min, /warmup 20/min, /voices/mine 60/min, endpoints GET abiertos 120/min por IP · POST /v1/voices/clone es un alias de /voices/create.
Catálogo
Efectos y fondos
El parámetro effect — un preset por solicitud. Los gratuitos están disponibles para todos; premium — en planes de pago.
Entrega (gratis)radio — emisión seca · audiobook — audiolibro · narrator_warm — narrador cálido · podcast — podcast · phone — teléfono · intimate — cercano · spacious — espacioso · whisper — susurro · deep — más grave · bright — más brillante · warm — más cálido
Estudio (premium)studio_announcer — locutor de emisión · studio_natural — natural de estudio · studio_rich — rico “caro” · cinematic — cine · concert — sala · megaphone — megáfono · vintage — vintage
Personajes (premium)robot — robot · cartoon — caricaturesco · chipmunk — ardilla listada · monster — monstruo · villain — villano · echo_hall — sala con eco
Fondos (fondo)Naturaleza: rain (lluvia) · thunder (tormenta) · sea (mar) · forest (bosque) · birds (pájaros) · wind (viento) · stream (arroyo) · night (noche). Ciudad: street (calle) · cafe (cafetería) · crowd (multitud). Acogedor: fire (chimenea). Volumen — bg_level 0.05–0.8
eq (timbre)8 bandas: 80, 160, 300, 600, 1500, 3500, 6500, 10500 Hz, cada una −12…+12 dB. Ejemplo: {"bands":[{"hz":80,"db":-4},{"hz":3500,"db":3}]} — quitar ruido grave, añadir claridad
Cuotas
Límites
Ritmo de solicitudessegún el plan de la clave: Starter — 30/min, Pro — 120/min, Business — 300/min, Scale — 600/min. Endpoints con su propio tope fijo, sin importar el plan: POST /v1/voices/create — 5/min, POST /v1/warmup — 20/min, GET /v1/status — 60/min por IP, GET /v1/voices — 120/min por IP.
Longitud del textoel máximo de caracteres por POST /api/v1/tts depende del plan de la clave
Saldo de caracteresla síntesis carga caracteres contra el plan de la clave; con saldo cero — 402
Transcripción≈1 min de audio = 1000 caracteres; aplican los minutos mensuales del plan: Pro 100, Business 300, Scale 800 min. Free y Starter NO incluyen transcripción — la API responde 403 (plan_required). Cuota agotada → 403 (plan_quota).
Tamaño del archivocreación de voz: muestra ≤10 MB (base64), de lo contrario 413
Ejemplo
Solicitud completa
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)