UtteraUttera

Autenticación

Cabecera Authorization: Bearer sk-echo-... en todas las peticiones. La clave se muestra una sola vez al crearla: guárdala. Si la pierdes, revócala y crea otra.

No la pongas en el navegador. La clave da acceso a tu bolsa de créditos. Llama a la API desde tu servidor, nunca desde código que el usuario final pueda leer.

Restringir una clave a unas IPs

Cada clave puede limitarse a las direcciones desde las que tiene sentido que se use. Si tu integración vive en un servidor con IP fija, una clave robada deja de servir de nada fuera de él.

Se configura en tu cuenta, en la columna IPs permitidas de cada clave. Se admiten direcciones sueltas y redes:

203.0.113.7, 198.51.100.0/24, 192.0.2.10

En blanco, la clave funciona desde cualquier sitio, que es el comportamiento por defecto.

Una petición desde una IP que no está en la lista recibe 403 con el código ip_not_allowed y, en el cuerpo, la IP que hemos visto — que es justo lo que necesitas para añadirla si te has dejado una:

{
  "error": "ip_not_allowed",
  "message": "This API key is restricted to a list of IP addresses and this request does not come from one of them",
  "client_ip": "203.0.113.55"
}
Es un 403, no un 401. La clave es buena; lo que no vale es el sitio desde el que llama. Distinguirlo importa: un 401 te haría rotar una clave que estaba perfectamente.

La restricción cubre todos los endpoints autenticados, incluido /v1/usage/last. Quien roba una clave no siempre quiere gastarla; a veces le basta con ver cuánto gasta su dueño.

Antes de restringir una clave en producción, comprueba desde qué IP sales de verdad. No siempre es la que crees: detrás de un NAT, de un balanceador o de una salida a internet con varias líneas, tu tráfico puede aparecer desde direcciones distintas. Lanza una petición, mira el client_ip que te devuelve el 403, y añade esa.

Análisis en la misma petición

Una transcripción puede traer análisis de voz sin subir el audio otra vez. Se piden en la cadena de consulta, separados por comas:

curl https://api.uttera.ai/v1/audio/transcriptions?extras=sentiment,profile,diarize \
  -H "Authorization: Bearer $UTTERA_API_KEY" \
  -F file=@grabacion.m4a \
  -F model=whisper-1
ExtraDevuelveEn la respuesta
sentimenttono emocionalsentiment
profileperfil del hablante (edad, género)profile
diarizequién habla y cuándodiarize

Los tres corren en paralelo sobre el mismo audio, así que pedir los tres tarda casi lo mismo que pedir uno. Cada uno se cobra aparte, y solo si se ejecuta: si un análisis falla, la transcripción llega igual y la respuesta trae un array errors diciendo cuál faltó — y ese no se factura.

sentiment necesita plan Developer o superior; profile y diarize, cualquier plan con inteligencia de audio. Un nombre que no sea uno de los tres devuelve 400 con la lista válida, no una transcripción silenciosamente sin análisis.

Para sentiment con nivel por segmentos o dimensional (valencia, activación, dominancia), use el endpoint suelto /v1/audio/sentiment: en extras va siempre el nivel global.

Formatos e idiomas

Audio de entrada: wav, mp3, flac, ogg, opus, aiff, m4a y webm — los mismos para transcribir y para analizar. webm es lo que graba un navegador y m4a lo que graba un móvil, así que ambos sirven tal cual.

Audio de salida (response_format de voz): wav, mp3, opus, flac y pcm. pcm es PCM crudo sin cabecera, así que por la webapp no se ofrece —no lo reproduce un navegador— y al usarlo por API hay que decirle al decodificador los cuatro parámetros, porque el fichero no los lleva:

VozFrecuenciaMuestraCanalesOrden
estándar24 000 Hz16 bits con signo1 (mono)little-endian
HD48 000 Hz16 bits con signo1 (mono)little-endian

La frecuencia es la nativa de cada voz y no se remuestrea: la HD genera a 48 kHz y se entrega tal cual. Lo único que cambia entre los dos es la frecuencia; decodificarlo con la que no toca no suena peor, suena al doble o a la mitad de velocidad. Con wav, flac u opus esto no aplica: el fichero lo declara solo.

# voz estándar
ffmpeg -f s16le -ar 24000 -ac 1 -i voz.pcm voz.wav
# voz HD
ffmpeg -f s16le -ar 48000 -ac 1 -i voz.pcm voz.wav

Cualquier otro valor de response_format devuelve 422 con la lista válida.

