El servicio está en modo de prueba — la beta está en marcha. Puede haber errores.
Inicio/Documentación de API

Documentación de API para integraciones

API REST para locución, generación en streaming, el catálogo de voces, crear tu propia voz y transcripción.

# Text-to-speech (voice — id from GET /api/v1/voices) curl https://hancvoice.com/api/v1/tts \ -H "X-API-Key: $HANCVOICE_KEY" \ -H "Content-Type: application/json" \ -d '{ "voice": "de_at_f1", "text": "Hallo! Das ist HancVoice.", "language": "de" }' --output out.wav
import fs from "node:fs/promises"; const response = await fetch("https://hancvoice.com/api/v1/tts", { method: "POST", headers: { "X-API-Key": process.env.HANCVOICE_KEY, "Content-Type": "application/json" }, body: JSON.stringify({ voice: "de_at_f1", text: "Hallo! Das ist HancVoice.", language: "de" }) }); const audio = Buffer.from(await response.arrayBuffer()); await fs.writeFile("out.wav", audio);
import os, requests response = requests.post( "https://hancvoice.com/api/v1/tts", headers={ "X-API-Key": os.environ["HANCVOICE_KEY"], "Content-Type": "application/json", }, json={ "voice": "de_at_f1", "text": "Hallo! Das ist HancVoice.", "language": "de", }, ) open("out.wav", "wb").write(response.content)
REST
interfaz de integración
Motor
generación de locución
318
voces en el catálogo
WAV
formato de respuesta de la API
Funciones

Diseñado para integraciones

Generación síncrona

Una solicitud POST devuelve un archivo WAV listo.

REST sin SDK

Ejemplos para cURL, Node.js y Python sobre HTTP puro.

Modo streaming

Un endpoint separado para escenarios de streaming.

10 idiomas + Auto

Un endpoint, el parámetro de idioma: ruso, inglés, alemán, francés, español, italiano, portugués, chino, japonés y coreano.

Sistema, personalizadas y variantes

Usa la biblioteca, las voces personalizadas guardadas y variantes de sonido.

hosting EU

Servidores en EU, GDPR.

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": "Young", "description": "Female voice — Austrian German, young, joyful, for presentations.", // in the response language (?locale=) "labels": { // filter on the *_key fields: they are stable and never translated "gender": "female", "language": "de-AT", "language_name": "Austrian German", "accent": "Austrian German", "age": "young", // age is "" unless the catalogue marks it "style": "Young", "style_key": "young", "use_case": "presentations", "use_case_key": "presentations", "emotion": "joyful", "emotion_key": "joyful" }, "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)
languageNormalmente no hace falta: el idioma se detecta a partir del texto y la voz lo lee en ese idioma. Sin acento, una voz solo suena en sus verified_languages (GET /api/v1/voices); en otros idiomas conserva su acento y la respuesta lo indica: X-Synthesis-Language, X-Voice-Language, X-Language-Verified: false. El parámetro solo cuenta para una voz sin idioma propio, cuando el texto es demasiado corto para detectar el idioma: de, 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 25.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. Aparte: concurrency_limit (también 429) significa demasiadas peticiones en curso a la vez en una cuenta (según el plan: Starter 2, Pro 3, Business 4, Scale 6 síntesis en paralelo); reinténtalo en cuanto termine una. Sin Retry-After, porque la espera depende de tu propia petición en curso.
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, concurrency_limit, 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) · concurrency_limit (429, concurrency) · 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)

Consigue una clave en un minuto

Obtener una clave de API →
POST /api/v1/ttsGET /api/v1/voicesPágina SEO de la API