Saltar al contenido
theus.pe ↗

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_...
Las keys se validan por hash (nunca se almacenan en texto plano) y tienen ámbito de inferencia. Una key revocada o expirada responde 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]
El gateway también traduce incompatibilidades comunes por ti: si un modelo de razonamiento upstream exige 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.

RutaFunción
POST /v1/titan/runsValida 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/registerRegistra o rota la identidad de un worker autorizado.
POST /v1/titan/fleet/workers/{worker_id}/heartbeatPublica salud, capacidad y estado de drenaje.
POST /v1/titan/fleet/leases/claimReclama atómicamente un job compatible de la queue.
POST /v1/titan/fleet/leases/{lease_id}/startInicia el lease con token y generación vigentes.
POST /v1/titan/fleet/leases/{lease_id}/heartbeatRenueva el lease, informa progreso y recibe cancelación.
POST /v1/titan/fleet/leases/{lease_id}/completeConfirma resultado y verificación de forma idempotente.
POST /v1/titan/fleet/leases/{lease_id}/failRegistra fallo recuperable o dead-letter al agotar intentos.
POST /v1/titan/runs/{run_id}/cancelCancela la corrida y cerca leases o resultados tardíos.
El perfil productivo v1 es single-active sobre SQLite/WAL. Es durable ante reinicios, pero no se declara HA multi-Gateway. Los workers normales usan scope de propietario; los claims globales de plataforma están deshabilitados por defecto.

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": {…}
}
Cobro la imagen consume el cubo de imagen, que es independiente de tus créditos de texto y no los descuenta (ver Cuotas por plan). Se cuenta por imagen entregada; una generación fallida no consume cuota. Desde el CLI basta pedir «genera una imagen de…» o usar /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.

Desde el CLI no necesitas llamarlo a mano: si le pasas una ruta local como imagen de partida, Theus la publica aquí por ti y usa la URL resultante.
Este tope de 8 MB es solo el de la imagen de partida de imagen→vídeo, que se publica en una URL pública. No lo confundas con el de los adjuntos del chat (/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.

Envíalo como 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 (queuedin_progresscompleted | 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"
Cobro el video consume el cubo de video, independiente de tus créditos de texto. Se cobra con una estimación por segundos al crear el job (el upstream no reporta usage por token en video); consultar el estado y descargar el contenido no consumen cuota adicional. Desde el CLI, el agente crea el job, espera y guarda el .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
  }
}
CampoQué es
weightCuá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 · visionSi sabe llamar herramientas y si sabe leer imágenes.
context_window · max_output_tokensLímites declarados por el proveedor, en tokens.
quality_tierDe 1 a 5, derivado del peso. Es un indicador relativo, no un benchmark.
task_affinityPara qué tipo de trabajo encaja: code, reasoning, planning, tool_use, vision, chat, summarize, cheap_bulk.
quarantinedtrue si el modelo está apartado por fallos recientes del proveedor.
eligibleEl veredicto completo: tu plan, la cuarentena y el estado del despliegue en un solo booleano. Si es false, no lo elijas.
Un modelo sin bloque 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.
El catálogo caduca Entre que lo descargas y envías el turno, tu plan puede cambiar o un modelo entrar en cuarentena. Si mandas la cabecera 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"
  }
}
HTTPcodeQué significa
401unauthorizedAPI key Theus inválida o ausente.
403insufficient_scopeLa credencial no tiene el ámbito de inferencia (p. ej. un token de solo perfil).
404model_not_foundEl modelo pedido no está disponible; el mensaje incluye los modelos servibles hoy.
429rate_limit_exceededSuperaste las solicitudes por minuto de tu plan. Respeta el header Retry-After.
429quota_exceededAgotaste 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.
501streaming_not_supportedStreaming pedido en /v1/responses; usa /v1/chat/completions.
502upstream_errorEl proveedor upstream falló; reintenta o cambia de modelo. Los fallos no consumen cuota de créditos.
503model_gateway_not_configuredEl 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.

PlanSolicitudes/minCréditos incluidos
Free1525
Pro Code601.500
Studio AI1205.000
Max Agent24015.000
Omnipresente24015.000
Omnipotente + Atlas48040.000
Los planes en soles aplican el mismo mecanismo y, desde la paridad plena del 29 de agosto de 2026, con las mismas cifras y los mismos nombres que su plan en dólares: Pro Code 60 rpm y 1.500 créditos · Studio AI 120 y 5.000 · Max Agent 240 y 15.000 · Omnipresente 240 y 15.000 · Omnipotente 480 y 40.000. Solo cambian la moneda y la pasarela. Ver La escalera en soles.
En el plan Free, agotar los créditos cierra la API: todos los modelos responden 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.
El cuerpo del 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.
El uso se contabiliza con el 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.
    ↑↓ navegar · ↵ abrir · esc cerrarDocumentación de Theus