Tamaño: hasta 400 MB por petición y 3 horas de audio, con un tope de 100 MB de fichero en transcripción. Un WAV de 3 horas pesa unos 346 MB y no pasa ese tope: para audios largos, envíelo comprimido.

Transcripción: detecta el idioma automáticamente y cubre los que soporta Whisper.

Voz: depende del motor, y la diferencia es grande. La voz estándar (tts-1) habla los nueve de la tabla de abajo. La voz de alta calidad (tts-1-hd) habla unos 30 —además de esos nueve, alemán, ruso, polaco, neerlandés, los nórdicos, griego, turco, árabe, coreano y varios del sudeste asiático, entre otros— y no hace falta declarar el idioma: se deduce del texto. Está explicado en Tres voces, no dos.

Traducción: ~50 idiomas de texto. La cadena sintetiza con la voz estándar, así que con voz son estos nueve:

CódigoIdiomaCódigoIdioma
eninglésititaliano
en-gbinglés británicojajaponés
esespañolptportugués
frfrancészhchino
hihindi

Catálogo de voces

Voces estándar disponibles con model: tts-1:

alloy · echo · fable · nova · onyx · shimmer

El catálogo ampliado está en revisión; se publicará cuando esté cerrado.

Créditos

Cada servicio cobra por lo que consume. Estos son los coeficientes vigentes:

ServicioSe cobra porCréditosUna hora de audio
Transcribirsegundo de audio de entrada0,032673117,6
Voz estándarsegundo de audio generado0,02100475,6
Voz clonadasegundo de audio generado0,4067481.464,3
Tonosegundo de audio0,00509018,3
Perfil del hablantesegundo de audio0,00346412,5
Interlocutoressegundo de audio0,02093875,4
Traducciónsegundo de audio de entrada0,080000288,0
Resumen (LLM)token de entrada0,001605
Resumen (LLM)token de salida0,080650
Un token de salida cuesta 54 veces uno de entrada. Generar es mucho más caro que leer, y por eso el tramo del modelo domina la factura de un resumen aunque la transcripción sea larga.

Cómo se compone cada servicio

ServicioFórmula
TranscribirSTT
Transcribir + tonoSTT + tono
VozTTS sobre los segundos generados
TraducirSTT + TTS del audio generado + recargo de traducción
ResumirSTT + perfil + interlocutores + tokens del modelo

Ejemplo real

Una grabación de 40 minutos (2.424 s) traducida al inglés con voz:

transcripción     79,22   2.424,5 s x 0,032673
voz               43,18   2.055,8 s x 0,021004   (el inglés sale ~15 % más corto)
traducción       193,96   2.424,5 s x 0,080000
                 ──────
                 316,36 créditos
Se cobra el audio que se genera, no el que subes. Al traducir, el idioma destino casi nunca dura lo mismo que el origen.

Planes y límites

Plan€/mesCréditosConcurrenciaVoz alta calidadClonadoResumirSLA
Free05001
Startup197.5003
Developer9950.00015
Professional299200.0005095,0 %
Business999800.00015099,0 %
Enterprisea medidaa medidaa medida99,9 %

Los créditos se renuevan en la fecha de tu suscripción, no el día 1. Si cambias de plan a uno menor, conservas los créditos ya pagados hasta que venza el periodo.

Límites por segundo

PlanVozTranscripciónAnálisis
Free11
Startup5205
Developer10040050
Professional2501.000200
Business5002.000500

Cada respuesta lleva X-RateLimit-Remaining-Second y X-Credits-Remaining-Monthly para que no tengas que adivinar.

Errores

CódigoQué significaQué hacer
400El fichero no se puede decodificar, o un parámetro no vale.El motivo viene en detail.
401Clave ausente, mal formada o revocada.Revisa la cabecera Authorization.
402Bolsa de créditos agotada.Espera a la renovación o sube de plan.
403Tu plan no incluye ese servicio.El mensaje dice qué plan lo incluye.
413Fichero demasiado grande.Trocea o comprime el audio.
422Petición válida pero imposible de servir.Por ejemplo, audio en un idioma sin voz. No se cobra.
429Demasiadas peticiones por segundo.Respeta Retry-After.
502 503Fallo temporal de un nodo.Se reintenta solo una vez. Reintenta tú pasados unos segundos.
Si una etapa falla, no se cobra. En las cadenas de varios pasos —traducir, resumir— un fallo intermedio devuelve el error sin cargar créditos, y un fallo parcial devuelve lo que sí se pudo hacer con un aviso, cobrando solo esa parte.

