Rate Limits
Para garantir estabilidade e disponibilidade da plataforma, a API Externa aplica limites de taxa por empresa.
Limites
| Escopo | Limite | Janela |
|---|---|---|
| Por empresa (companyId) | 100 requisicoes | 1 minuto (janela deslizante) |
O limite e compartilhado entre todas as API Keys da mesma empresa. Ou seja, se a empresa possui 3 chaves ativas, as 3 dividem a mesma cota de 100 req/min.
Headers de Resposta
Todas as respostas da API incluem headers informativos sobre o consumo:
| Header | Descricao | Exemplo |
|---|---|---|
X-RateLimit-Limit | Limite total na janela | 100 |
X-RateLimit-Remaining | Requisicoes restantes | 73 |
X-RateLimit-Reset | Timestamp Unix de quando o limite sera renovado | 1711324800 |
Exemplo de headers em uma resposta:
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 73
X-RateLimit-Reset: 1711324800
Resposta ao Exceder o Limite (HTTP 429)
Quando o limite e ultrapassado, a API retorna:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 23
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1711324800
{
"statusCode": 429,
"message": "RATE_LIMIT_EXCEEDED",
"friendlyMessage": "Limite de requisicoes excedido. Tente novamente em alguns segundos."
}
O header Retry-After indica quantos segundos aguardar antes de tentar novamente.
Estrategia de Retry — Exponential Backoff
Recomendamos implementar exponential backoff com jitter para lidar com erros 429:
tentativa 1: aguardar 1s + jitter aleatorio (0-500ms)
tentativa 2: aguardar 2s + jitter aleatorio (0-500ms)
tentativa 3: aguardar 4s + jitter aleatorio (0-500ms)
tentativa 4: aguardar 8s + jitter aleatorio (0-500ms)
tentativa 5: aguardar 16s + jitter aleatorio (0-500ms)
Maximo de tentativas recomendado: 5
Exemplo em JavaScript:
async function requestWithRetry(fn, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (error.response?.status !== 429 || attempt === maxRetries - 1) {
throw error;
}
const retryAfter = error.response.headers['retry-after'];
const baseDelay = retryAfter
? parseInt(retryAfter, 10) * 1000
: Math.pow(2, attempt) * 1000;
const jitter = Math.random() * 500;
await new Promise(resolve => setTimeout(resolve, baseDelay + jitter));
}
}
}
Exemplo em Python:
import time
import random
import requests
def request_with_retry(method, url, max_retries=5, **kwargs):
for attempt in range(max_retries):
response = requests.request(method, url, **kwargs)
if response.status_code != 429:
return response
if attempt == max_retries - 1:
response.raise_for_status()
retry_after = response.headers.get("Retry-After")
if retry_after:
delay = int(retry_after)
else:
delay = (2 ** attempt)
jitter = random.uniform(0, 0.5)
time.sleep(delay + jitter)
return response
Dicas para Otimizar o Consumo
- Cache respostas de leitura (GET) quando os dados nao mudam com frequencia
- Agrupe operacoes em lotes ao inves de chamadas individuais
- Utilize filtros e paginacao para reduzir o volume de dados por requisicao
- Monitore os headers
X-RateLimit-Remainingpara ajustar a cadencia das chamadas proativamente - Distribua chamadas ao longo do tempo ao inves de enviar rajadas (burst)