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, 1–45. |
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: nullsignifica 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. Respostas5xxusam uma mensagem genérica e nunca vazam detalhes internos.requestId— correlaciona seu relato com o log do servidor. Também é ecoado no header de respostax-request-id; você pode fornecer o seu próprio via o header de requisiçãoX-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:
- 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.
- 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 headerRetry-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 escopos —
X-API-Key,brands:read/insights:read, ciclo de vida da chave e a semântica completa de401/403/429. - Conecte seu agente de IA (MCP) — o endpoint
mcp.obviouy.come as ferramentassearch_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.