Empezar
- URL base:
https://app.atentina.com.ar/api/v1/inference - Autenticación:
Authorization: Bearer vaas_..., con una API key que tenga el alcance del motor. - Compatible con el SDK de OpenAI: cambiás la
base_urly la API key. El campomodeles obligatorio en los SDK pero se ignora: el modelo lo fija la plataforma.
- Pedí acceso: te creamos la cuenta con el plan Free (20 minutos por mes, llamadas web, panel y API).
- En el panel, entrá a API > Nueva API key, elegí el alcance y copiala: se muestra una sola vez.
- Hacé el primer pedido:
from openai import OpenAI
client = OpenAI(base_url="https://app.atentina.com.ar/api/v1/inference", api_key="vaas_...")
chat = client.chat.completions.create(
model="atentina", # obligatorio en el SDK, pero se ignora
messages=[{"role": "user", "content": "Hola"}],
)
print(chat.choices[0].message.content)API keys y alcances
Cada key hace solo lo que le diste. Una key puede tener varios alcances; conviene una por sistema y con el mínimo necesario, porque se revoca en el acto si se filtra.
| Alcance | Sirve para |
|---|---|
llm | POST /chat/completions |
stt | POST /audio/transcriptions |
tts | POST /audio/speech y GET /voices |
calls | La API de llamadas, agentes y reportes (no usa los motores) |
Las dos APIs no se cruzan: una key llm no administra agentes ni llamadas, y una key calls no usa los motores.
Endpoints
| Endpoint | Alcance | Qué hace |
|---|---|---|
POST /chat/completions | llm | Chat con el LLM, con o sin streaming |
POST /audio/transcriptions | stt | Transcribe un archivo de audio |
POST /audio/speech | tts | Sintetiza texto con una de las voces |
GET /voices | tts | Voces disponibles |
GET /models | cualquiera | Modelos que sirve la plataforma |
GET /usage | cualquiera | Tu consumo del mes contra el plan |
LLM
Acepta messages, max_tokens, temperature, top_p, stop, seed, response_format, tools, tool_choice y stream. La respuesta trae usage con los tokens de entrada y salida, que es lo que se descuenta.
curl https://app.atentina.com.ar/api/v1/inference/chat/completions \
-H "Authorization: Bearer $ATENTINA_KEY" \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Hola, ¿qué horarios tienen?"}],"max_tokens":200}'Transcripción
Subís el archivo (wav, mp3, flac, ogg…; hasta 25 MB) y, si querés, language. Se descuentan los segundos de audio que informa usage.
curl https://app.atentina.com.ar/api/v1/inference/audio/transcriptions \
-H "Authorization: Bearer $ATENTINA_KEY" \
-F [email protected] -F language=esSíntesis
voice es obligatoria y tiene que ser una de GET /voices (41 voces con nombres argentinos, como sofia o martin). input admite hasta 1.500 caracteres. Se descuentan los segundos de audio generado.
curl https://app.atentina.com.ar/api/v1/inference/audio/speech \
-H "Authorization: Bearer $ATENTINA_KEY" \
-H "Content-Type: application/json" \
-d '{"voice":"sofia","input":"Hola, ¿en qué te puedo ayudar?"}' \
--output respuesta.wavStreaming
El LLM y la síntesis se pueden consumir sin esperar a que termine la respuesta.
LLM: con "stream": true responde SSE como OpenAI: líneas data: {chunk}, un último chunk con usage y data: [DONE].
curl -N https://app.atentina.com.ar/api/v1/inference/chat/completions \
-H "Authorization: Bearer $ATENTINA_KEY" \
-H "Content-Type: application/json" \
-d '{"stream": true, "max_tokens": 200, "messages": [{"role": "user", "content": "Contame algo breve"}]}'Síntesis: tres formas de recibir el audio.
| Pedido | Qué llega | Para qué |
|---|---|---|
response_format: "wav" (default) | El archivo WAV completo, al terminar | Guardar o reproducir un audio ya hecho |
response_format: "pcm" | Bytes PCM crudos (24 kHz, mono, 16 bits) a medida que se sintetizan | Reproducir en vivo o enviarlo a otro sistema |
response_format: "pcm" + stream_format: "sse" | Eventos SSE con el audio en base64 | Navegadores y clientes que ya consumen SSE |
# Escuchar mientras se sintetiza (ffplay viene con ffmpeg)
curl -sN https://app.atentina.com.ar/api/v1/inference/audio/speech \
-H "Authorization: Bearer $ATENTINA_KEY" -H "Content-Type: application/json" \
-d '{"voice":"sofia","input":"Hola, ¿en qué te puedo ayudar?","response_format":"pcm"}' \
| ffplay -f s16le -ar 24000 -ac 1 -nodisp -autoexit -En una medición del 9 de octubre de 2026, el primer audio en pcm llegó a los 53 ms, contra 2,1 s del WAV completo; y el primer token del LLM con stream, a los 32 ms.
Un stream cuenta contra el cupo igual que un pedido normal. Si cortás antes de que termine, se cobra solo lo ya entregado.
Límites y consumo
Los fija tu plan y valen para todas las keys de tu cuenta juntas. Los cupos son por mes calendario (se renuevan el día 1 a las 00:00, hora de Argentina) y están separados por motor: agotar uno no afecta a los otros.
| Límite | Qué mide |
|---|---|
api_llm_input_tokens | Tokens del prompt, por mes |
api_llm_output_tokens | Tokens generados, por mes |
api_tts_minutes | Audio sintetizado, en minutos por mes |
api_stt_minutes | Audio transcripto, en minutos por mes |
api_rate_limit | Pedidos por minuto, entre todas las keys |
- Antes de cada pedido se verifica la key, su alcance, el tope por minuto y el cupo. Si no pasa, el pedido no llega al motor ni se cobra.
- Un pedido que falla en el motor no se cobra.
- En el chat,
max_tokensse achica a lo que te queda de tokens de salida del mes. - La plataforma guarda cuánto consumiste, por key y por día, pero no los prompts, los audios ni los textos.
Para ver tu consumo del mes contra el plan (no gasta cupo):
curl https://app.atentina.com.ar/api/v1/inference/usage -H "Authorization: Bearer $ATENTINA_KEY"Errores
El cuerpo siempre tiene la misma forma:
{"detail": "texto para mostrar", "code": "codigo_estable", "errors": []}| HTTP | code | Cuándo |
|---|---|---|
| 401 | Sin API key, inválida o revocada | |
| 403 | scope_missing | La key no tiene el alcance de ese motor |
| 403 | not_in_plan | El plan no incluye ese motor |
| 429 | rate_limited | Te pasaste de los pedidos por minuto; trae Retry-After |
| 429 | api_* | Se agotó el cupo del mes de ese motor |
| 400 | upstream_rejected | El motor rechazó el pedido (prompt más largo que el contexto, audio ilegible) |
| 400 | payload_too_large | Audio de más de 25 MB: partilo |
| 422 | invalid_request / invalid_voice | Pedido mal armado, o voz inexistente |
| 502 | upstream_error | El motor no responde |
Un 429 por cupo agotado no se arregla reintentando: hay que esperar al día 1 o ampliar el plan. Uno por rate_limited sí, después de los segundos de Retry-After.
Agentes y llamadas
Con una key calls podés crear agentes, lanzar llamadas, recibir el resultado de cada una por API o webhook y descargar reportes. También se puede hacer desde tu agente de programación, con las skills para Claude Code, Cursor y Codex.
Estamos completando esta sección. La referencia de pedidos y respuestas de esta API y de la de llamadas y agentes todavía no está publicada. Si la necesitás ya, pedila y te la pasamos.