Rate Limits e Boas Práticas
Para garantir a estabilidade da plataforma para todos os usuários, a API do eAgenda aplica limites de taxa (rate limits) nas requisições.
Limites de taxa
| Tipo | Limite |
|---|---|
| Requisições por minuto | Varia conforme o plano |
| Requisições por hora | Varia conforme o plano |
Os limites específicos dependem do seu plano contratado. Entre em contato com o suporte para informações sobre limites do seu plano.
Headers de resposta
A API retorna headers informativos sobre o consumo de rate limit:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1717524600
| Header | Descrição |
|---|---|
X-RateLimit-Limit | Máximo de requisições permitidas no período |
X-RateLimit-Remaining | Requisições restantes no período atual |
X-RateLimit-Reset | Timestamp Unix de quando o contador reseta |
Quando o limite é atingido
Se você exceder o limite, a API retorna:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
{
"detail": "Limite de requisições excedido. Tente novamente em 30 segundos."
}
Como lidar com rate limiting
Retry com backoff exponencial
import requests
import time
def api_request(url, auth, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, auth=auth)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 30))
wait = retry_after * (2 ** attempt) # backoff exponencial
print(f"Rate limit atingido. Aguardando {wait}s...")
time.sleep(wait)
continue
return response
raise Exception("Limite de tentativas excedido")
JavaScript
async function apiRequest(url, headers, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, { headers });
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After") || "30");
const wait = retryAfter * Math.pow(2, attempt);
console.log(`Rate limit atingido. Aguardando ${wait}s...`);
await new Promise(resolve => setTimeout(resolve, wait * 1000));
continue;
}
return response;
}
throw new Error("Limite de tentativas excedido");
}
Boas práticas para integrações
1. Minimize requisições desnecessárias
- Use filtros — Filtre por
status,start_date,calendar_keyem vez de buscar tudo e filtrar localmente - Paginação inteligente — Use
page_sizeadequado ao seu caso (ex: 100 resultados por página) - Evite polling excessivo — Use webhooks em vez de consultar a API a cada poucos segundos
2. Cache quando possível
Alguns dados mudam com pouca frequência e podem ser cacheados:
| Recurso | Tempo de cache sugerido |
|---|---|
Contas (/accounts/) | 1 hora |
Agendas (/calendars/) | 15 minutos |
Serviços (/services/) | 15 minutos |
Tags (/tags/) | 30 minutos |
| Horários disponíveis | 1-2 minutos (máximo) |
| Agendamentos | Sem cache (use webhooks) |
3. Trate erros adequadamente
response = requests.get(url, auth=auth)
match response.status_code:
case 200:
data = response.json()
case 400:
print(f"Dados inválidos: {response.json()}")
case 401:
print("Credenciais inválidas")
case 403:
print("Sem permissão")
case 404:
print("Recurso não encontrado")
case 429:
print("Rate limit - aguarde e tente novamente")
case _:
print(f"Erro inesperado: {response.status_code}")
4. Use timeouts
Sempre defina timeouts para evitar que requisições travem sua aplicação:
response = requests.get(url, auth=auth, timeout=30)
const controller = new AbortController();
setTimeout(() => controller.abort(), 30000);
const response = await fetch(url, {
headers,
signal: controller.signal,
});
5. Logs e monitoramento
Registre as requisições para facilitar o debugging:
- URL e método da requisição
- Status code da resposta
- Tempo de resposta
- Headers de rate limit
- Erros e retries