Referência
API v1 — endpoints
GET/api/v1/voicesCatálogo de vozes: id, língua, género, estilo, licença, exemplo
GET/api/v1/voices/{voice}/avatarAvatar da voz (imagem carregada ou gradiente gerado)
GET/api/v1/languagesLínguas suportadas: código, nome, nível, número de vozes
POST/api/v1/ttsSíntese de fala → WAV ou MP3 (parâmetro format)
POST/api/v1/tts_streamSíntese em streaming (PCM em blocos) para baixa latência — um stream limpo, sem pós-efeitos e sem mp3
POST/api/v1/voices/createCriar uma voz: name, audio_b64 (≤10 MB base64), ref_text (=áudio palavra por palavra), consent="voice-data-consent,privacy", language? → id da voz
GET/api/v1/voices/mineAs suas próprias vozes (clones criados + compradas): voice (slug), name, language, kind, sample_url — chave API necessária
POST/api/v1/transcribeTranscreva um fragmento curto: audio_b64, language? (nome completo) → texto. A duração conta para o limite mensal de minutos de transcrição do plano
GET/api/v1/statusProntidão do motor (agentes em tempo real): ready, model_ready, engine_up, latency_ms
POST/api/v1/warmupAqueça o motor antes de uma sessão de chamada (sem cobrar caracteres)
GET /api/v1/voices — filtros: q (pesquisa por nome/estilo), language (ru, en, de…), gender (male/female), limit (padrão 200, máximo 500), offset. Passe o campo voice da resposta para 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 & idiomas. Avatar: 302 para a imagem ou um gradiente SVG — coloque-o diretamente em <img>. Idiomas: tier = principal (pronto) | beta | em breve.
# 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" />
Acesso
Autenticação
Todos os endpoints requerem uma chave API: o cabeçalho X-API-Key: <key> ou Authorization: Bearer <key> (exceto GET /api/v1/voices, GET /api/v1/status, GET /api/v1/languages e GET /api/v1/voices/{voice}/avatar — abertos). A chave é criada na sua conta → secção “API”; a API está disponível a partir do plano Starter e acima (caso contrário 403). A síntese cobra caracteres ao plano da chave — com saldo zero devolve 402. O limite de taxa depende do plano: Starter — 30 pedidos/min, Pro — 120, Business — 300, Scale — 600 (fallback 60); ao exceder → 429, o cabeçalho Retry-After.
POST /api/v1/tts
Parâmetros
voiceID da voz de GET /api/v1/voices. ⚠️ Se o campo faltar, a síntese recorre à voz predefinida (de_at_n1) e os caracteres continuam a ser cobrados — passe sempre o ID explicitamente.
texttexto para voz; o comprimento máximo depende do plano da chave (obrigatório)
languagede, en, ru, fr, es, it, pt, zh, ja, ko (também de-DE, en-US …) e nomes completos (alemão, inglês …). Além disso Auto: o motor deteta o idioma a partir do texto — a única forma de sintetizar um idioma beta com a sua própria voz.
instructemoção/estilo em inglês, por exemplo "calm, friendly" (opcional)
emotionemoção studio-voice (para vozes com referências emocionais gravadas): alegre, animado, terno, calmo, triste, sério, tenso, zangado, assustado, surpreendido (opcional; sem o parâmetro — neutro)
saturationsaturação/“coloração” harmónica do timbre (pós-processamento): {"preset":"tube"|"tape"|"air","intensity":0–1} (opcional)
speedritmo da fala 0.5–2.0 (opcional) Valores fora do intervalo são limitados ao limite mais próximo; a resposta inclui então X-Effects-Failed: speed_clamped_to_….
gain_dbvolume −24…+24 dB (opcional)
eqequalizador do timbre: {"bands":[{"hz":80,"db":4}, …]} (opcional)
effectpredefinição de som: radio, audiobook, podcast, phone, cinematic, megaphone, vintage, deep, bright, warm, narrator_warm, intimate, spacious, whisper, concert; personagens: robot, cartoon, chipmunk, monster, villain, echo_hall; studio: studio_announcer, studio_natural, studio_rich. Efeitos Premium (characters, studio, cinematic, concert, megaphone, vintage) — apenas nos planos pagos, caso contrário são ignorados (opcional)
seedum número para uma repetição determinística da mesma locução (opcional)
cleantrue — denoising neural (separado do efeito, opcional)
backgroundfundo/ambiente: rain, thunder, sea, forest, birds, wind, stream, night, street, cafe, crowd, fire (opcional)
bg_levelvolume do fundo 0.05–0.8 (opcional, predefinição 0.25)
lead_silence_mssilêncio no início do áudio, ms (opcional, para agentes; predefinição 0)
format"wav" (predefinição) ou "mp3" (opcional)
response_formatSaída de telefonia (B2B/IVR): g711_alaw_8k, g711_ulaw_8k, g722_16k, opus, pcm_s16le_24k. A resposta é o fluxo do codec + cabeçalho X-Audio-Format (opcional)
containerapenas com response_format: wav (contentor, predefinição) ou raw (frames brutos para SIP/RTP) (opcional)
A resposta é um ficheiro de áudio binário: audio/wav ou audio/mpeg (se format=mp3); para um response_format de telefonia, o contentor de codec correspondente (ver X-Audio-Format).
POST /api/v1/tts_stream
Síntese em streaming
Aceita voice, text, language, instruct, speed, gain_db, eq, effect, background, bg_level, saturation, seed e segments (até 40 itens: text, instruct até 200 caracteres, silence 0–3000 ms). Resposta: PCM bruto — 24 kHz, 16-bit, mono, little-endian (application/octet-stream, chunked); não há cabeçalho WAV, defina a taxa de amostragem manualmente.
# 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
Criar uma voz
namenome da voz (obrigatório)
audio_b64amostra da gravação em base64, ≤10 MB (obrigatório)
ref_textTranscrição da gravação — palavra por palavra, máx. 2000 caracteres (mais longo → 400 ref_text_too_long). Se o texto não corresponder ao áudio, a voz soa incompreensível.
consentstring de consentimento — passe exatamente "voice-data-consent,privacy" (dados de voz, GDPR); sem isso — 400 (obrigatório)
languageidioma da amostra, nome completo (Russo, Inglês…) ou código ISO; padrão Alemão (opcional)
Passe o campo voice da resposta para POST /tts. O valor voice abaixo é um exemplo ilustrativo; o identificador real vem na resposta. Criar a sua própria voz está disponível no plano pago; o número das suas próprias vozes é ilimitado — criar uma custa 10.000 caracteres do seu saldo (armazenar e usar é gratuito).
# Response — 200 OK (voice value is an example)
{
"ok": true,
"voice": "usr_a1b2c3",
"name": "My voice",
"language": "German"
}
GET /api/v1/voices/mine
As suas próprias vozes
GET /api/v1/voices devolve apenas o catálogo público. Para obter AS SUAS próprias vozes — tanto as criadas via API como as geradas na sua conta/estúdio — autentique-se com a sua chave API e chame este endpoint. Ele devolve os seus próprios clones (kind="own") e vozes compradas no Marketplace (kind="marketplace"). Passe o campo voice (slug) para 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 é null para vozes próprias (não armazenado); sample_url pode ser null se não existir amostra. Ao sintetizar com a sua própria voz, o idioma é retirado da voz e substitui o parâmetro language em POST /tts.
Fluxo completo de copiar e colar — criar, listar, sintetizar (substitua a chave de exemplo pela sua própria em Conta → 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
Transcrição
audio_b64áudio em base64; destinado a um fragmento curto (obrigatório)
languageapenas o nome COMPLETO do idioma: Russo, Inglês, Alemão, Francês, Italiano, Espanhol, Português, Chinês, Japonês, Coreano — mais 14 idiomas beta (Búlgaro, Checo, Grego, Ucraniano, Polaco e outros) como dica de reconhecimento, e o literal "auto" (códigos ISO NÃO são aceites aqui, ao contrário de /tts; sem o parâmetro — deteção automática) (opcional)
Os caracteres são cobrados de acordo com o plano (≈1 min de áudio = 1000 caracteres); aplica-se o limite mensal de minutos de transcrição do plano.
# 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 e aquecimento
GET /api/v1/status (sem chave) — prontidão do motor para tempo real. POST /api/v1/warmup (com chave; não cobra caracteres) aquece o motor antes de uma série de chamadas.
# 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
}
Resposta
Cabeçalhos e o campo code
Content-Typeaudio/wav ou audio/mpeg (conforme o parâmetro de formato); para /tts_stream — application/octet-stream
X-Effects-Failedefeitos que NÃO foram aplicados (no motor ou removidos pelo plano), separados por vírgulas — o áudio é devolvido sem eles
X-CacheHIT / MISS — se a resposta veio da cache. Nota: com uma chave de API, um HIT na cache é faturado como um MISS (a cache poupa tempo de geração, não caracteres).
Retry-Afterem 429 — em quantos segundos repetir o pedido
O campo code no corpo do erro (legível por máquina): plan_required — é necessário um plano superior; voice_limit — o limite de vozes do plano; plan_quota — o limite mensal de minutos de transcrição foi esgotado; email_unverified — verifique o seu email; voice_conflict — o nome da voz já está em uso (ao criar uma voz).
Códigos de resposta
Erros
200Sucesso — o corpo da resposta contém o ficheiro de áudio
400JSON inválido ou texto vazio. Um idioma desconhecido devolve o 4xx do motor (por exemplo, 400) com o código engine_bad_request — o mesmo em /v1/tts e /v1/tts_stream
401Chave API em falta ou inválida (X-API-Key / cabeçalho Authorization)
402Não há caracteres suficientes no saldo da chave — carregue o plano
403A funcionalidade não está disponível no plano atual (por exemplo, API — no Starter, voz personalizada — num plano pago) ou não tem acesso à voz
409Conflito (voice_conflict): já existe uma voz com este nome — escolha outro nome ao criar uma voz
413Ficheiro demasiado grande: para uma voz personalizada o áudio é >10 MB (base64)
429Limite de pedidos excedido (por plano: Starter 30, Pro 120, Business 300, Scale 600 por minuto; /voices/create 5/min, /warmup 20/min). Respeite o cabeçalho Retry-After. Código: rate_limited.
500Erro interno (por exemplo, a base de dados não está disponível em GET /v1/voices) — tente novamente mais tarde.
502O motor de síntese/transcrição não respondeu (Bad Gateway) — aguarde um pouco e tente novamente
503O motor está a dormir/indisponível ou o serviço está sobrecarregado — tente novamente dentro de alguns segundos
O corpo do erro é JSON { "error": "description", "code": "machine-readable" }. Valores possíveis 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. Em caso de falha, não são cobrados caracteres — exceto quando o cliente aborta um stream (o áudio entregue é faturado pro rata).
Todos os códigos de erro
Lista completa de códigos de máquina no campo code: auth_required (401) · plan_required (403, API a partir do 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, com 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, o cliente interrompeu a ligação).
Notas
Detalhes práticos que são fáceis de ignorar: o corpo do pedido é limitado a 2 MB para /v1/tts e /v1/tts_stream (413 caso contrário) e a 30 MB base64 para /v1/transcribe · speaker é um sinónimo de voice · o marcador de pausa ‖ (U+2016) colocado no texto gera exatamente 400 ms de silêncio · instruct é truncado silenciosamente para 500 caracteres e lead_silence_ms é limitado a 5000 · sem seed é usado o valor 4242, por isso a saída é reproduzível por defeito (altere a seed se quiser variação) · sem language o alemão é assumido · GET /v1/languages aceita ?locale · o limite de taxa é contado por endpoint separadamente; limites próprios: /voices/create 5/min, /warmup 20/min, /voices/mine 60/min, endpoints GET abertos 120/min por IP · POST /v1/voices/clone é um alias de /voices/create.
Catálogo
Efeitos e fundos
O parâmetro effect — um preset por pedido. Os gratuitos estão disponíveis para todos; premium — nos planos pagos.
Entrega (gratuito)radio — emissão seca · audiobook — audiobook · narrator_warm — narrador quente · podcast — podcast · phone — telefone · intimate — próximo · spacious — amplo · whisper — sussurro · deep — mais grave · bright — mais brilhante · warm — mais quente
Estúdio (premium)studio_announcer — locutor de estúdio · studio_natural — natural de estúdio · studio_rich — rico “caro” · cinematic — cinema · concert — sala de concertos · megaphone — megafone · vintage — vintage
Personagens (premium)robot — robot · cartoon — caricatural · chipmunk — esquilo-canhão · monster — monstro · villain — vilão · echo_hall — eco de sala
Fundos (fundo)Natureza: rain (chuva) · thunder (trovoada) · sea (mar) · forest (floresta) · birds (pássaros) · wind (vento) · stream (riacho) · night (noite). Cidade: street (rua) · cafe (café) · crowd (multidão). Aconchegante: fire (lareira). Volume — bg_level 0.05–0.8
eq (timbre)8 bandas: 80, 160, 300, 600, 1500, 3500, 6500, 10500 Hz, cada uma −12…+12 dB. Exemplo: {"bands":[{"hz":80,"db":-4},{"hz":3500,"db":3}]} — remover ruído, adicionar clareza
Cotas
Limites
Taxa de pedidossegundo o plano da chave: Starter — 30/min, Pro — 120/min, Business — 300/min, Scale — 600/min. Endpoints com limite próprio, independentemente do plano: 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.
Comprimento do textoo máximo de caracteres por POST /api/v1/tts depende do plano da chave
Saldo de caracteresa síntese desconta caracteres do plano da chave; com saldo zero — 402
Transcrição≈1 min de áudio = 1000 caracteres; aplicam-se os minutos mensais do plano: Pro 100, Business 300, Scale 800 min. Free e Starter NÃO incluem transcrição — a API responde 403 (plan_required). Cota esgotada → 403 (plan_quota).
Tamanho do ficheirocriação de voz: sample ≤10 MB (base64), caso contrário 413
Exemplo
Pedido completo
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)