O serviço está a funcionar em modo de teste — os testes beta estão em curso. São possíveis erros.
Início/Documentação da API

Documentação da API para integrações

API REST para locução, geração em streaming, catálogo de vozes, criação da sua própria voz e transcrição.

# 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
interface de integração
Motor
geração de locução
318
vozes no catálogo
WAV
formato de resposta da API
Capacidades

Criado para integração

Geração síncrona

Um pedido POST devolve um ficheiro WAV pronto.

REST sem SDK

Exemplos para cURL, Node.js e Python sobre HTTP simples.

Modo de streaming

Um endpoint separado para cenários de streaming.

10 línguas + Auto

Um endpoint, o parâmetro de idioma: russo, inglês, alemão, francês, espanhol, italiano, português, chinês, japonês e coreano.

Sistema, personalizadas e variantes

Use a biblioteca, vozes personalizadas guardadas e variantes de som.

Alojamento EU

Servidores em EU, GDPR.

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": "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 & 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)
languageNormalmente não é necessário: o idioma é detetado a partir do texto e a voz lê o texto nesse idioma. Sem sotaque, uma voz só soa nos seus verified_languages (GET /api/v1/voices); noutros idiomas mantém o sotaque, e a resposta indica-o: X-Synthesis-Language, X-Voice-Language, X-Language-Verified: false. O parâmetro só conta para uma voz sem idioma próprio, quando o texto é demasiado curto para detetar o idioma: de, 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 25.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. À parte: concurrency_limit (também 429) significa demasiados pedidos a decorrer em simultâneo numa conta (por plano: Starter 2, Pro 3, Business 4, Scale 6 sínteses em paralelo) — repita assim que um terminar. Sem Retry-After, pois a espera depende do seu próprio pedido em curso.
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, 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. 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) · concurrency_limit (429, concurrency) · 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)

Obtenha uma chave em um minuto

Obter uma chave de API →
POST /api/v1/ttsGET /api/v1/voicesPágina SEO da API