Limites e cotas
Rate limit de rondas, cota de análises com IA, limite de apps, chaves e destinos.
Resumo
Tudo que tem teto na API, em uma tabela. Os números de plano vêm do catálogo em vigor.
| O quê | Limite | Ao passar |
|---|---|---|
POST /scans | 10 rondas de rajada por conta, reabastecendo 1 por minuto | 429 rate_limited + Retry-After |
| Leituras (GET) | Sem limite de taxa hoje | — |
Análises com IA (ai: true) | Cota mensal do plano: Pro 20 · Business 60 | 402 quota_exceeded |
| Apps | Limite do plano: Pro 10 · Business sem limite | 402 domain_limit em hostname novo |
| Histórico de rondas | Retenção do plano: Pro 365 dias · Business sem limite | Rondas mais antigas deixam de existir |
| Chaves de API ativas | 10 por conta | 409 no painel |
| Destinos de webhook | 5 por conta | 409 no painel |
| Duração de uma ronda | Teto de 30 minutos | A ronda termina parcial em vez de morrer sem resultado |
| Tamanho do corpo da requisição | 1 MB | 413 bad_request |
Limite de rondas
É um balde de tokens por conta: cabem 10 rondas de rajada, e o balde reabastece 1 por minuto. Passou, a resposta é 429 rate_limited com o header Retry-After (segundos) e o mesmo valor em retryAfterSec no corpo. É o primeiro guard da rota — roda antes de cota, autorização e limite de apps.
const BASE = "https://api.guarita.dev/v1/public";
const auth = { Authorization: `Bearer ${process.env.GUARITA_API_KEY}` };
// Honra o Retry-After UMA vez. Se estourar de novo, desiste: insistir só renova a espera.
async function dispararRonda(target, retried = false) {
const res = await fetch(`${BASE}/scans`, {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({ target }),
});
if (res.status === 429 && !retried) {
const wait = Number(res.headers.get("retry-after") ?? 60);
await new Promise((r) => setTimeout(r, wait * 1000));
return dispararRonda(target, true);
}
const body = await res.json();
if (res.status !== 202) throw new Error(`Guarita ${res.status} ${body.error}: ${body.message}`);
return body.id;
}concurrency no workflow — a receita do GitHub Actions já vem com isso.Cota de análises com IA
A ronda com ai: true consome 1 análise da cota do mês. A reserva é feita no enfileiramento, uma vez por ronda — não há como a mesma ronda cobrar duas vezes.
- Não consome: a ronda básica (
ai: false), nunca. - Devolve a reserva: ronda bloqueada pelo WAF, parcial por tempo, que falhou — ou que você cancelou em
POST /scans/{id}/cancel. Você não paga por uma ronda que não viu o app. - Ao esgotar:
402 quota_exceeded, comlimit,usedeupgradeTo. Não é bug: refaça comai: falseou avise quem cuida da assinatura. - Excedente: planos com preço por análise extra cobram por análise acima da cota — o valor vem em
overagePricena resposta 402 e na tabela abaixo.
Por plano
| Pro | Business | |
|---|---|---|
| Preço | R$ 397/mês | R$ 1.197/mês |
| Análises com IA por mês | 20 | 60 |
| Análise extra | R$ 15 | R$ 12 |
| Apps | 10 | sem limite |
| Histórico de rondas | 365 dias | sem limite |
Leituras
As leituras (GET) não têm limite de taxa hoje. Se um dia tiver, entra pelo changelog e vem com Retry-After, igual ao de rondas. Polling a cada 10 s é o ritmo que recomendamos — mais rápido só gasta requisição sem antecipar nada.
x-request-id, se for sobre uma resposta.