Visión general
La API pública vive bajo /api/v1. Es de solo lectura, no requiere clave de
API ni autenticación, y tiene un límite de tasa por IP del cliente (300
solicitudes/minuto por defecto). CORS está totalmente abierto
(Access-Control-Allow-Origin: *) — es un dataset público, sin cookies ni
credenciales que proteger.
curl https://aiapipricing.slxd.app/api/v1/models
Envoltorio de la respuesta
Toda respuesta correcta tiene esta forma:
{
"data": /* el payload del endpoint */,
"meta": {
"datasetVersion": "2026-08-19T03:00:00.000Z",
"generatedAt": "2026-08-19T03:00:00.000Z"
/* campos específicos del endpoint, p. ej. count, nextCursor */
}
}
meta.datasetVersion es la marca de tiempo de la ejecución de ingesta que
produjo el dato — el mismo valor que la cabecera de respuesta
x-dataset-version. Dos respuestas con el mismo datasetVersion se
calcularon a partir de la misma ejecución y son seguras de comparar
directamente.
Caché
Las respuestas llevan un ETag débil que cubre tanto la versión del dataset
como la consulta exacta, más Cache-Control: public, max-age=<n>, s-maxage=3600, stale-while-revalidate=86400. Envía If-None-Match en
solicitudes repetidas — una coincidencia devuelve 304 Not Modified sin
cuerpo, mucho más barato que volver a traer el dato. max-age varía por
endpoint (ver abajo); un modelo individual o el registro de fuentes, que
cambian con menos frecuencia, cachean más tiempo que la lista de modelos.
Errores
Los errores son problem details de
RFC 9457
(Content-Type: application/problem+json):
{ "type": "about:blank", "title": "Model not found", "status": 404, "detail": "openai/made-up-model" }
Un 429 incluye además una cabecera Retry-After.
Endpoints
GET /api/v1/meta
Resumen del dataset: contadores y la última ejecución de ingesta. Útil como
comprobación de salud o para leer el datasetVersion actual sin traer nada
más. max-age=60.
{
"data": {
"datasetVersion": "2026-08-19T03:00:00.000Z",
"generatedAt": "2026-08-19T03:00:00.000Z",
"models": 842,
"providers": 37,
"prices": 3110,
"lastRun": { "id": "128", "status": "ok", "finishedAt": "2026-08-19T03:00:00.000Z" },
"rates": { "contractVersion": 2, "officialSources": ["official_scrape"] }
}
}
GET /api/v1/providers
Todos los proveedores del catálogo, con su número de modelos.
Son las casas que fabrican los modelos. Quien revende —Vertex, Bedrock, Azure, OpenRouter, el catálogo de Alibaba, un plan de suscripción— es un canal de venta y no un proveedor, así que no sale aquí: el mismo modelo es un solo modelo, vendido a varios precios.
| Campo | Tipo | Notas |
|---|---|---|
slug | string | p. ej. openai, anthropic |
name | string | Nombre para mostrar |
website | string | null | |
pricingUrl | string | null | La página de precios propia del proveedor |
official | boolean | Si es el listado propio del fabricante (ver Introducción) |
models | number | Número de modelos de este proveedor |
GET /api/v1/models
Lista paginada de modelos.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
q | string | — | Coincidencia de texto libre contra el slug y el nombre |
provider | string | — | Slugs de proveedor separados por comas, p. ej. openai,anthropic |
confidence | string | — | Uno de verified, high, medium, low, unverified |
limit | number | 50 | 1–500 |
cursor | string | — | Cursor opaco tomado del meta.nextCursor de una respuesta anterior |
La paginación es por keyset (nunca por offset), así se mantiene rápida
incluso con miles de filas. meta.nextCursor es null en la última página.
curl "https://aiapipricing.slxd.app/api/v1/models?provider=anthropic&limit=20"
Cada modelo en data tiene esta forma (la misma que devuelven GET /api/v1/models/{provider}/{model} y GET /api/v1/compare):
{
"id": "anthropic/claude-sonnet-4-5",
"provider": "anthropic",
"slug": "claude-sonnet-4-5",
"name": "Claude Sonnet 4.5",
"family": "claude-4",
"contextWindow": 200000,
"maxOutputTokens": 64000,
"openWeights": false,
"firstSeenAt": "2026-02-11T00:00:00.000Z",
"lifecycle": { "state": "active", "releasedOn": "2026-02-11", "deprecatedOn": null, "retiresOn": null },
"prices": [
{
"label": "Input",
"direction": "input",
"modality": "text",
"tier": "standard",
"cache": "none",
"contextMin": 0,
"contextMax": null,
"qualifiers": {},
"amount": 3,
"displayUnit": "per 1M tokens",
"denomination": "currency",
"currency": "USD",
"confidence": "verified",
"confidenceScore": 0.95,
"sources": ["anthropic-pricing-page"],
"dissenting": [],
"disputed": false,
"fallbackAmount": null,
"effectiveFrom": "2026-02-11T00:00:00.000Z",
"staleSince": null
}
]
}
amount siempre está en unidades de visualización (p. ej. dólares por
millón de tokens), nunca en unidades base sin convertir — quien compare 3
contra 0.000003 ya ha perdido.
Dos dimensiones de precio pueden compartir label — la búsqueda web se cobra
por tamaño de contexto y las tres se llaman «Web search» — así que las que
coincidirían dentro del mismo modelo se desempatan con sus cualificadores:
Web search (context size: high). El objeto qualifiers en crudo sigue ahí
para uso estructurado.
GET /api/v1/models/search
Sugerencias para un buscador: el mismo filtro y el mismo orden que GET /api/v1/models, pero solo lo que necesita un selector — el id y cómo se lee.
Úsalo mientras se completa el nombre de un modelo; para los precios, GET /api/v1/models.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
q | string | — | Coincidencia de texto libre contra el slug y el nombre. Sin él, la cabecera del catálogo |
limit | number | 10 | 1–50 |
{
"data": [
{ "id": "anthropic/claude-sonnet-4-5", "label": "Claude Sonnet 4.5 · Anthropic" }
],
"meta": { "count": 1 }
}
La etiqueta lleva el proveedor porque el mismo modelo aparece bajo varias pasarelas, y el nombre a secas se repite.
GET /api/v1/models/{provider}/{model}
Un modelo concreto por slug de proveedor y slug de modelo, p. ej.
/api/v1/models/anthropic/claude-sonnet-4-5. 404 (problem detail) si no
existe. max-age=3600.
Por defecto los precios son los de quien fabrica el modelo. Con ?channel= se piden los de quien lo revende — uno de direct, vertex, bedrock, azure, alibaba, openrouter, coding_plan, token_plan, other. Un canal que no vende este modelo devuelve la ficha con prices vacío; un canal que no existe es un 400.
curl "https://aiapipricing.slxd.app/api/v1/models/anthropic/claude-opus-5?channel=bedrock"
GET /api/v1/models/{provider}/{model}/history
El historial de precios de ese modelo — un punto por cambio, no uno por
día, ya que los precios son funciones escalonadas. Añade from / to
(fechas ISO, inclusive) para acotar el rango. max-age=3600.
Una serie por dimensión de precio, no por etiqueta: dos dimensiones pueden
compartir nombre (la búsqueda web se cobra por tamaño de contexto y las tres se
llaman «Web search»), así que las series que coincidirían se desempatan con sus
cualificadores — Web search (context size: high). Dentro de una serie, los
puntos consecutivos con el mismo importe se funden en el primero: repetir un
importe no es un cambio.
Cada punto es [fecha, importe], con la fecha en YYYY-MM-DD. Si un precio
cambió dos veces el mismo día, se devuelven los dos puntos con la misma fecha,
en orden: plegarlos escondería un cambio de precio que ocurrió de verdad.
{
"data": [
{ "label": "Input", "displayUnit": "per 1M tokens", "points": [["2026-02-11", 3], ["2026-06-01", 2.5]] }
],
"meta": { "model": "anthropic/claude-sonnet-4-5", "granularity": "change" }
}
GET /api/v1/compare?models=
Precios lado a lado de 2 a 8 modelos, separados por comas como
provider/slug:
curl "https://aiapipricing.slxd.app/api/v1/compare?models=openai/gpt-5,anthropic/claude-opus-5"
data es un array con la misma forma de modelo que /api/v1/models, en el
orden encontrado (los ids desconocidos se descartan en silencio — compara
meta.found con meta.requested). 400 si se pasan menos de dos ids. Los
importes facturados en créditos nunca se convierten a dinero, así que un
modelo facturado en créditos no es comparable a uno facturado en tokens por
su amount en crudo.
GET /api/v1/changes
Movimientos de mercado recientes, de más reciente a más antiguo: subidas,
bajadas, retiradas y cambios de unidad. Es el equivalente JSON de
/changes.xml, con los mismos filtros.
Por defecto no incluye altas de catálogo (price_added, coverage_added,
reference_changed): esas son «Nuevos en el catálogo», no un cambio de
precio, y solo aparecen aquí si se piden explícitamente con kind.
| Parámetro | Tipo | Por defecto | Notas |
|---|---|---|---|
days | number | 30 | Ventana de consulta hacia atrás |
limit | number | 100 | Máximo de filas (tope en 500) |
provider | string | — | Solo los cambios de este proveedor (su slug) |
model | string | — | Solo los cambios de este modelo (su slug, sin el proveedor) |
q | string | — | Texto libre: busca por slug y por nombre visible, del modelo y de su proveedor (2026-09-17) |
kind | string | los cuatro de mercado | Uno o varios, separados por coma: price_increase, price_decrease, price_removed, unit_change, price_added, coverage_added, reference_changed. Un valor que no existe es 400. |
{
"data": [
{
"kind": "price_increase",
"model": "openai/gpt-5",
"modelName": "GPT-5",
"providerName": "OpenAI",
"label": "Output",
"oldAmount": 10,
"newAmount": 12,
"deltaPct": 20,
"occurredAt": "2026-08-01T00:00:00.000Z"
}
]
}
GET /api/v1/sources
Todas las fuentes de datos configuradas y su salud — peso, licencia, si es
autoritativa, cuándo tuvo éxito por última vez y su último error si lo hubo.
Así se puede juzgar cuánto confiar en un precio más allá del campo
confidence por precio. max-age=900.
{
"data": [
{
"source": "anthropic-pricing-page",
"name": "Anthropic pricing page",
"license": null,
"homepage": "https://www.anthropic.com/pricing",
"weight": 10,
"authoritative": true,
"lastSuccessAt": "2026-08-19T03:00:00.000Z",
"lastError": null,
"rowsLastRun": 24
}
]
}
GET /api/v1/rates
La tarifa de coste de cada modelo cobrable, estrechada a lo que un
facturador necesita: tokens de texto, tarifa estándar, sin caché y sin tramo
de contexto, un número por dirección. Es el endpoint que consumen las
aplicaciones SLXD para cobrar créditos de IA — el margen lo aplica la
plataforma (coste × 2 con suelo de 1 crédito por operación), aquí solo está el
hecho. max-age=3600.
Filtro opcional ?provider=anthropic,openai (hasta 50). Sin paginar: el
consumidor la quiere entera y el ETag evita reenviarla mientras el dataset no
cambie. Un modelo sin las dos direcciones publicadas se omite — mejor ausente
que a medias.
{
"data": [
{
"id": "anthropic/claude-opus-5",
"provider": "anthropic",
"slug": "claude-opus-5",
"currency": "USD",
"inputPerMTok": 15,
"outputPerMTok": 75,
"cachedInputPerMTok": 1.5,
"confidence": "verified",
"confidenceScore": 95,
"agreeingSources": ["models_dev", "official_scrape"],
"sourceCount": 2,
"official": true,
"disputed": false,
"staleSince": null,
"aliases": ["claude-opus-5-20260101"]
}
]
}
Versión 2 del contrato (2026-09-17). Cada tarifa declara además de dónde
sale, para que quien cobre con ella pueda decidir por política:
confidenceScore (0-100), agreeingSources (las fuentes que respaldan las
dos direcciones, no la unión de ambas), sourceCount (cuántas se
pronunciaron sobre la pata más floja), official (la página de precios del
propio fabricante está entre ellas) y disputed. Son campos nuevos: nada
se ha renombrado y un cliente de la versión 1 sigue leyendo lo mismo.
GET /api/v1/meta devuelve la versión del contrato y qué fuentes cuentan como
oficiales (rates.contractVersion, rates.officialSources), para no llevar
esa tabla escrita a mano.
El endpoint no filtra por confianza: publica el hecho entero y la política
la pone quien consume. Las aplicaciones SLXD, desde el 2026-09-17, solo cobran créditos
contra tarifas verified u official y cae a su catálogo estático con el
resto.
Niveles de confianza
Todo precio lleva un confidence y un confidenceScore, además de qué
fuentes coinciden (sources) y cuáles discrepan (dissenting):
| Nivel | Significado |
|---|---|
verified | Confirmado directamente en la página de precios del proveedor |
high | Fuerte coincidencia entre fuentes independientes |
medium | Cierta coincidencia, o una única fuente razonablemente fiable |
low | Evidencia débil o parcial |
unverified | Aún sin corroborar — tratar con cautela |
disputed: true significa que al menos una fuente discrepa activamente del
amount publicado; fallbackAmount (cuando está presente) es lo que el
catálogo mostraría si la fuente principal fallara.
Ver también
El mismo catálogo se puede consultar desde un asistente de IA a través del conector MCP, que refleja estos endpoints uno a uno para que un modelo nunca cite un precio distinto al de esta API.