Consultar el consumo

El cargo se calcula después de enviarte la respuesta, así que no viene dentro de ella. Para saber lo que te ha costado exactamente una petición:

GET /v1/usage/last
GET /v1/usage/last?endpoint=/v1/summarize

Devuelve los créditos cobrados y el desglose por tramo:

{
  "endpoint": "/v1/summarize",
  "credits": 108.978,
  "breakdown": { "stt": 3.1255, "diarize": 2.0029,
                 "profile": 0.1946, "llm": 103.655 },
  "audio_seconds": 95.66,
  "input_tokens": 2776, "output_tokens": 1230
}

Guarda los diez últimos cargos durante una hora. Es para comprobar al momento, no un histórico de facturación.

Cuánto tarda cada cosa

Números medidos, no promesas. Varían con el nodo que atienda y con la carga del momento:

OperaciónTiempo típico
Transcribir 100 minutos de audio10 a 35 s
Transcribir una grabación de 40 minutosmenos de 30 s
Voz estándar, una frasedécimas de segundo
Voz clonadaBastante más: la muestra hay que procesarla
Acierto de cachémilisegundos
Resumen de una grabación largaEl más lento de sus tramos, no la suma: corren en paralelo

Lo que de verdad hay que configurar bien es el tiempo de espera de tu cliente: el servidor mantiene la conexión hasta 7200 segundos, y el fallo más común al integrar es un cliente con 30 segundos por defecto que corta trabajos que iban perfectamente. Está explicado en Integración.

Versionado y cambios

Lo que integras hoy tiene que seguir funcionando mañana. Este es el compromiso:

Seis meses de preaviso para cualquier cambio que rompa. Si algún día tenemos que cambiar algo de forma incompatible, la versión anterior sigue funcionando al menos seis meses desde que lo anunciamos, y te avisamos por correo a la dirección de tu cuenta.

Para que eso signifique algo, hace falta decir qué cuenta como romper y qué no:

Rompe (seis meses de preaviso)No rompe (puede pasar cualquier día)
Quitar un endpoint o un parámetroAñadir un endpoint nuevo
Quitar o renombrar un campo de la respuestaAñadir un campo a la respuesta
Cambiar el tipo o el significado de un campoAñadir un parámetro opcional
Cambiar el valor por defecto de un parámetroAñadir una voz o un idioma
Hacer obligatorio algo que era opcionalAñadir una cabecera de respuesta
Cambiar un código de error por otro distintoMejorar el texto de un mensaje de error

De ahí sale la regla práctica para tu código: ignora los campos que no conozcas en vez de fallar al encontrarlos. Un cliente que revienta porque la respuesta trae una clave nueva se romperá solo, sin que nadie haya roto nada.

Los precios son caso aparte: no son la interfaz, pero sí tu factura. Una subida de coeficientes se anuncia con treinta días y no se aplica a un ciclo ya pagado. Una bajada se aplica en cuanto está.

Estado del servicio

Si algo va mal, lo primero es saber si es tuyo o nuestro.

GET https://api.uttera.ai/health responde sin necesidad de clave y dice si la API está en pie. Es la comprobación que puedes automatizar.

curl -s https://api.uttera.ai/health

Cada respuesta lleva además una cabecera X-Request-Id. Guárdala cuando algo falle: con ese identificador podemos decirte exactamente qué pasó con tu petición, y sin él la conversación empieza por reconstruir cuál era.

Para cualquier incidencia, escríbenos con el X-Request-Id, la hora aproximada y qué esperabas que pasara.

Una página pública de estado con el histórico de incidencias está en camino. Mientras tanto, /health y el identificador de petición cubren lo que de verdad se necesita para resolver un problema concreto.

En estudio

Cosas que nos piden, que tienen sentido y que todavía no están. Las ponemos aquí porque enterarte de que algo no existe después de integrarlo es peor que saberlo ahora:

QuéPara quéEstado
WebhooksQue te avisemos al terminar un trabajo largo, en vez de mantener la conexión abiertaPor decidir
Diccionario de pronunciaciónDecirle al motor cómo se pronuncian nombres propios, marcas y siglasPor decidir
Página pública de estadoHistórico de disponibilidad e incidenciasEn camino
Cuentas de servicio y varios usuariosQue una empresa tenga varias personas y claves separadas bajo una misma cuentaDespués de la beta

Si alguna de ellas te bloquea, dínoslo: lo que nos piden los clientes es lo que decide el orden.