Saltar a contenido

Primeros pasos

IRIS expone un contrato de lectura neutral sobre el corpus de marcas de INAPI: una API REST versionada más un servidor MCP, ambos respaldados por la misma capa de consultas y los mismos datos. Esta guía te lleva desde cero hasta una primera llamada autenticada contra la API REST.

El esquema completo y siempre actualizado por campo vive en la referencia OpenAPI interactiva en /docs (Scalar). Esta guía explica cómo hacer la puesta en marcha y enlaza a esa referencia — no reformula el esquema. Cuando un campo no está documentado aquí, /docs es autoritativo.

1. URL base y el prefijo /v1

La API REST la sirve tu operador sobre HTTPS. Cada endpoint del contrato de lectura vive bajo el prefijo de versión /v1, p. ej. https://<iris-host>/v1/brands. A lo largo de esta guía la URL base se escribe como la variable de entorno IRIS_BASE_URL — sustitúyela por el host que tu operador te haya entregado.

export IRIS_BASE_URL="https://<iris-host>"

Un puñado de rutas son intencionalmente públicas (no requieren clave):

Path Propósito
/health Sonda de liveness / readiness (200 ok / 503 degradado)
/docs Referencia OpenAPI (Scalar) interactiva
/metrics Métricas de Prometheus (solo red interna)

Todo lo que está bajo /v1 está protegido y requiere una clave de API (ver más abajo y la guía de autenticación).

2. Obtén una clave de API

Las claves de API las emite el operador, fuera de banda, a través de la CLI de administración. No hay endpoint de registro de autoservicio — tú no creas tu propia clave. Pídele a tu operador una clave de lectura; te entregará una cadena de clave opaca y te dirá qué scopes lleva (brands:read, insights:read, o sin restricción). Consulta la guía de autenticación para los scopes, el ciclo de vida (rotar / revocar / expiración) y la semántica exacta de errores.

Guarda la clave como una variable de entorno y nunca la subas al control de versiones:

export IRIS_API_KEY="iris_xxx"   # the opaque key string your operator issued

Todos los ejemplos de este portal usan el marcador de posición obvio iris_xxx. Reemplázalo por tu clave real en tiempo de ejecución; nunca escribas una clave de forma fija en un archivo versionado.

3. Tu primera llamada autenticada: GET /v1/brands

Envía la clave en el encabezado de solicitud X-API-Key. GET /v1/brands busca o lista resúmenes de marcas.

curl

curl -sS "$IRIS_BASE_URL/v1/brands?q=cafe&limit=5" \
  -H "X-API-Key: $IRIS_API_KEY"

TypeScript (fetch)

const baseUrl = process.env.IRIS_BASE_URL!;
const apiKey = process.env.IRIS_API_KEY!; // "iris_xxx"

const res = await fetch(`${baseUrl}/v1/brands?q=cafe&limit=5`, {
  headers: { "X-API-Key": apiKey },
});

if (!res.ok) {
  const { error } = await res.json();
  throw new Error(`${res.status} ${error.code}: ${error.message} (requestId=${error.requestId})`);
}

const page = await res.json(); // { items: BrandSummary[], nextCursor: string | null }
console.log(page.items.length, "results; nextCursor =", page.nextCursor);

Una respuesta exitosa es una página por keyset:

{
  "items": [
    {
      "nroSolicitud": "123456",
      "nroRegistro": null,
      "denominacion": "CAFE EXAMPLE",
      "estado": "...",
      "tipoSigno": "...",
      "fechaPresentacion": "2023-01-15",
      "fechaVencimiento": null,
      "score": 0.0163
    }
  ],
  "nextCursor": "b2Zmc2V0OjUw"
}

score es el puntaje de relevancia de fusión (RRF) y está presente solo en la ruta de búsqueda de texto libre (q=); se omite en un listado filtrado simple. Para el conjunto exacto de campos de BrandSummary y BrandDetail, consulta la referencia /docs.

4. Filtrado y paginación por keyset

GET /v1/brands acepta estos parámetros de consulta:

