Voizum

API de texto a voz: tus voces, desde tu código

Una API REST sencilla: mandas un texto y una de tus voces, y recibes el MP3. Cobra los mismos créditos que la web, sin cuota de desarrollador ni coste por llamada.

URL base
https://voizum.com/api/v1
Autenticación
Bearer sk_voizum_…
Salida
MP3
Idiomas
es · en · de · fr · pt · it · ru
Precio
60 créditos / 1.000 caracteres (mín. 100)

Para asistentes de IA y herramientas

Tres puertas, según quién se conecte. Todas llevan a lo mismo: tus voces y tus créditos.

Claude, ChatGPT, Cursor… sin programar
El conector MCP: añádelo al asistente y pídele audios en el chat.
https://voizum.com/mcp
ChatGPT Actions, Postman, generadores de clientes
Importa la especificación OpenAPI 3.1: describe todos los endpoints y sus campos.
https://voizum.com/openapi.json
Agentes que leen documentación
llms.txt: el contrato entero en texto plano, pensado para modelos de lenguaje.
https://voizum.com/llms.txt

Empieza en tres pasos

  1. Crea tu cuenta y tu clave en la sección API de la web. La clave empieza por sk_voizum_ y se enseña una sola vez: guárdala como un secreto, nunca en el código del navegador.
  2. Elige una voz: clona la tuya o añade a «Mis voces» una de la biblioteca. GET /voices te da su id.
  3. Crea el audio con POST /tts, consulta su estado cada pocos segundos y descárgalo cuando esté listo (o recibe un webhook).

Un ejemplo completo

Crear, esperar y descargar. La API es asíncrona: un audio largo tarda en generarse y así no hay que tener la conexión abierta.

curl

# 1. Crear el audio
curl -X POST https://voizum.com/api/v1/tts \
  -H "Authorization: Bearer $VOIZUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Hola, esto es Voizum.", "voice_id": "VOICE_ID"}'
# → {"job_id": "…", "status": "queued", "credits_charged": 100, "eta_seconds": 20}

# 2. Consultar el estado (hasta "done")
curl https://voizum.com/api/v1/tts/JOB_ID -H "Authorization: Bearer $VOIZUM_API_KEY"

# 3. Descargar el MP3
curl -L -o audio.mp3 "https://voizum.com/api/v1/tts/JOB_ID/audio?download=1" -H "Authorization: Bearer $VOIZUM_API_KEY"

Python

import os, time, requests

API = "https://voizum.com/api/v1"
H = {"Authorization": f"Bearer {os.environ['VOIZUM_API_KEY']}"}

job = requests.post(f"{API}/tts", headers=H, json={"text": "Hola, esto es Voizum.", "voice_id": "VOICE_ID"}).json()
while True:
    estado = requests.get(f"{API}/tts/{job['job_id']}", headers=H).json()
    if estado["status"] in ("done", "error", "canceled"):
        break
    time.sleep(3)

if estado["status"] == "done":
    mp3 = requests.get(f"{API}/tts/{job['job_id']}/audio?download=1", headers=H)
    open("audio.mp3", "wb").write(mp3.content)

JavaScript (Node 18+)

const API = "https://voizum.com/api/v1";
const H = { Authorization: `Bearer ${process.env.VOIZUM_API_KEY}`, "Content-Type": "application/json" };

const job = await (await fetch(`${API}/tts`, {
  method: "POST", headers: H,
  body: JSON.stringify({ text: "Hola, esto es Voizum.", voice_id: "VOICE_ID" }),
})).json();

let estado;
do {
  await new Promise((r) => setTimeout(r, 3000));
  estado = await (await fetch(`${API}/tts/${job.job_id}`, { headers: H })).json();
} while (!["done", "error", "canceled"].includes(estado.status));

if (estado.status === "done") {
  const mp3 = await fetch(`${API}/tts/${job.job_id}/audio?download=1`, { headers: H });
  await (await import("node:fs/promises")).writeFile("audio.mp3", Buffer.from(await mp3.arrayBuffer()));
}

Endpoints

Método y rutaQué hace
GET /statusSalud del servicio. Sin clave.
GET /accountTu saldo de créditos y el precio por caracteres.
GET /voicesLas voces de tu biblioteca: su id es el voice_id.
POST /ttsCrea un audio a partir de un texto.
GET /tts/{job_id}Estado del audio: queued, processing, done, error o canceled.
GET /tts/{job_id}/audioEl MP3 terminado (redirige al fichero; ?download=1 para descargar).
DELETE /tts/{job_id}Cancela un audio que aún no ha empezado: se devuelven sus créditos.
GET /ttsTus últimos audios, paginados.
POST /tts/batchVarios audios separados en una petición, con un solo mínimo (de 2 a 100).
POST /tts/dialogueUn audio con varias voces por turnos (hasta 5 voces).

