API para desarrolladores (/v1)
El gateway de Theus expone una API compatible con el estándar OpenAI en https://api.theus.pe/v1. Con una sola API key de Theus accedes a todo el catálogo de modelos y a TITAN, sin gestionar keys de ningún proveedor.
Base y autenticación
Base URL: https://api.theus.pe/v1
https://theus.pe/v1 sigue funcionando como alias de compatibilidad permanente; para integraciones nuevas usa siempre el subdominio api.theus.pe.
Crea tu API key desde el dashboard de tu cuenta en theus.pe. El gateway acepta la key de dos formas equivalentes:
# Bearer (recomendado, estilo OpenAI)
Authorization: Bearer theus_mlp_...
# o como header propio
x-api-key: theus_mlp_...
401.POST /v1/chat/completions
Inferencia de chat, compatible OpenAI. Usa cualquier id del catálogo como model — incluido titan, el orquestador. La respuesta nunca expone el modelo upstream: model devuelve el id Theus que pediste.
curl https://api.theus.pe/v1/chat/completions \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "titan",
"messages": [
{"role": "system", "content": "Eres un asistente de código conciso."},
{"role": "user", "content": "Escribe una función en Python que valide un RUC peruano."}
],
"max_tokens": 800,
"stream": false
}'
Respuesta (formato chat.completion estándar):
{
"id": "chatcmpl-…",
"object": "chat.completion",
"model": "titan",
"choices": [
{"index": 0, "message": {"role": "assistant", "content": "…"}, "finish_reason": "stop"}
],
"usage": {"prompt_tokens": …, "completion_tokens": …, "total_tokens": …}
}
Streaming (SSE)
Con "stream": true la respuesta llega como text/event-stream: chunks chat.completion.chunk con deltas, un chunk final con usage y el terminador data: [DONE]. El gateway pide usage al upstream automáticamente (stream_options.include_usage) para facturar con datos reales; el chunk final extra con choices vacíos es estándar e inocuo.
curl -N https://api.theus.pe/v1/chat/completions \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "titan", "messages": [{"role": "user", "content": "Hola"}], "stream": true}'
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"delta":{"content":"…"}}], …}
…
data: [DONE]
max_completion_tokens en lugar de max_tokens, el reintento es automático. Puedes seguir enviando max_tokens clásico.TITAN Fleet Scheduler v1
El control-plane distribuido de TITAN vive en el mismo Gateway. Una corrida crea un DAG durable; los workers oficiales de CLI, Chat y Enterprise reclaman jobs mediante leases exclusivos, mantienen heartbeats y confirman el resultado con fencing e idempotencia. Estas rutas son para runtimes Theus, no para simular trabajo desde un cliente ordinario.
| Ruta | Función |
|---|---|
POST /v1/titan/runs | Valida y crea una corrida durable con plan, presupuesto y capacidades. |
GET /v1/titan/runs/{run_id} | Consulta estado y ledger paginado del propietario. |
POST /v1/titan/fleet/workers/register | Registra o rota la identidad de un worker autorizado. |
POST /v1/titan/fleet/workers/{worker_id}/heartbeat | Publica salud, capacidad y estado de drenaje. |
POST /v1/titan/fleet/leases/claim | Reclama atómicamente un job compatible de la queue. |
POST /v1/titan/fleet/leases/{lease_id}/start | Inicia el lease con token y generación vigentes. |
POST /v1/titan/fleet/leases/{lease_id}/heartbeat | Renueva el lease, informa progreso y recibe cancelación. |
POST /v1/titan/fleet/leases/{lease_id}/complete | Confirma resultado y verificación de forma idempotente. |
POST /v1/titan/fleet/leases/{lease_id}/fail | Registra fallo recuperable o dead-letter al agotar intentos. |
POST /v1/titan/runs/{run_id}/cancel | Cancela la corrida y cerca leases o resultados tardíos. |
POST /v1/embeddings
Embeddings compatibles OpenAI, con el alias del catálogo theus-embed (la memoria semántica del CLI). input acepta un string no vacío o una lista. Passthrough de parámetros estándar: encoding_format, dimensions, user.
curl https://api.theus.pe/v1/embeddings \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "theus-embed",
"input": ["función que valida el token de sesión", "handler de pagos"]
}'
La respuesta es el objeto list de embeddings estándar, con model enmascarado al id Theus. El consumo entra al mismo ledger de tokens que el chat.
POST /v1/images/generations
Generación de imágenes, compatible OpenAI, con los modelos de imagen del catálogo: theus-image-flash (por defecto), theus-image-mini y theus-image-pro. Requiere el plan Omnipresente u Omnipotente o un pack de imagen. La imagen vuelve en la respuesta como b64_json (base64); el gateway no devuelve URLs upstream.
curl https://api.theus.pe/v1/images/generations \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "theus-image-flash",
"prompt": "logo minimalista de una forja, fondo oscuro, trazo dorado",
"size": "1024x1024"
}'
Respuesta:
{
"created": 1767…,
"data": [
{"b64_json": "iVBORw0KGgo…"}
],
"usage": {…}
}
/imagen: el agente llama a este endpoint, guarda el archivo en theus-media/ y además ve una vista previa del resultado para poder corregir el prompt si no cuadra.Editar una imagen
Pasando input_references el modelo transforma las imágenes que le das en vez de crear desde cero: retocar, recolorear, sustituir el fondo o combinar varias. El prompt describe el cambio, no la escena completa.
A diferencia de imagen → video, aquí la imagen puede ir embebida como data URL en base64, además de como enlace: no hace falta publicarla en ningún sitio.
curl https://api.theus.pe/v1/images/generations \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "theus-image-flash",
"prompt": "cambia el fondo a un degradado oscuro y conserva el trazo dorado",
"input_references": [
{
"type": "image_url",
"image_url": {"url": "data:image/png;base64,iVBORw0KGgo…"}
}
]
}'
Cuántas imágenes de partida admite cada modelo: theus-image-flash y theus-image-pro hasta 14; theus-image-mini hasta 16. Editar consume el cubo de imagen igual que generar: una imagen entregada, un cargo.
POST /v1/media/uploads
Publica una imagen con una URL temporal. Existe para imagen → video: el proveedor de video descarga el primer fotograma por HTTP, así que una imagen de tu disco le resulta invisible.
curl https://api.theus.pe/v1/media/uploads \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"data_b64": "iVBORw0KGgo…"}'
{
"url": "https://api.theus.pe/v1/media/in/AbC…xyz.png",
"expires_at": 1767…,
"bytes": 48213
}
La URL devuelta es pública (sin cabecera de autorización, porque quien la descarga es la infraestructura del proveedor), tiene un identificador inadivinable y caduca a las 2 horas. Se admiten PNG, JPEG, GIF y WebP hasta 8 MB; el tipo se determina por la firma real del archivo, no por lo que declares. Hay un tope de imágenes vivas por cuenta: no es un alojamiento permanente.
/v1/chat/blobs), que es de 30 MB y nunca se publica.POST /v1/chat/blobs
Sube un adjunto (imagen o documento) al almacén privado de tu cuenta y devuelve solo una referencia: el binario jamás entra en la conversación ni viaja al modelo en bruto. Es lo que usa el chat web cuando arrastras un archivo.
curl https://api.theus.pe/v1/chat/blobs \
-H "Authorization: Bearer $THEUS_API_KEY" \
-F "file=@informe.pdf"
{
"id": "9f3c…",
"mime": "application/pdf",
"bytes": 24117248,
"extracto_b64": "RUwgcHJveWVjdG8…",
"extracto_chars": 32768,
"truncado": true
}
Límites: 30 MB por archivo, 300 MB de archivos vivos por cuenta y 50 archivos. El tipo se determina por la firma real, no por lo que declares; los ejecutables y los SVG se rechazan. De un PDF con capa de texto se extraen hasta 400 páginas y 128 KB de texto (truncado: true te avisa si se cortó); un PDF escaneado se guarda como adjunto descargable, sin extracto — se te dice, no se finge.
multipart/form-data con el campo file. Se acepta también un JSON con data_b64, pero para archivos grandes es peor: base64 infla el cuerpo un 33% y obliga a materializarlo entero en memoria.POST /v1/videos
Video con los modelos del catálogo: theus-video (por defecto), theus-video-plus, theus-video-max y theus-video-ultra. Requiere el plan Omnipresente u Omnipotente o un pack de video. La generación es asíncrona: crear el clip devuelve un job con id y status, que luego consultas y descargas.
curl https://api.theus.pe/v1/videos \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "theus-video",
"prompt": "un colibrí en cámara lenta sobre flores andinas",
"seconds": 8
}'
Respuesta (job de video):
{
"id": "video_…",
"object": "video",
"model": "theus-video",
"status": "queued",
"progress": 0
}
Cada modelo admite un conjunto propio de duraciones: theus-video de 4 a 12 s, theus-video-plus 5 o 10 s, theus-video-max 6 o 10 s y theus-video-ultra 4, 6 u 8 s. Pedir una duración que el modelo no admite devuelve un error del proveedor.
Imagen → video
Pasando frame_images el modelo anima una imagen en vez de partir de cero, usándola como primer fotograma. La imagen debe ser una URL pública: el proveedor la descarga (usa /v1/media/uploads si la tienes en local).
curl https://api.theus.pe/v1/videos \
-H "Authorization: Bearer $THEUS_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "theus-video",
"prompt": "que el colibrí despegue lentamente",
"seconds": 6,
"frame_images": [
{
"type": "image_url",
"image_url": {"url": "https://api.theus.pe/v1/media/in/AbC…xyz.png"},
"frame_type": "first_frame"
}
]
}'
Los cuatro modelos aceptan first_frame; theus-video y theus-video-ultra aceptan además last_frame para interpolar entre dos imágenes.
GET /v1/videos/{id} — estado del job
curl https://api.theus.pe/v1/videos/video_… \
-H "Authorization: Bearer $THEUS_API_KEY"
Devuelve el mismo objeto video con status (queued → in_progress → completed | failed) y progress. Sondea hasta completed.
GET /v1/videos/{id}/content — descargar el clip
curl -o clip.mp4 https://api.theus.pe/v1/videos/video_…/content \
-H "Authorization: Bearer $THEUS_API_KEY"
.mp4 en theus-media/, o usas /video.GET /v1/models
Catálogo servible en formato lista OpenAI. Solo aparecen los modelos que hoy resuelven a un proveedor operativo; cada entrada añade name, modality, tier y status, más available (si tu plan alcanza ese modelo) y required_plan cuando no lo alcanza.
curl https://api.theus.pe/v1/models \
-H "Authorization: Bearer $THEUS_API_KEY"
El bloque routing
Si vas a elegir el modelo desde tu cliente, cada entrada puede traer un bloque routing con lo necesario para decidir:
{
"id": "claude-opus-4-8",
"name": "Claude Opus 4.8",
"modality": "codigo",
"available": true,
"routing": {
"weight": 5.0,
"tools": true,
"vision": true,
"context_window": 200000,
"max_output_tokens": 32000,
"quality_tier": 4,
"task_affinity": ["code", "tool_use"],
"quarantined": false,
"eligible": true
}
}
| Campo | Qué es |
|---|---|
weight | Cuántos Theus Tokens consume, en proporción. Es el eje de coste: no publicamos precios en dólares, porque lo que te cuesta a ti es tu cuota. |
tools · vision | Si sabe llamar herramientas y si sabe leer imágenes. |
context_window · max_output_tokens | Límites declarados por el proveedor, en tokens. |
quality_tier | De 1 a 5, derivado del peso. Es un indicador relativo, no un benchmark. |
task_affinity | Para qué tipo de trabajo encaja: code, reasoning, planning, tool_use, vision, chat, summarize, cheap_bulk. |
quarantined | true si el modelo está apartado por fallos recientes del proveedor. |
eligible | El veredicto completo: tu plan, la cuarentena y el estado del despliegue en un solo booleano. Si es false, no lo elijas. |
routing no se rutea desde el cliente Significa que no tenemos capacidades declaradas para él, o que es un alias o una utilidad. Preferimos no dar el dato a darlo inventado: una ficha rellenada con supuestos hace que todos los candidatos empaten y la elección acabe dependiendo del orden alfabético. Sigue apareciendo en la lista; simplemente no entra en la decisión automática.X-Theus-Router: cliente y el modelo que elegiste ya no vale, el gateway resuelve el turno con su propio enrutador en vez de rechazarlo. Sin esa cabecera el comportamiento no cambia: recibirás el error correspondiente.POST /v1/responses
Compatibilidad básica con el API Responses: acepta input como texto o lista de mensajes {role, content}, más max_output_tokens, temperature y top_p, y responde un objeto response con output_text. El streaming de Responses no está implementado (501): para streaming usa /v1/chat/completions con stream: true.
Errores
Los errores del gateway usan el formato OpenAI:
{
"error": {
"message": "Alcanzaste el limite de solicitudes por minuto del plan Pro Code. Reintenta en 12 segundos.",
"type": "theus_error",
"param": null,
"code": "rate_limit_exceeded"
}
}
| HTTP | code | Qué significa |
|---|---|---|
| 401 | unauthorized | API key Theus inválida o ausente. |
| 403 | insufficient_scope | La credencial no tiene el ámbito de inferencia (p. ej. un token de solo perfil). |
| 404 | model_not_found | El modelo pedido no está disponible; el mensaje incluye los modelos servibles hoy. |
| 429 | rate_limit_exceeded | Superaste las solicitudes por minuto de tu plan. Respeta el header Retry-After. |
| 429 | quota_exceeded | Agotaste los créditos incluidos en tu plan para el periodo; el mensaje indica la fecha de renovación y Retry-After los segundos hasta entonces. |
| 501 | streaming_not_supported | Streaming pedido en /v1/responses; usa /v1/chat/completions. |
| 502 | upstream_error | El proveedor upstream falló; reintenta o cambia de modelo. Los fallos no consumen cuota de créditos. |
| 503 | model_gateway_not_configured | El gateway autentica pero no hay ningún proveedor upstream disponible (condición de operación, no de tu cuenta). |
Rate limits y cuotas
Cada plan define solicitudes por minuto (por API key) y créditos incluidos por periodo (1 crédito = 1.000 Theus Tokens; ver Cuotas por plan). Ambos límites responden 429 con header Retry-After.
| Plan | Solicitudes/min | Créditos incluidos |
|---|---|---|
| Free | 15 | 25 |
| Pro Code | 60 | 1.500 |
| Studio AI | 120 | 5.000 |
| Max Agent | 240 | 15.000 |
| Omnipresente | 240 | 15.000 |
| Omnipotente + Atlas | 480 | 40.000 |
429 quota_exceeded hasta la renovación. Hubo un «carril gratuito» que dejaba seguir con los modelos de coste cero, y se cerró el 20 de agosto de 2026: esos modelos pasaron a variantes de pago y ahora consumen créditos como el resto. El plan Free son 25 créditos para probar, no una cuota que se reabre sola.429 quota_exceeded incluye, además del bloque en dólares, uno en soles con el primer plan de la escalera peruana que da estrictamente más créditos que los que tenías. Nunca propone un plan de la misma cuota, y nunca inicia un cobro por su cuenta.usage real del upstream cuando existe; si el proveedor no lo reporta, el gateway aplica una estimación conservadora por caracteres. Puedes consultar tu consumo del periodo en el dashboard de tu cuenta.