API de voz
Genera voz desde tu propio código con las voces de Voice Studio: una voz o un guion completo, 0,4 créditos por carácter hablado en cualquier idioma, con una estimación gratuita antes.
Genera voz desde tu propio código con NueSpeak Apex, las mismas voces que Voice Studio. Las solicitudes gastan créditos de tu saldo de NueForm: 0,4 créditos por carácter hablado (unos $0.04 por cada 1.000 caracteres) en cualquier idioma, redondeados hacia arriba a un crédito entero una vez por solicitud. Las estimaciones son gratuitas.
Todos los cuerpos de solicitud y respuesta usan nombres de campo en snake_case. Las voces se identifican con IDs nv_… y las generaciones con IDs gen_….
Las claves Voice funcionan en todos los planes una vez que tu cuenta ha hecho una primera compra de créditos (o tiene un plan de pago) y ha verificado su correo. Consulta Claves de la API de voz.
Generar voz
/api/v1/voiceGenera el audio y responde cuando está listo (de forma síncrona, como máximo 5.000 caracteres hablados por solicitud). Envía Accept: audio/mpeg (o audio/wav, audio/ogg, audio/basic, audio/*) para recibir el audio en sí; si no, la respuesta es JSON con una audio.url autenticada.
Los créditos se cobran cuando empieza la solicitud. Las líneas que fallan se devuelven automáticamente, y nada que termine en error se cobra. Una solicitud que ya se cobró nunca termina en error: si su audio no está listo a tiempo, responde 202 con un encabezado Location. Descarga el audio desde ahí en lugar de volver a enviar la solicitud.
Cuerpo de la solicitud
modestring"speak" (una voz lee text), "script" (varias voces) o "estimate" (consulta Estimar el costo)
textstringspeak: las palabras que se leen
voicestringUna voz nv_… de Listar voces. Obligatoria para speak; en un script, la voz de las líneas sin etiqueta de personaje
linesarrayscript: líneas estructuradas, cada una {"speaker", "voice", "text"} o una pausa {"pause_ms": 800} (hasta 10.000)
scriptstringscript: el formato multivoz, una línea por personaje: [Maya] Did you hear that?
castarrayscript: una voz para cada personaje etiquetado, [{"speaker": "Maya", "voice": "nv_…"}]
auto_convertbooleanConvertir primero un guion o un chat pegado (MAYA: Hi) al formato multivoz. Gratis, dentro de un límite diario
auto_castbooleanElegir una voz para cada personaje que no tenga. Gratis, dentro de un límite diario. Envía language para un guion que no esté en inglés
languagestringUn nombre o código de idioma ("es", "Spanish"). Predeterminado: el idioma propio de la voz
qualitystring"standard" (predeterminado), "studio" o "phone". Mismo precio
speednumberDe 0,85 a 1,15 (predeterminado 1)
formatstring"mp3" (predeterminado), "wav", "ogg_opus" o "mulaw_8k"
max_creditsintegerRechazar la solicitud (409, sin cobro) si fuera a costar más
reusebooleanPredeterminado true: una solicitud idéntica hecha en los últimos 30 días se responde con ese audio por 0 créditos
savebooleantrue conserva el audio hasta que lo elimines. Predeterminado: se elimina a los 30 días
retake_ofstringVolver a generar una generación (consulta Retomas)
titlestringSu título en tu Library
Campos de respuesta
idstringLa generación (gen_…)
statusstring"ready", "rendering" (202: todavía se está generando), "partial" (algunas líneas fallaron y no cuestan nada) o "failed"
audioobject or nullurl (envía tu clave de API), format, sample_rate, duration_seconds, retained_until
creditsobjectestimated, charged (lo que cobró esta solicitud) y remaining
linesarraySolo script: speaker, voice, text, status, start_ms, end_ms y credits de cada línea
retakes_remainingintegerRetomas gratuitas que quedan para este clip
reusedbooleanEl audio de una solicitud idéntica anterior, por 0 créditos
Ejemplos de código
curl -X POST https://nueform.io/api/v1/voice \
-H "Authorization: Bearer $NUEFORM_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: audio/mpeg" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"mode": "speak",
"voice": "nv_7QmS2xK9aLpe3vT8a",
"text": "Fresh bread every morning at seven. Croissants too. See you on Main Street."
}' \
--output speech.mp3 --dump-header -
Este texto tiene 75 caracteres hablados, así que cuesta 30 créditos (75 × 0,4).
Encabezados de respuesta
HTTP/1.1 200 OK
Content-Type: audio/mpeg
NueForm-Generation-Id: gen_2cH4kXyQ9vLmNp3Rs
NueForm-Credits-Estimated: 30
NueForm-Credits-Charged: 30
NueForm-Credits-Remaining: 48730
NueForm-Rate-Card: 1
NueForm-Retakes-Remaining: 2
NueForm-Audio-Duration: 4.8
Idempotent-Replayed: false
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 2026-11-04T18:13:00.000Z
Respuesta JSON
{
"data": {
"id": "gen_2cH4kXyQ9vLmNp3Rs",
"object": "voice.generation",
"status": "ready",
"mode": "speak",
"source": "api",
"voice": { "id": "nv_7QmS2xK9aLpe3vT8a", "name": "Amara" },
"language": "English",
"characters": 75,
"audio": {
"url": "https://nueform.io/api/v1/voice/generations/gen_2cH4kXyQ9vLmNp3Rs/audio?format=mp3",
"format": "mp3",
"sample_rate": 24000,
"duration_seconds": 4.8,
"retained_until": "2026-12-04T18:12:00.000Z"
},
"credits": { "estimated": 30, "charged": 30, "remaining": 48730 },
"retakes_remaining": 2,
"reused": false,
"created_at": "2026-11-04T18:12:00.000Z"
},
"meta": { "rate_card": "1" }
}
Guiones
Un guion habla con varias voces en un solo archivo de audio. Envía lines estructuradas (sin ningún análisis) o un script en el formato multivoz con su cast. Las pausas ({"pause_ms": 800}, o (pause 2s) en un guion) no cuestan nada; solo se cobran los caracteres hablados.
La respuesta añade lines: dónde empieza y termina cada línea en el audio, su estado y lo que suman sus caracteres (credits, con decimales). La solicitud se cobra una sola vez, redondeada hacia arriba. Una línea que falla muestra "credits": 0 y no cuesta nada.
Con auto_convert, primero se convierte un guion o un chat pegado; con auto_cast, cada personaje sin voz recibe una.
Ejemplo de solicitud
{
"mode": "script",
"lines": [
{ "speaker": "Maya", "voice": "nv_7QmS2xK9aLpe3vT8a", "text": "Did you hear that?" },
{ "speaker": "Leo", "voice": "nv_P3vT8aLeQ2mwX4kZ9", "text": "Hear what?" },
{ "pause_ms": 800 },
{ "speaker": "Maya", "voice": "nv_7QmS2xK9aLpe3vT8a", "text": "Exactly. Nothing." }
],
"format": "wav"
}
O el formato multivoz
{
"mode": "script",
"script": "[Maya] Did you hear that?\n[Leo] Hear what?\n(pause 1s)\n[Maya] Exactly. Nothing.",
"auto_cast": true
}
Estimar el costo
/api/v1/voice"mode": "estimate" acepta el mismo cuerpo que speak o script y responde con el costo exacto, sin generar nada. Es gratis y no cuenta para tus límites de generación (hasta 300 por minuto por clave).
Campos de respuesta
charactersintegerCaracteres hablados: lo que se cobra
creditsintegerExactamente lo que cobraría la solicitud
seconds_estimatednumberCuánto durará el audio, aproximadamente
balanceintegerTu saldo actual
enoughbooleanTu saldo (y el límite mensual de la clave, si lo tiene) lo cubre
Ejemplo
curl -X POST https://nueform.io/api/v1/voice \
-H "Authorization: Bearer $NUEFORM_API_KEY" \
-d '{"mode": "estimate", "voice": "nv_7QmS2xK9aLpe3vT8a", "text": "Fresh bread every morning at seven. Croissants too. See you on Main Street."}'
{
"data": {
"object": "voice.estimate",
"characters": 75,
"credits": 30,
"seconds_estimated": 4.8,
"balance": 48760,
"enough": true
},
"meta": { "rate_card": "1" }
}
Transmitir voz
/api/v1/voice/streamEnvía el audio mientras se genera, para que tu app empiece a reproducirlo en alrededor de un segundo en vez de esperar al clip completo: un agente, un bot de voz, un lector. Una voz lee text. Con el motor de voz ya en caliente, el primer audio suele llegar en 1–2 segundos, sea cual sea la longitud del texto.
El precio es el de Generar voz: 0,4 créditos por carácter hablado, redondeados hacia arriba una vez por solicitud y cobrados cuando empieza la transmisión. Una transmisión admite hasta unos 200 segundos de voz: unos 3.100 caracteres en inglés, menos en idiomas que se hablan más despacio (un texto más largo es 413 TEXT_TOO_LONG con max_characters). Para textos más largos, envía varias transmisiones o usa POST /api/v1/voice.
Antes del primer byte, cualquier fallo es un error normal y no cuesta nada: si el motor de voz falla antes de cualquier audio, se devuelve el cobro (500, o 503 WARMING_UP con Retry-After mientras el motor arranca). Después del primer byte el estado ya no puede cambiar, así que una transmisión que falla a mitad de camino se detiene antes de su final: tu cliente HTTP informa de un cuerpo incompleto. Usa NueForm-Generation-Id con Obtener una generación para ver la copia guardada y lo que costó. Si cuelgas, la transmisión se termina y se guarda igualmente, y no se devuelve.
Cada transmisión también se guarda como una generación: aparece en tu Library y Descargar el audio la sirve, normalizada como cualquier clip.
¿Transmitir o /voice? Transmite cuando alguien está esperando para oírlo (agentes, bots de voz, lectura en voz alta). Usa POST /api/v1/voice para archivos, guiones con varias voces, speed, retomas y estimaciones. Las herramientas MCP no transmiten: generan el audio como /voice.
Cuerpo de la solicitud
voicestringUna voz nv_… de Listar voces
textstringLas palabras que se leerán
formatstring"mp3" (predeterminado, para navegadores), "pcm_24k" (PCM mono de 16 bits little-endian sin procesar a 24.000 Hz, para agentes) o "mulaw_8k" (G.711 μ-law a 8 kHz, para telefonía; "ulaw_8000" también funciona)
languagestringUn nombre o código de idioma. Predeterminado: el idioma propio de la voz
qualitystring"standard" (predeterminado; "phone" con mulaw_8k), "studio" o "phone". Mismo precio
max_creditsintegerRechazar la solicitud (409, sin cobro) si fuera a costar más
savebooleantrue conserva la copia guardada hasta que la elimines. Predeterminado: se elimina a los 30 días
titlestringSu título en tu Library
speed, los guiones, retake_of y reuse no están disponibles en una transmisión (400, reason: "not_on_stream").
Ejemplos de código
curl -N -X POST https://nueform.io/api/v1/voice/stream \
-H "Authorization: Bearer $NUEFORM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"voice": "nv_7QmS2xK9aLpe3vT8a", "text": "Fresh bread every morning at seven.", "format": "mp3"}' \
--output stream.mp3
Este texto tiene 35 caracteres hablados, así que cuesta 14 créditos (35 × 0,4).
Encabezados de respuesta
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Transfer-Encoding: chunked
NueForm-Generation-Id: gen_2cH4kXyQ9vLmNp3Rs
NueForm-Credits-Estimated: 14
NueForm-Credits-Charged: 14
NueForm-Credits-Remaining: 48716
NueForm-Rate-Card: 1
NueForm-Audio-Format: pcm_24k
NueForm-Audio-Encoding: pcm_s16le
NueForm-Audio-Sample-Rate: 24000
NueForm-Audio-Channels: 1
X-Accel-Buffering: no
Retomas
Envía {"mode": "speak", "retake_of": "gen_…"} para volver a generar una generación con las mismas palabras, voces, idioma, calidad y velocidad. Con retake_of solo van mode, format, max_credits y save.
- Gratis dos veces dentro de las 24 horas de la generación, siempre que las retomas gratuitas de la clave este mes no superen una cuarta parte de los caracteres que se le cobraron este mes. Una retoma gratuita conserva el mismo ID
gen_…. - Si no, es una generación nueva, cobrada como cualquier solicitud (0,4 créditos por carácter), y
retake_ofindica la generación que se volvió a tomar.
Envía "mode": "estimate" con retake_of para verlo antes: la respuesta dice "free": true o lo que costaría.
Idempotencia
Envía un encabezado Idempotency-Key (de 1 a 255 caracteres, por ejemplo un UUID) con las solicitudes speak y script, y un reintento nunca podrá cobrar dos veces:
- la misma clave con el mismo cuerpo vuelve a responder con lo que generó la primera solicitud, sin cobrar (
Idempotent-Replayed: true,NueForm-Credits-Charged: 0); - la misma clave con otro cuerpo da
409 CONFLICTconreason: "idempotency_conflict"; - mientras la primera solicitud sigue en curso,
409 CONFLICTconreason: "request_in_progress"yRetry-After.
Las claves se recuerdan durante 24 horas, por clave de API.
En una transmisión, la misma clave con el mismo cuerpo responde con JSON: la generación que hizo la primera solicitud (no se vuelve a transmitir).
Encabezados de respuesta
Cada respuesta dice lo que costó:
| Encabezado | Significado |
|---|---|
NueForm-Generation-Id | La generación (gen_…) |
NueForm-Credits-Estimated | El precio que se cotizó para la solicitud |
NueForm-Credits-Charged | Lo que cobró esta solicitud, después de cualquier devolución automática (0 para una estimación, un clip reutilizado, una retoma gratuita, una repetición y cualquier error) |
NueForm-Credits-Remaining | Tu saldo después |
NueForm-Rate-Card | La versión de la tarifa con la que se cobró |
NueForm-Retakes-Remaining | Retomas gratuitas que quedan para este clip |
NueForm-Audio-Duration | La duración del audio en segundos |
Idempotent-Replayed | Con una Idempotency-Key: si esto responde a una solicitud anterior |
NueForm-Audio-Format, NueForm-Audio-Encoding, NueForm-Audio-Sample-Rate, NueForm-Audio-Channels | El audio de una transmisión: su formato, codificación, frecuencia de muestreo y canales |
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset | Las solicitudes de esta clave en este minuto (consulta Límites de velocidad) |
Listar voces
/api/v1/voice/voicesLas voces predefinidas de NueForm y después tus propias voces y las de tus equipos, cada una con su ID nv_…, su idioma, una vista previa gratuita y su ritmo. Gratis.
Parámetros de consulta
sourcestring"all" (predeterminado), "stock" o "mine"
languagestringUn nombre o código de idioma
genderstringPor ejemplo "female"
qstringBuscar en nombres, estilos y etiquetas
featuredbooleantrue: solo las voces predefinidas destacadas
Respuesta
{
"data": [
{
"id": "nv_7QmS2xK9aLpe3vT8a",
"object": "voice",
"name": "Amara",
"source": "stock",
"type": "clone",
"language": "English",
"language_label": "English (US)",
"gender": "female",
"age": null,
"style": "Warm",
"featured": true,
"preview_url": "https://nueform.io/voice-previews/amara.mp3",
"team_id": null,
"can_delete": false,
"chars_per_second": 15.5,
"created_at": null
}
],
"meta": { "count": 1 }
}
Eliminar una voz
/api/v1/voice/voices/:idElimina definitivamente una de tus voces: su muestra, sus prompts y su vista previa, y después la voz. Los créditos no se reembolsan. Mientras formularios o números de teléfono sigan usando la voz, la respuesta es 409 CONFLICT con reason: "voice_in_use" y cuántos; envía ?replacement=nv_… para cambiarlos antes a otra voz.
Respuesta
{
"data": {
"id": "nv_9LmQ2xT4aPe7vK3sW",
"object": "voice",
"deleted": true,
"switched": { "forms": 2, "numbers": 1 },
"forms_to_republish": 1
}
}
Listar generaciones
/api/v1/voice/generationsTus generaciones, de la más reciente a la más antigua. Pasa de página con meta.next_cursor.
Parámetros de consulta
limitintegerDe 1 a 100 (predeterminado 20)
cursorstringnext_cursor de la página anterior
sourcestringSolo las generadas mediante "api", "studio", "mcp" o "app"
Respuesta
{
"data": [
{ "id": "gen_2cH4kXyQ9vLmNp3Rs", "object": "voice.generation", "status": "ready", "credits": { "charged": 30 } }
],
"meta": { "next_cursor": null, "has_more": false }
}
Obtener una generación
/api/v1/voice/generations/:idUna generación, con sus lines si es un guion. Aquí credits.charged es lo que costó en total, después de cualquier devolución automática.
Descargar el audio
/api/v1/voice/generations/:id/audioEl audio en sí, transmitido con tu clave de API (admite rangos de bytes). ?format= es mp3 (predeterminado), wav, ogg_opus o mulaw_8k. Ogg/Opus y μ-law de 8 kHz se generan la primera vez que los pides: un 202 significa "vuelve a pedirlo después de Retry-After segundos". Gratis.
Eliminar una generación
/api/v1/voice/generations/:idElimina la generación y su audio de forma definitiva. Los créditos no se reembolsan. Una generación que todavía se está generando responde 409 CONFLICT con reason: "still_rendering".
Consultar tus créditos
/api/v1/creditsEl saldo del que gasta tu clave, el mes de la clave y la tarifa. Solo lectura, con una clave Voice o una clave de acceso completo.
Campos de respuesta
balanceintegerCréditos que puedes gastar ahora (10.000 créditos = $1)
approxstringEl saldo en dólares
keyobjectmonthly_credit_limit de esta clave (null = ninguno), spent_this_month, paused y resets_at (el día 1, UTC)
voice_apiobjectcredits_per_character (0,4), cómo se redondea y que las estimaciones son gratuitas
rate_cardobjectTodos los precios, por acción
Respuesta
{
"data": {
"object": "credits",
"balance": 48730,
"approx": "≈ $4.87",
"currency": "usd",
"frozen": false,
"key": {
"id_prefix": "nf_a1b2c3d4",
"monthly_credit_limit": 100000,
"spent_this_month": 1240,
"paused": false,
"resets_at": "2026-12-01T00:00:00.000Z"
},
"voice_api": { "credits_per_character": 0.4, "rounding": "up_per_request", "estimate_free": true }
},
"meta": { "rate_card": "1" }
}
Precios
| Qué | Créditos | En dólares |
|---|---|---|
| Voz mediante la API de voz | 0,4 por carácter hablado, en cualquier idioma | unos $0.04 por cada 1.000 caracteres |
| Una estimación | 0 | gratis |
Un clip reutilizado (reuse) | 0 | gratis |
| Una retoma | 0 dos veces dentro de 24 horas (uso justo), después 0,4 por carácter |
Los créditos vienen en paquetes (desde $5 por 50.000 créditos) y nunca caducan. Una clave puede tener un límite mensual de créditos: cuando ha gastado esa cantidad, sus solicitudes de voz y de borrado reciben 403 FORBIDDEN con reason: "key_limit_reached" hasta el día 1 (puede seguir listando y descargando lo que generó), y tus otras claves siguen funcionando. Las solicitudes se pagan con los créditos que el dueño de la clave eligió en Pagar Voice Studio con, en la Billetera: los suyos, salvo que haya elegido un equipo. Un equipo que no puede pagar nunca se cambia por los créditos propios: la solicitud recibe 403 FORBIDDEN con reason: "team_payer_unavailable", o reason: "member_cap_reached" al llegar a su tope mensual como miembro, y no se cobra nada.
Errores
Todos los errores usan el formato de error estándar, y nada que termine en error se cobra. Los más comunes:
| Estado | code | Cuándo |
|---|---|---|
| 402 | INSUFFICIENT_CREDITS | Tu saldo no cubre la solicitud (credits_required, credits_available, top_up_url; payer: "team" cuando el que no alcanza es el equipo con el que paga el dueño de la clave: entonces top_up_url abre la Billetera, donde Pagar Voice Studio con se puede cambiar a sus propios créditos) |
| 403 | FORBIDDEN | reason: key_limit_reached, account_gate, scope_not_allowed, cooldown, voice_studio_suspended, wallet_frozen, member_cap_reached, team_payer_unavailable |
| 409 | CONFLICT | reason: quote_exceeds_max_credits, idempotency_conflict, request_in_progress, unit_rendering |
| 413 | TEXT_TOO_LONG | Más de 5.000 caracteres hablados (max_characters) |
| 422 | CONTENT_BLOCKED, VOICE_UNAVAILABLE, LANGUAGE_NOT_SUPPORTED_BY_VOICE, INVALID_SCRIPT | El texto o las voces no se pueden hablar tal como se enviaron |
| 429 | RATE_LIMITED, CONCURRENCY_LIMIT | Demasiadas solicitudes (consulta Límites de velocidad) |
| 503 | CAPACITY, WARMING_UP, MODERATION_UNAVAILABLE, AI_UNAVAILABLE | Vuelve a intentarlo después de Retry-After segundos |