Ir para o conteúdo

Primeiros passos

O IRIS expõe um contrato de leitura neutro sobre o corpus de marcas do INAPI: uma API REST versionada mais um servidor MCP, ambos apoiados na mesma camada de consultas e nos mesmos dados. Este guia leva você do zero à primeira chamada autenticada contra a API REST.

O schema completo, sempre atualizado e por campo, vive na referência OpenAPI interativa em /docs (Scalar). Este guia explica como fazer os primeiros passos e aponta para essa referência — ele não reafirma o schema. Quando um campo não estiver documentado aqui, /docs é autoritativo.

1. URL base e o prefixo /v1

A API REST é servida pelo seu operador sobre HTTPS. Todo endpoint do contrato de leitura vive sob o prefixo de versão /v1, por exemplo https://<iris-host>/v1/brands. Ao longo deste guia a URL base é escrita como a variável de ambiente IRIS_BASE_URL — substitua pelo host que seu operador lhe deu.

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

Um punhado de caminhos são intencionalmente públicos (não exigem chave):

Caminho Finalidade
/health Sonda de liveness / readiness (200 ok / 503 degradado)
/docs Referência OpenAPI (Scalar) interativa
/metrics Métricas Prometheus (somente rede interna)

Tudo sob /v1 é protegido e exige uma chave de API (veja abaixo e o guia de autenticação).

2. Obtenha uma chave de API

As chaves de API são emitidas pelo operador, fora de banda, via CLI de administração. Não há endpoint de cadastro self-service — você não cria sua própria chave. Peça ao seu operador uma chave de leitura; ele lhe entregará uma string de chave opaca e informará quais escopos (scopes) ela carrega (brands:read, insights:read ou irrestrita). Veja o guia de autenticação para escopos, ciclo de vida (rotacionar / revogar / expirar) e a semântica exata de erro.

Guarde a chave como variável de ambiente e nunca a comite no controle de versão:

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

Todos os exemplos deste portal usam o placeholder óbvio iris_xxx. Substitua-o pela sua chave real em tempo de execução; nunca embuta uma chave em um arquivo comitado.

3. Sua primeira chamada autenticada: GET /v1/brands

Envie a chave no header de requisição X-API-Key. GET /v1/brands busca ou lista resumos 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);

Uma resposta bem-sucedida é uma página keyset:

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

score é o score de relevância por fusão (RRF) e está presente somente no caminho de busca por texto livre (q=); é omitido em uma listagem apenas filtrada. Para o conjunto exato de campos de BrandSummary e BrandDetail, veja a referência /docs.

4. Filtragem e paginação por keyset

GET /v1/brands aceita estes parâmetros de consulta:

Parâmetro Tipo Notas
q string Busca por texto livre (full-text + fuzzy). Quando presente, os resultados são ranqueados e carregam score. Omita-o para uma listagem apenas filtrada.
clase integer Filtro de classe de Nice, 145.
estado string Código de status (catálogo controlado).
tipoSigno string Código de tipo de signo (catálogo controlado).
fechaDesde YYYY-MM-DD Limite inferior da data de apresentação (fecha_presentacion >=).
fechaHasta YYYY-MM-DD Limite superior da data de apresentação (fecha_presentacion <=).
limit integer Tamanho da página. Padrão 20, máximo 100.
cursor string Cursor de keyset opaco (veja abaixo). Trate-o como uma caixa-preta.

A paginação é baseada em keyset, não em offset. Cada resposta carrega um nextCursor:

  • Para buscar a próxima página, passe-o de volta sem alteração como o parâmetro de consulta cursor.
  • nextCursor: null significa fim dos resultados — pare.
# 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 buscar uma marca por completo (classes + pessoas + anotações do Estado-Diário), chame GET /v1/brands/:nroSolicitud:

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

Um número de solicitação desconhecido retorna 404 not_found.

A família insights:read (GET /v1/freshness, GET /v1/sync-runs) está documentada no guia de autenticação e na referência /docs.

5. O envelope de erro uniforme

Todo erro — validação, autenticação, não encontrado, limite de taxa e erros inesperados de servidor — é retornado com um único formato uniforme:

{ "error": { "code": "unauthorized", "message": "Missing or invalid API key", "requestId": "..." } }
  • code — um token estável e neutro sobre o qual você pode fazer switch (veja a tabela abaixo).
  • message — uma descrição legível por pessoas. Respostas 5xx usam uma mensagem genérica e nunca vazam detalhes internos.
  • requestId — correlaciona seu relato com o log do servidor. Também é ecoado no header de resposta x-request-id; você pode fornecer o seu próprio via o header de requisição X-Request-Id.
HTTP code Quando
400 validation_error Consulta / parâmetros inválidos (falha de validação Zod).
401 unauthorized Chave de API ausente, malformada, desconhecida ou revogada.
403 forbidden Chave válida, mas sem o escopo que a rota exige.
404 not_found Número de solicitação de marca desconhecido, ou rota desconhecida.
429 rate_limited Limite de rajada de curto prazo excedido (veja abaixo).
429 quota_exceeded Cota mensal esgotada (veja abaixo). Carrega Retry-After.
500 internal_error Erro inesperado de servidor (nenhum detalhe interno é vazado).

6. Limites de taxa e cota

Dois limites independentes protegem o contrato de leitura:

  1. Limite de rajada de curto prazo — um teto de taxa de requisições por chave (padrão 100 requisições / minuto). Excedê-lo retorna HTTP 429.
  2. Cota mensal — um orçamento mensal de requisições por chave. Quando você o esgota, a API retorna HTTP 429 com code: "quota_exceeded" e um header Retry-After (segundos até a janela de cota reiniciar no fim do mês). Essa mesma cota se aplica de forma idêntica em REST e no MCP — veja o guia MCP.
HTTP/1.1 429 Too Many Requests
Retry-After: 1209600
Content-Type: application/json

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

Respeite Retry-After: aguarde o número indicado de segundos antes de tentar novamente.

Próximos passos

  • Autenticação e escoposX-API-Key, brands:read / insights:read, ciclo de vida da chave e a semântica completa de 401 / 403 / 429.
  • Conecte seu agente de IA (MCP) — o endpoint mcp.obviouy.com e as ferramentas search_brands / get_brand_detail.
  • Exemplos de código — clientes REST e MCP prontos para copiar e colar.
  • A referência OpenAPI ao vivo em /docs — o schema autoritativo por campo.