Qué acepta POST /tts

CampoQué es
textObligatorio. El texto, hasta 600.000 caracteres.
voice_idObligatorio. Una voz de tu biblioteca (GET /voices).
speedOpcional. Velocidad, de 0.5 a 2 (1 = el ritmo natural de la voz).
pause_msOpcional. Pausa entre frases, de 0 a 800 ms.
languageOpcional. auto, es, en, de, fr, pt, it, ru. Sin él, se deduce del texto.
loudness_normalizationOpcional. Iguala el volumen para que todas las voces suenen igual de fuerte.
webhook_urlOpcional. Una URL https pública a la que avisamos con un POST cuando el audio termina.
Idempotency-KeyCabecera opcional. Si reintentas con la misma, recibes el mismo audio y no se cobra dos veces.

Webhook

Con webhook_url no hace falta sondear: al terminar te mandamos un POST con el evento generation.finished (3 intentos, 10 s de espera cada uno). Si tu servidor contesta con un 4xx, no se reintenta.

El aviso no va firmado: tómalo como una señal para consultar GET /tts/{job_id} con tu clave, que es la fuente de verdad, y no como prueba de que el audio está listo.

{
  "event": "generation.finished",
  "id": "JOB_ID",
  "status": "completed",
  "voice_id": "VOICE_ID",
  "duration_seconds": 12.4,
  "credits": 100,
  "error": null
}

Límites

20 creaciones por minuto (POST /tts, /tts/batch y /tts/dialogue lo comparten) y 300 peticiones por minuto por clave en total. Las respuestas de crear traen X-RateLimit-Limit y X-RateLimit-Remaining, y todo 429 trae Retry-After con los segundos que hay que esperar.

El MP3 se guarda 4 días; después GET /tts/{job_id}/audio da 404, así que descárgalo y guárdalo tú.

Un audio admite hasta 600.000 caracteres. Un lote, de 2 a 100 audios y 1.200.000 caracteres en total. Un diálogo, hasta 100 turnos y 5 voces distintas.

Errores

Siempre con la misma forma: { "error": { "code", "message" } }, a veces con detalles (por ejemplo, cuántos créditos faltan).

CódigoHTTPQué pasa
no_autorizado401Falta la API key o no es válida.
parametros_invalidos400Faltan campos o tienen un valor no válido.
cuerpo_invalido400El cuerpo no es un JSON válido.
texto_demasiado_largo400El texto supera el máximo de caracteres.
lote_invalido400Un lote lleva entre 2 y 100 audios.
dialogo_invalido400Un diálogo lleva entre 2 y 100 turnos y hasta 5 voces.
webhook_invalido400La webhook_url no es https o no apunta a un servidor público.
voz_sin_muestra400Esa voz aún no se puede usar.
saldo_insuficiente402No tienes créditos suficientes (la respuesta dice cuántos hacen falta).
requiere_compra403Los lotes necesitan una cuenta que haya comprado créditos.
voz_no_encontrada404La voz no existe en tu biblioteca.
no_encontrado404No existe un job con ese id (o no es tuyo).
limite_peticiones429Demasiadas peticiones: espera lo que diga Retry-After.
demasiados_en_cola429Tienes demasiados trabajos en curso: espera a que terminen algunos.
mantenimiento503Pausa de mantenimiento: reintenta en un rato.
servicio_no_disponible503El servicio no está disponible ahora: reintenta.

Preguntas

¿Hay SDK para Python o JavaScript?
No hace falta: son unas pocas llamadas REST con JSON y funcionan con cualquier cliente HTTP (requests, fetch, curl). Si quieres un cliente generado, la especificación OpenAPI lo crea en tu lenguaje.
¿Hay streaming en tiempo real?
No. La API es asíncrona: creas el audio, consultas su estado y descargas el MP3 terminado. Está pensada para narraciones, vídeos, cursos y contenido, no para conversación en directo.
¿Puedo usar las voces de la biblioteca?
Sí: añádelas antes a «Mis voces» desde la web y aparecerán en GET /voices. Por la API solo se usan las voces de tu biblioteca.
¿Se puede clonar una voz por la API?
No: se clona desde la web (subes la grabación una vez) y luego la usas por la API con su voice_id.
¿Cuánto cuesta?
Lo mismo que en la web: 60 créditos por cada 1.000 caracteres, con un mínimo de 100 por petición. Sin cuota mensual ni coste por llamada. Si un audio falla, se devuelven sus créditos.
¿En qué formato sale el audio?
MP3.

Escribe tu texto y escúchalo con voz real

La API gasta créditos de un pack (60 por cada 1.000 caracteres) y pide entrar con Google. Packs desde 5,99 €, sin suscripción.