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:
| Header | Valor | Significado |
|---|---|---|
X-RateLimit-Limit | 100 | Limite configurado pra essa chave |
X-RateLimit-Remaining | 87 | Chamadas restantes na janela atual |
X-RateLimit-Reset | 1747920620 | Unix 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 RequestsX-RateLimit-Limit: 100X-RateLimit-Remaining: 0X-RateLimit-Reset: 1747920620Retry-After: 23Content-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
-
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} -
Bulk endpoints quando disponíveis — algumas operações têm versão
/bulk/*que aceita N items por chamada (ex:POST /activities/bulk/complete). -
Cache local — se você lê os mesmos pipelines/properties múltiplas vezes, cacheie no seu lado. Esses dados raramente mudam.
-
Webhooks em vez de polling — em vez de chamar GET
/contactsa 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:
- Primeiro, otimize: aplique cache, bulk ops, e backoff antes de pedir mais limite
- Suba o limite na própria chave: admin pode ajustar até 1000 req/min via UI
- 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