Referencia de la API
SUB&SUB expone un relay multiproveedor en https://api.subnsub.com/v1. Los clientes de OpenAI llaman a /v1/chat/completions; los clientes de Anthropic llaman a /v1/messages. La misma clave sk-cf-... enruta ambos — elige el modelo en el cuerpo de la solicitud y el relay elige el upstream.
Inicio rápido
Tres cosas que necesitas:
- URL base:
https://api.subnsub.com/v1(clientes de OpenAI) ohttps://api.subnsub.com(clientes de Anthropic — el SDK añade/v1/messagespor sí mismo) - Clave API:
sk-cf-...emitida desde la consola - Modelo: uno de los 21 modelos verificados — p. ej.
gpt-5.4-minioclaude-haiku-4.5
Autenticación
Cada solicitud debe llevar una cabecera Authorization: Bearer sk-cf-.... Las claves se emiten desde la consola y se almacenan como hashes SHA-256 — una vez que abandonas la pantalla de creación, el texto plano desaparece para siempre, así que guárdalo de inmediato.
Endpoints
POST /v1/chat/completions
Envía una solicitud de chat completion. La forma de la solicitud coincide con la API de Chat Completions de OpenAI — los SDK de OpenAI funcionan sin modificaciones.
| Parámetro | Tipo | Descripción |
|---|---|---|
| model | string | Uno de los IDs de modelo verificados. |
| messages | array | Historial de la conversación. Cada elemento: {role, content} con role ∈ system / user / assistant. |
| stream | boolean | Si es true, la respuesta se envía como fragmentos SSE. Consulta Streaming. |
| stream_options | object | Opcional. El relay siempre fuerza {include_usage: true} en el upstream para que el fragmento final lleve el bloque de uso de tokens — sobrescribirlo no tiene efecto. |
| max_tokens | integer | Limita la longitud de la respuesta. Por defecto, el máximo del modelo. |
| temperature | number | 0 – 2. Más alto = más aleatorio. |
POST /v1/messages
Endpoint nativo de Anthropic para los modelos claude-* — el SDK de Anthropic (anthropic-sdk-python, @anthropic-ai/sdk, claude-code) funciona sin modificaciones contra esta ruta. Apunta tu URL base a https://api.subnsub.com y autentícate mediante la cabecera x-api-key (la forma Authorization-Bearer también funciona, si tu cliente lo prefiere).
| Parámetro | Tipo | Descripción |
|---|---|---|
| model | string | Un ID de modelo claude-* (consulta Modelos disponibles). Pasar aquí un modelo de OpenAI devuelve 400 invalid_request_error. |
| max_tokens | integer | Requerido por Anthropic — limita la longitud de la respuesta del asistente. |
| messages | array | Historial de la conversación, forma de Anthropic: {role, content} con role ∈ user / assistant. |
| stream | boolean | Si es true, devuelve la secuencia estándar de eventos SSE de Anthropic: message_start, content_block_delta, message_delta, message_stop. |
| thinking | object | Se reenvía literalmente. Combínalo con una variante de modelo -thinking para habilitar el pensamiento extendido. |
| cache_control | object | El prompt-caching está soportado. Los tokens de escritura en caché se facturan a 1.25× y los de lectura en caché a 0.10× la tarifa de entrada del tier. |
GET /v1/models
Lista los modelos que realmente puedes llamar. El relay fusiona los catálogos de OpenAI y Anthropic de sub2api y los filtra hasta los 21 que hemos probado de extremo a extremo contra el grupo de cuentas actual — los IDs fantasma que dan 503 en el momento del enrutamiento, o un 400 upstream en el primer token, quedan ocultos. Si todos los upstreams configurados son inalcanzables, el endpoint devuelve 502 models_unreachable en lugar de una lista vacía engañosa.
# sample response (truncated)
{
"object": "list",
"data": [
{ "id": "gpt-5.4-mini", "type": "model", ... },
{ "id": "gpt-5.4", "type": "model", ... },
{ "id": "claude-sonnet-4.5", "type": "model", ... },
{ "id": "claude-haiku-4.5", "type": "model", ... },
...
]
}
Modelos disponibles
Dos familias de upstream. Los 7 modelos de OpenAI se enrutan a cuentas compartidas de la gama de ChatGPT; los 14 modelos de Claude se enrutan a través de un proxy inverso de Kiro hacia AWS CodeWhisperer. Las tarifas por token dependen del tier (consulta Precios) — la misma clave funciona para ambos.
OpenAI
| ID del modelo | Familia | Tier | Notas |
|---|---|---|---|
| gpt-5.4-mini | GPT-5.4 | Mini | Rápido y barato. Predeterminado recomendado para chat y programación. |
| gpt-5.3-codex | Codex | Mini | 5.3 afinado para programación. Mismo precio que mini. |
| gpt-5.2 | GPT-5.2 | Standard | 5.2 estable. |
| gpt-5.2-chat-latest | GPT-5.2 | Standard | Sigue automáticamente el último ajuste de chat de 5.2 (actualmente mapea al upstream gpt-5.2). |
| gpt-5.4 | GPT-5.4 | Standard | GPT-5.4 de tamaño completo — más lento, razonamiento más potente. |
| gpt-5.4-2026-03-05 | GPT-5.4 | Standard | Snapshot fechado de gpt-5.4. |
| gpt-5.5 | GPT-5.5 | Premium | Buque insignia más reciente. |
Anthropic
| ID del modelo | Familia | Tier | Notas |
|---|---|---|---|
| claude-haiku-4.5 | Haiku 4.5 | Mini | El Claude más pequeño — misma tarifa por token que gpt-5.4-mini. |
| claude-haiku-4.5-thinking | Haiku 4.5 | Mini | Variante de pensamiento extendido de haiku-4.5. Combínala con el campo de solicitud thinking. |
| claude-sonnet-4.5 | Sonnet 4.5 | Standard | Claude de tier medio — misma tarifa por token que gpt-5.4. |
| claude-sonnet-4.5-thinking | Sonnet 4.5 | Standard | Variante de pensamiento extendido de sonnet-4.5. |
| claude-sonnet-4.6 | Sonnet 4.6 | Standard | Ajuste más reciente de Sonnet — tier Standard, misma tarifa que sonnet-4.5. |
| claude-sonnet-4.6-thinking | Sonnet 4.6 | Standard | Variante de pensamiento extendido de sonnet-4.6. |
| claude-opus-4.5 | Opus 4.5 | Ultra | Claude de frontera. Facturado al precio de lista de Anthropic — sin margen (consulta Precios). |
| claude-opus-4.5-thinking | Opus 4.5 | Ultra | Variante de pensamiento extendido de opus-4.5 (pensamiento adaptativo). |
| claude-opus-4.6 | Opus 4.6 | Ultra | Ajuste más reciente de Opus. |
| claude-opus-4.6-thinking | Opus 4.6 | Ultra | Variante de pensamiento extendido de opus-4.6. |
| claude-opus-4.7 | Opus 4.7 | Ultra | Snapshot anterior de Opus. |
| claude-opus-4.7-thinking | Opus 4.7 | Ultra | Variante de pensamiento extendido de opus-4.7. |
| claude-opus-4.8 | Opus 4.8 | Ultra | Último snapshot de Opus. |
| claude-opus-4.8-thinking | Opus 4.8 | Ultra | Variante de pensamiento extendido de opus-4.8. |
gpt-5.2-pro, gpt-5.2-pro-2025-12-11), gpt-4o, gpt-4o-mini, gpt-5, gpt-5-mini, variantes de imagen / audio / realtime, claude-haiku-4-6 e IDs upstream con fecha (p. ej. claude-sonnet-4-5-20250929). Llamarlos devuelve 400 model_not_available. Los modelos Pro están fuera del menú porque las cuentas subyacentes de tier social del grupo agotarían sus diminutas cuotas en un puñado de solicitudes.
Esfuerzo de razonamiento
Cada modelo de OpenAI anterior es un modelo de razonamiento — el backend puede gastar más o menos tokens de "pensamiento" antes de emitir salida visible. Establece reasoning_effort en el cuerpo de la solicitud de OpenAI /v1/chat/completions para controlar el presupuesto. Para Claude, usa el campo de solicitud nativo de Anthropic thinking (o elige una variante de modelo -thinking) — consulta la sección /v1/messages. Los modelos de OpenAI aceptan los mismos cinco valores de esfuerzo:
| Valor | Comportamiento |
|---|---|
| none | Sin pensamiento — directo a la respuesta. El más barato y rápido. |
| low | Una pasada de razonamiento breve. |
| medium | Predeterminado si no pasas el campo. Equilibrado. |
| high | Razonamiento más profundo. Recomendado para programación no trivial / problemas de varios pasos. |
| xhigh | Esfuerzo máximo. El más lento y caro; resérvalo para análisis difíciles donde realmente lo necesites. |
# Two equivalent forms — pick whichever your SDK supports
{
"model": "gpt-5.4-mini",
"reasoning_effort": "high",
"messages": [ ... ]
}
{
"model": "gpt-5.5",
"reasoning": { "effort": "xhigh" },
"messages": [ ... ]
}
'minimal', pero los modelos de nuestro grupo lo rechazan: "'minimal' is not supported with this model". Limítate a los cinco valores anteriores.
Streaming
Establece "stream": true para recibir Server-Sent Events. El fragmento final lleva un bloque usage (forzamos stream_options.include_usage en el upstream para que los recuentos de tokens siempre se emitan), y luego un literal data: [DONE] cierra el stream.
# Streaming format (line by line)
data: {"id":"resp_...","choices":[{"delta":{"content":"Hi"}}]}
data: {"id":"resp_...","choices":[{"delta":{"content":"!"}}]}
data: {"id":"resp_...","choices":[],"usage":{"prompt_tokens":18,"completion_tokens":11,"total_tokens":29}}
data: [DONE]
Búsqueda web
Añade :online a cualquier ID de modelo soportado por el endpoint y el relay ejecutará una búsqueda web antes de reenviar al modelo, anteponiendo los resultados a la conversación para que la respuesta se base en datos frescos. El sufijo funciona en /v1/chat/completions y /v1/messages (este último sigue requiriendo una base claude-*); no se requiere ningún campo de solicitud específico de búsqueda.
# Same call as before — just :online on the model
curl https://api.subnsub.com/v1/chat/completions \
-H "Authorization: Bearer sk-cf-xxx" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.4-mini:online",
"messages": [
{"role": "user", "content": "What did Anthropic ship this week?"}
]
}'
Cómo funciona: el relay elimina :online, toma el mensaje de usuario más reciente como consulta (limitada a 400 caracteres), llama a Tavily para obtener hasta 3 resultados con el texto extraído de la página cuando esté disponible, más un resumen opcional generado por Tavily, y luego los antepone a ese mismo turno de usuario como un bloque <search_results> claramente delimitado antes de enviar la solicitud al upstream. La llamada de búsqueda tiene un timeout de 8 segundos. Los resultados se inyectan deliberadamente en el rol de usuario — nunca en el system prompt — para que los fragmentos no confiables no puedan elevarse a instrucciones de prioridad de sistema.
El bloque <search_results> tiene este aspecto. Va precedido de una instrucción de una línea que indica al modelo que trate el bloque como datos externos no confiables y que cite los elementos numerados de forma inline:
<search_results query="What did Anthropic ship this week?" retrieved="2026-05-21">
Summary: <short LLM-generated synthesis of the result set>
[1] Anthropic launches Opus 4.8
URL: https://www.anthropic.com/news/opus-4-8
<extracted page text, or short snippet if extraction failed — up to ~2000 chars>
[2] ...
</search_results>
| Comportamiento | Detalle |
|---|---|
| Coste | Sin recargo hoy — pagas la tarifa normal por token del modelo; el relay absorbe la llamada de búsqueda. El bloque <search_results> inyectado sí cuenta como tokens de entrada, así que espera una factura de tokens de prompt mayor que la misma pregunta sin :online. |
| Modo de fallo | Suave. Si Tavily agota el tiempo o falla, la solicitud continúa al modelo sin contexto de búsqueda (sigues obteniendo una respuesta, solo que sin fundamentar). El único fallo duro es 503 search_unavailable cuando la búsqueda no está configurada en el relay en absoluto. |
| count_tokens | /v1/messages/count_tokens elimina el sufijo pero nunca llama a Tavily — el recuento refleja tu prompt original, no el aumentado. |
| Varios turnos | Solo se consulta y aumenta el último turno de usuario; los turnos anteriores quedan intactos. Para buscar de nuevo, envía un nuevo mensaje de usuario con :online aún en el modelo. |
Cuándo usar :online
El relay hace una única llamada a Tavily por solicitud e inyecta los resultados — no es un bucle de búsqueda agéntico. El modelo no decide volver a buscar en función de lo que ve, como hacen Perplexity Sonar o la herramienta de navegación de ChatGPT. Planifica teniendo en cuenta esa limitación:
| Buen encaje | Mal encaje |
|---|---|
| Hechos sensibles al tiempo (noticias, precios, números de versión, fechas de lanzamiento) | Código privado o pegado que no está en la web pública — añade ruido al prompt sin fundamentar |
| Localizar un documento o anuncio oficial | Matemáticas, razonamiento, traducción, escritura creativa — no hay nada que fundamentar |
| Cualquier cosa que de otro modo verificarías buscando en Google | Conocimiento estable que ya está en los datos de entrenamiento ("qué es un árbol binario") |
Formula el último mensaje de usuario como una consulta de búsqueda autónoma. La búsqueda se ejecuta contra el texto literal de tu turno de usuario más reciente (limitado a 400 caracteres), por lo que los seguimientos conversacionales como "¿y qué hay de la última versión?" se convierten en consultas inútiles sin contexto. En un chat de varios turnos, replantea el tema cuando añadas :online — p. ej. "última versión del SDK de Python de Anthropic" en lugar de "la más reciente".
Para preguntas que requieren síntesis de varios pasos (comparar y contrastar, investigación profunda), divídelas en varios turnos y añade :online a cada uno. El modelo leerá los resultados frescos de cada turno; tú diriges la siguiente consulta manualmente. Ten en cuenta que el bloque <search_results> inyectado se envía solo al upstream — no se devuelve a tu cliente y no se conserva en la siguiente solicitud, así que si un turno posterior depende de detalles de fuentes anteriores, pide al modelo que los resuma en su respuesta visible. El modo de investigación en una sola pasada no está soportado.
reasoning_effort: "high") para que el modelo realmente sopese las fuentes devueltas en lugar de apoyarse en el primer resultado. La instrucción inyectada pide al modelo que cite las fuentes numeradas como [1], [2] de forma inline, por lo que la salida normalmente llevará tales citas — aunque el modelo no está estrictamente obligado a ese formato.
Errores
El envoltorio depende del endpoint que hayas llamado — el relay devuelve los errores en el protocolo que coincide con el SDK del llamante, y los errores del upstream se transmiten literalmente.
Rutas de OpenAI (/v1/chat/completions, /v1/responses, /v1/models) — envoltorio de OpenAI:
{ "error": { "message": "...", "type": "...", "code": "..." } }
Rutas de Anthropic (/v1/messages, /v1/messages/count_tokens) — envoltorio de Anthropic:
{ "type": "error", "error": { "type": "...", "message": "..." } }
El envoltorio de Anthropic usa una forma diferente — sin campo code, y el discriminador type: "error" está en el nivel superior (con el error.type interno dando la categoría, p. ej. authentication_error, invalid_request_error, permission_error, api_error). Los SDK de Anthropic ya parsean esta forma; los manejadores de errores del SDK estándar de OpenAI no, así que llama a /v1/messages con un SDK de Anthropic (o haz HTTP en crudo).
Los códigos de estado son los canónicos de HTTP en ambos protocolos:
| Estado | OpenAI code / Anthropic error.type | Significado |
|---|---|---|
| 401 | invalid_api_key / authentication_error | Clave sk-cf-... ausente o desconocida. |
| 402 | insufficient_balance / permission_error | El saldo de la cuenta es negativo. Recarga en la pestaña de facturación de la consola. |
| 403 | key_revoked / permission_error | La clave fue revocada. |
| 400 | model_not_available / invalid_request_error | El model que enviaste no está en el catálogo verificado, o es incorrecto para el endpoint (p. ej. un modelo de OpenAI en /v1/messages) — comprueba Modelos disponibles. |
| 503 | — | Ninguna cuenta upstream atiende actualmente la solicitud — normalmente una ventana de límite de tasa de todo el grupo, no un problema de configuración. |
| 503 | search_unavailable / api_error | Usaste :online pero la búsqueda web no está configurada en este relay. Consulta Búsqueda web. |
| 502 | upstream_unreachable / api_error | El relay no pudo alcanzar el backend. Reintenta tras un breve backoff. |
Precios y facturación
Pago por uso, facturado por token en microdólares (1 micro = $0.000001 = 1/10,000 de un centavo) para que las solicitudes de menos de un centavo se registren con precisión. Las tarifas son por 1M de tokens, por tier — consulta la tabla de modelos para ver a qué tier mapea cada modelo.
| Tier | Modelos | Entrada / 1M | Salida / 1M |
|---|---|---|---|
| Mini | gpt-5.4-mini, gpt-5.3-codex, claude-haiku-4.5, claude-haiku-4.5-thinking | $0.20 | $1.60 |
| Standard | gpt-5.2, gpt-5.2-chat-latest, gpt-5.4, gpt-5.4-2026-03-05, claude-sonnet-4.5, claude-sonnet-4.5-thinking, claude-sonnet-4.6, claude-sonnet-4.6-thinking | $0.75 | $6.00 |
| Premium | gpt-5.5 | $1.10 | $8.80 |
| Ultra | claude-opus-4.5, claude-opus-4.5-thinking, claude-opus-4.6, claude-opus-4.6-thinking, claude-opus-4.7, claude-opus-4.7-thinking, claude-opus-4.8, claude-opus-4.8-thinking | $5.00 | $25.00 |
Las tarifas del tier Ultra coinciden con el precio de lista de Opus publicado por Anthropic — pass-through directo, sin margen. Los otros tiers funcionan por debajo de sus tarifas upstream gracias al respaldo de la suscripción agrupada.
Los tokens de razonamiento (cuando estableces reasoning_effort en OpenAI, o usas una variante -thinking de Claude) cuentan como tokens de salida a la tarifa del tier del modelo — no hay recargo aparte por esfuerzo alto, pero una solicitud de pensamiento profundo puede emitir fácilmente entre 10–50× más tokens de salida que una sin esfuerzo, por lo que la factura en dólares escala con ello.
El prompt-caching de Anthropic se factura como una línea aparte: las escrituras en caché a 1.25× y las lecturas en caché a 0.10× la tarifa de entrada del tier. Así, un acierto de caché de haiku-4.5 cuesta 0.20 × 0.10 = $0.02 per 1M tokens, y un acierto de caché de sonnet-4.5 cuesta 0.75 × 0.10 = $0.075 per 1M tokens. Las columnas de caché se registran en cada fila de liquidación para que la consola pueda mostrar el desglose.
El saldo se descuenta en tiempo real a medida que cada solicitud retorna — para las solicitudes en streaming, la liquidación se ejecuta después de que aterrice el fragmento [DONE]. Consulta tu saldo en vivo y las liquidaciones por solicitud en /console#billing.
Límites de tasa
Hoy no hay límites de tasa por clave. Se aplican la concurrencia del grupo de cuentas upstream y la limitación del lado del servidor de OpenAI; si alcanzas esos límites, el relay devuelve 429 con una cabecera retry-after. Los límites de RPM / TPM por clave llegarán después del MVP.