Pular para o conteúdo

Limites de requisição

Uma requisição da sua integração passa por limites em duas fases. Os limites por IP são aplicados antes da autenticação. Depois que a chave é aceita, o ambiente dela é conferido e a conta do tenant é liberada, vêm o limite da chave, o limite do tenant e, em duas operações, um limite da operação. O primeiro que estourar responde 429.

Na superfície de chave de API (/vasp), antes da autenticação, valem estes limites:

Limite Valor Resposta
Teto por hora Mais de 5.000 requisições na hora, do mesmo IP, sem autenticação válida 429 com retry_after: 3600 no corpo e Retry-After: 3600
IP bloqueado O IP está bloqueado (por três tentativas de travessia de diretório na hora, ou por abuso vindo do mesmo IP em outras rotas da plataforma) 429 com code: "IP_BANNED" e Retry-After: 3600 até o bloqueio vencer, em até 1 hora
Travessia de diretório URL com ../, %2e%2e, /etc/passwd e padrões parecidos, no caminho ou na query 403 com error: "Request blocked by security policy."; a terceira na hora bloqueia o IP
Corpo grande Corpo acima de 1 MiB 413 com code: "BODY_TOO_LARGE"

O teto por hora conta só o que não autenticou ou não coube nos limites: a requisição cuja chave é aceita, com o ambiente certo, a conta do tenant ativa, a API liberada e dentro dos limites da chave e do tenant, tem a unidade devolvida ao contador do IP e passa a contar no limite do tenant (seção 2). Requisição recusada pelo ambiente da chave, ou que estoura o limite da chave ou o do tenant, continua contando no IP. Na prática, o teto por IP pesa sobre tráfego sem credencial, sobre credencial recusada e sobre excesso, e não sobre a sua integração dentro dos limites.

Nesta superfície não há teto por IP por minuto, não há regra de rajada e não há pontuação de User-Agent, de cabeçalhos ou de trechos do corpo e da query. Cliente em Go, Python ou curl, sem Accept-Language, com --, /* ou sp_ nos dados e disparando requisições em paralelo, a menos de 50 ms uma da outra, não é tratado como ataque. Quem controla o volume da sua integração são os limites do tenant e da chave (seções 2 e 3).

Credencial recusada conta no teto por hora. Se o mesmo IP acumular mais de 5.000 requisições sem autenticação válida na hora (chave revogada em laço, por exemplo), todas as requisições desse IP, inclusive as com chave válida, recebem 429 até a janela vencer, porque essa verificação acontece antes de a chave ser conferida. Não repita em laço uma requisição que recebeu 401.

O limite do tenant é de 2.000 requisições por minuto e soma tudo o que o tenant faz autenticado: todas as chaves de API e todos os usuários do painel. A janela é de um minuto, contada a partir da primeira requisição dela.

Ao estourar:

HTTP/1.1 429 Too Many Requests
Retry-After: 42
Content-Type: application/json
{
"success": false,
"error": "Too many requests. Please try again later.",
"retry_after": 42
}

Retry-After e retry_after trazem o mesmo número: os segundos que faltam para a janela vencer, de 1 a 60. Este limite não envia X-RateLimit-Limit nem X-RateLimit-Remaining; na superfície /vasp, esses cabeçalhos são do limite da chave (seção 3).

O limite da superfície /vasp é por chave e por minuto. Ele é definido na criação da chave, no painel, pelo campo rate_limit_per_min, com valor de 1 a 10.000. Chave criada sem esse campo usa o padrão do servidor, 60 requisições por minuto. Cada chave tem o próprio contador: duas chaves do mesmo tenant não dividem o limite da chave, mas dividem o limite do tenant da seção 2, que é conferido logo depois deste. Uma chave com rate_limit_per_min acima de 2.000 fica limitada, na prática, pelo tenant.

Toda resposta que passa por esse limite traz:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57

Ao estourar:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json
{
"success": false,
"error": {
"code": "api_key_rate_limit_exceeded",
"message": "API key rate limit exceeded"
}
}
Operação Limite Resposta ao estourar
GET /vasp/customers e POST /vasp/customers/search Por chave e por minuto; o padrão do servidor é 120. Uma busca que devolve lista vazia consome 5 unidades, e não 1, para dificultar enumeração 429 com error: "rate_limited", retry_after: 60 e Retry-After: 60. Estas duas operações também enviam X-RateLimit-Reset, que é a duração da janela em segundos (60), e não um horário
POST /vasp/kyt-report 120 emissões por hora, contadas por IP de origem 429 com error: "RATE_LIMIT_EXCEEDED" e Retry-After: 3600

Esses limites se somam aos limites do tenant e da chave: a requisição precisa passar por todos.

O corpo do 429 depende do limite que disparou: em alguns, error é um objeto com code; em outros, error é uma string e o código vem em code ao lado dele. O teto por hora da seção 1 e o limite do tenant da seção 2 usam a mesma forma, com error string e retry_after inteiro igual ao Retry-After. Trate sempre pelo status HTTP e pelo header Retry-After quando ele vier; não escreva resposta.error.code sem checar o tipo de error.

Não existe o header X-RateLimit-Scope. Ele nunca foi emitido pelo servidor, e um consumidor que dependa dele lê string vazia.

  1. Respeite Retry-After quando ele vier. Quando não vier, use espera exponencial a partir de 1 segundo
  2. Use Idempotency-Key nas operações que o honram, para que a retentativa depois de um 429 ou 5xx não duplique a análise. Ver Idempotência
  3. Prefira webhook a consultas em intervalo curto. Ver Webhooks
  4. Acompanhe X-RateLimit-Remaining e reduza o ritmo antes de chegar a zero
  5. Não repita 401 em laço: credencial recusada conta no teto por IP e pode bloquear o IP inteiro por até 1 hora
  1. O limite da chave é definido na criação dela, no painel. Para outro valor, crie uma chave nova com o rate_limit_per_min desejado e revogue a antiga
  2. Para os limites por IP, do tenant e por operação, escreva para dev-support@sentinexrisk.com com o volume por minuto esperado, a janela de pico e a quantidade de IPs de saída