Param Type Notas
q string Búsqueda de texto libre (full-text + fuzzy). Cuando está presente, los resultados se rankean y llevan score. Omítelo para un listado filtrado simple.
clase integer Filtro de clase de Niza, 145.
estado string Código de estado (catálogo controlado).
tipoSigno string Código de tipo de signo (catálogo controlado).
fechaDesde YYYY-MM-DD Límite inferior de la fecha de presentación (fecha_presentacion >=).
fechaHasta YYYY-MM-DD Límite superior de la fecha de presentación (fecha_presentacion <=).
limit integer Tamaño de página. Por defecto 20, máximo 100.
cursor string Cursor de keyset opaco (ver más abajo). Trátalo como una caja negra.

La paginación se basa en keyset, no en offset. Cada respuesta lleva un nextCursor:

  • Para obtener la página siguiente, pásalo de vuelta sin cambios como el parámetro de consulta cursor.
  • nextCursor: null significa fin de los resultados — detente.
# page 1
curl -sS "$IRIS_BASE_URL/v1/brands?q=cafe&limit=20" -H "X-API-Key: $IRIS_API_KEY"
# page 2 — pass the nextCursor from page 1
curl -sS "$IRIS_BASE_URL/v1/brands?q=cafe&limit=20&cursor=<nextCursor>" -H "X-API-Key: $IRIS_API_KEY"

Para obtener una marca completa (clases + personas + anotaciones del Estado-Diario), llama a GET /v1/brands/:nroSolicitud:

curl -sS "$IRIS_BASE_URL/v1/brands/123456" -H "X-API-Key: $IRIS_API_KEY"

Un número de solicitud desconocido devuelve 404 not_found.

La familia insights:read (GET /v1/freshness, GET /v1/sync-runs) está documentada en la guía de autenticación y en la referencia /docs.

5. El sobre de error uniforme

Cada error — validación, autenticación, no encontrado, límite de tasa y errores inesperados del servidor — se devuelve con una única forma uniforme:

{ "error": { "code": "unauthorized", "message": "Missing or invalid API key", "requestId": "..." } }
  • code — un token estable y neutral sobre el que puedes ramificar (ver la tabla siguiente).
  • message — una descripción legible por humanos. Las respuestas 5xx usan un mensaje genérico y nunca filtran detalles internos.
  • requestId — correlaciona tu reporte con el log del servidor. También se refleja en el encabezado de respuesta x-request-id; puedes suministrar el tuyo propio mediante el encabezado de solicitud X-Request-Id.
HTTP code Cuándo
400 validation_error Consulta / parámetros inválidos (falló la validación de Zod).
401 unauthorized Clave de API ausente, malformada, desconocida o revocada.
403 forbidden Clave válida, pero le falta el scope que la ruta requiere.
404 not_found Número de solicitud de marca desconocido, o una ruta desconocida.
429 rate_limited Se excedió el límite de ráfaga de corto plazo (ver más abajo).
429 quota_exceeded Cuota mensual agotada (ver más abajo). Lleva Retry-After.
500 internal_error Error inesperado del servidor (no se filtran detalles internos).

6. Límites de tasa y cuota

Dos límites independientes protegen el contrato de lectura:

  1. Límite de ráfaga de corto plazo — un tope de tasa de solicitudes por clave (por defecto 100 solicitudes / minuto). Excederlo devuelve HTTP 429.
  2. Cuota mensual — un presupuesto mensual de solicitudes por clave. Cuando lo agotas, la API devuelve HTTP 429 con code: "quota_exceeded" y un encabezado Retry-After (segundos hasta que la ventana de cuota se reinicia al final del mes). Esta misma cuota aplica de forma idéntica en REST y en el MCP — consulta la guía de MCP.
HTTP/1.1 429 Too Many Requests
Retry-After: 1209600
Content-Type: application/json

{ "error": { "code": "quota_exceeded", "message": "Monthly quota exceeded", "requestId": "..." } }

Respeta Retry-After: espera el número indicado de segundos antes de reintentar.

Próximos pasos

  • Autenticación y scopesX-API-Key, brands:read / insights:read, ciclo de vida de la clave y la semántica completa de 401 / 403 / 429.
  • Conecta tu agente de IA (MCP) — el endpoint mcp.obviouy.com y las herramientas search_brands / get_brand_detail.
  • Ejemplos de código — clientes REST y MCP listos para copiar y pegar.
  • La referencia OpenAPI en vivo en /docs — el esquema autoritativo por campo.