Pular para o conteúdo

Rate limiting

A Public API tem rate limit por API Key (não por IP, não por tenant). Cada key tem seu próprio contador independente — uma chave saturada não afeta outras chaves do mesmo tenant.

Limites padrão

  • Default: 100 requisições por minuto
  • Máximo configurável: 1000 requisições por minuto
  • Janela: 60 segundos (sliding window)

Admins podem ajustar o limite por chave em Configurações → Integrações → API Keys → editar (campo “Rate limit” na seção avançada do form).

Headers de resposta

Toda resposta inclui headers que mostram o estado atual do bucket:

HeaderValorSignificado
X-RateLimit-Limit100Limite configurado pra essa chave
X-RateLimit-Remaining87Chamadas restantes na janela atual
X-RateLimit-Reset1747920620Unix timestamp (segundos) de quando a janela reseta

Quando o limite é estourado, a próxima chamada recebe 429 Too Many Requests:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1747920620
Retry-After: 23
Content-Type: application/json
{
"error": "rate_limit_exceeded",
"message": "Rate limit excedido. Aguarde antes de tentar novamente.",
"limit": 100,
"retryAfterSeconds": 23
}

Retry-After indica em quantos segundos você pode tentar de novo. Respeite esse header — clientes que ignoram e refazem imediatamente vão continuar batendo em 429.

Estratégia recomendada

  1. Backoff exponencial em caso de 429:

    async function fetchWithRetry(url, opts, attempt = 0) {
    const res = await fetch(url, opts)
    if (res.status === 429 && attempt < 5) {
    const retryAfter = Number(res.headers.get('retry-after') ?? 1)
    await new Promise(r => setTimeout(r, retryAfter * 1000))
    return fetchWithRetry(url, opts, attempt + 1)
    }
    return res
    }
  2. Bulk endpoints quando disponíveis — algumas operações têm versão /bulk/* que aceita N items por chamada (ex: POST /activities/bulk/complete).

  3. Cache local — se você lê os mesmos pipelines/properties múltiplas vezes, cacheie no seu lado. Esses dados raramente mudam.

  4. Webhooks em vez de polling — em vez de chamar GET /contacts a cada N segundos pra ver o que mudou, configure um webhook de saída (em breve) que dispara quando contatos mudam.

Aumentar o limite

Se você está hitando rate limit consistentemente em uso legítimo:

  1. Primeiro, otimize: aplique cache, bulk ops, e backoff antes de pedir mais limite
  2. Suba o limite na própria chave: admin pode ajustar até 1000 req/min via UI
  3. Precisa mais que 1000? Entre em contato com o time Indutiva — limites maiores são possíveis pra casos justificados (migrações em massa, sync inicial de bases grandes)

Detalhes técnicos

  • O contador é em memória do processo (cluster single-instance). Funciona pra PM2 single-process; quando escalarmos pra cluster, migra pra Redis com mesma API
  • Janela é “sliding”: o contador zera 60 segundos após a primeira chamada do bucket atual (não em horários fixos de relógio)
  • Não há “burst” — cada chamada conta exatamente igual, regardless de quão rápido vieram