Autenticação e escopos
Todo endpoint protegido do contrato de leitura do Tarno é controlado por uma chave de API. Este guia
cobre como apresentar a chave, os dois escopos, o ciclo de vida da chave e a semântica exata de 401 / 403 /
429 — tudo alinhado com os handlers ao vivo.
O header X-API-Key
Envie sua chave no header de requisição X-API-Key em toda chamada a uma rota protegida:
curl -sS "$TARNO_BASE_URL/v1/brands?limit=1" -H "X-API-Key: $TARNO_API_KEY"
A chave é uma string opaca emitida pelo operador (placeholder <API_KEY> nesta documentação). O
servidor a verifica em toda requisição; a chave bruta nunca é registrada em log.
O servidor MCP usa o mesmo header X-API-Key, enviado por requisição sobre o transporte
Streamable HTTP — veja o guia MCP. (Para o transporte stdio, a chave é lida da
variável de ambiente TARNO_API_KEY.)
Rotas públicas que não precisam de chave
/health, /docs e /metrics são os únicos caminhos que funcionam sem chave. Tudo
sob /v1 exige uma.
Escopos
Uma chave carrega um conjunto de escopos (scopes) que determinam quais partes do contrato ela pode ler:
| Escopo | Concede acesso a |
|---|---|
brands:read |
O contrato de marcas: GET /v1/brands, GET /v1/brands/:nroSolicitud. |
insights:read |
O contrato operacional: GET /v1/freshness, GET /v1/sync-runs. |
watch:read |
Leituras de Vigilância: GET /v1/watch, GET /v1/watch/:id, GET /v1/watch/:id/hits. |
watch:write |
Escritas de Vigilância: POST /v1/watch, PATCH /v1/watch/:id, DELETE /v1/watch/:id. |
Um array de escopos vazio é irrestrito — uma chave emitida sem escopos recebe todos os
escopos de leitura. Uma chave com um array de escopos não vazio recebe somente os escopos listados; chamar
uma rota cujo escopo exigido está ausente é rejeitado com 403 forbidden.
Os escopos watch:* exigem adicionalmente que a chave tenha uma org dona (consumerId); veja o
guia de Vigilância para tenancy, entrega dual e assinatura dos webhooks.
As ferramentas MCP seguem a mesma regra: tanto search_brands quanto get_brand_detail exigem
brands:read (ou uma chave irrestrita, de escopo vazio).
Ciclo de vida da chave (gerenciado pelo operador)
As chaves são criadas, rotacionadas, revogadas e expiradas pelo operador via CLI de administração. Como integrador, você não gerencia chaves por conta própria; você solicita mudanças ao seu operador.
- Rotacionar — o operador lhe emite uma nova chave e desativa a antiga. Troque o
valor de
X-API-Keyque seu cliente envia; nenhuma mudança de código além do segredo. - Revogar — uma chave revogada para de funcionar imediatamente: as chamadas seguintes retornam
401 unauthorized, exatamente como para uma chave desconhecida. - Expiração — uma chave pode carregar uma data de expiração. Após passar da expiração, ela é tratada como inválida e
retorna
401 unauthorized. Peça ao seu operador para reemitir antes da expiração para evitar indisponibilidade.
Cada chave também pertence a um consumer e carrega uma cota mensal (veja abaixo).
Semântica de status
Estes são os resultados exatos que as camadas de autenticação e cota produzem:
401 unauthorized
Retornado quando a chave está ausente, malformada, desconhecida ou revogada/expirada.
{ "error": { "code": "unauthorized", "message": "Missing or invalid API key", "requestId": "..." } }
403 forbidden
Retornado quando a chave é válida e ativa, mas não tem o escopo que a rota exige. A mensagem nomeia o escopo faltante:
{ "error": { "code": "forbidden", "message": "API key lacks required scope: insights:read", "requestId": "..." } }
429 quota_exceeded
Retornado quando a cota mensal da chave está esgotada. Carrega um header Retry-After com os
segundos até a janela de cota reiniciar:
HTTP/1.1 429 Too Many Requests
Retry-After: 1209600
{ "error": { "code": "quota_exceeded", "message": "Monthly quota exceeded", "requestId": "..." } }
429 rate_limited
Existem dois limites de taxa, ambos aditivos à cota mensal, e ambos retornam 429 com um header
Retry-After (segundos a aguardar):
- Rajada por chave (
code: rate_limited) — um segundo nível baseado no hash da chave que limita um único inquilino: por padrão 300 requisições a cada 60 s. Aplica-se de forma idêntica em REST e no MCP (ambos os transportes compartilham o mesmo contador), é independente do IP do cliente (então um pool de IP rotativo não o contorna) e não altera o esquema do contrato/v1— é uma nova condição429puramente aditiva.
```text HTTP/1.1 429 Too Many Requests Retry-After: 42
{ "error": { "code": "rate_limited", "message": "Too many requests (per-key burst limit)", "requestId": "..." } } ```
- Defesa anti-inundação por IP (
code: rate_limited) — um limite baseado no IP do cliente (padrão 100 requisições/minuto) que contém uma avalanche pré-autenticação (chaves rotativas). É independente do nível por chave.
Ação do consumidor: respeite o Retry-After e tente novamente após esse número de segundos. A cota
mensal (quota_exceeded) e ambos os limites de taxa (rate_limited) se aplicam de forma idêntica em REST
e no MCP, já que ambos os transportes se autenticam contra as mesmas chaves e compartilham os mesmos
contadores.
O envelope de erro uniforme
{ error: { code, message, requestId } }está descrito no guia de primeiros passos. UserequestId(também ecoado no header de respostax-request-id) ao relatar um problema ao seu operador.
CORS e acesso pelo navegador
O IRIS é server-side-only por padrão: a X-API-Key é uma credencial de servidor e nunca deve ser
embutida em um cliente de navegador. Por isso, por padrão a API não emite nenhum header
Access-Control-Allow-Origin — um fetch de navegador de terceiros não consegue ler as respostas. Este é
o comportamento padrão e não muda nada em relação a versões anteriores.
O acesso cross-origin pelo navegador é opt-in por deploy através da variável de ambiente
IRIS_CORS_ALLOWLIST (lista de origens exatas separadas por vírgulas):
IRIS_CORS_ALLOWLIST=https://app.tarno.cl,https://docs.tarno.cl
- Vazia / não definida → sem CORS (sem header
Access-Control-Allow-Origin) — o padrão no-op. - Com origens → apenas essas origens exatas recebem o header
Access-Control-Allow-Origin(nunca um curinga nem reflexo arbitrário doOrigin); nenhuma credencial é enviada (credentials:false). Um preflightOPTIONSdessas origens é respondido com os headers de permissão.
O servidor MCP não usa CORS. O MCP é um transporte servidor-a-servidor (agentes de IA o chamam pela rede, não um
fetchde navegador), então CORS — uma salvaguarda do navegador — não se aplica ali.
Veja também
- Primeiros passos — URL base, primeira chamada, paginação, envelope de erro.
- Conecte seu agente de IA (MCP) — mesma chave, mesmos escopos, via MCP.
- A referência OpenAPI ao vivo em
/docs— segurança e schema por endpoint.