Ir para o conteúdo

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-Key que 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ção 429 puramente 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. Use requestId (também ecoado no header de resposta x-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 do Origin); nenhuma credencial é enviada (credentials:false). Um preflight OPTIONS dessas 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 fetch de 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.