Rate Limiting (v2)
A limitação de taxa documentada aqui é explícita e aplicada na API v2. Para a API v1, o rate limiting segue o comportamento descrito nas Dúvidas Frequentes — sem limites fixos por cliente, apenas bloqueio temporário em caso de excesso de requisições (HTTP
429).
A API v2 implementa rate limiting(limitação de taxa) para garantir disponibilidade e performance para todos os clientes. Este guia explica como os limites funcionam na v2 e como evitar bloqueios.
O que é Rate Limiting?
Rate limiting é um mecanismo que limita o número de requisiçõesque você pode fazer em um período de tempo. Isso protege a API de sobrecarga e garante que todos os clientes tenham acesso justo aos recursos.
- Garantir disponibilidade para todos
- Prevenir abuso acidental ou intencional
- Manter performance consistente
- Proteger todos os endpoints da API v2
Limites Atuais
Cada cliente possui os seguintes limites:
| Autenticação | Limite | Burst | Janela | Configurável? |
|---|---|---|---|---|
| HMAC | 10 req/min | +2 | 60s | Fixo |
O que isso significa:
- Você pode fazer até 10 requisições por minuto
- Burst de +2: Permite até 12 requisições em rajadas curtas
- O limite se aplica a todos os endpoints(não há limites específicos por endpoint)
- O contador é resetado a cada minuto
Headers de Rate Limiting
Toda respostada API inclui headers que informam seu status de rate limiting:
HTTP/1.1 200 OK
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1698765492
Descrição dos Headers
| Header | Descrição | Exemplo |
|---|---|---|
X-RateLimit-Limit | Limite total de requisições na janela (1 min) | 10 |
X-RateLimit-Remaining | Requisições restantes na janela atual | 7 |
X-RateLimit-Reset | Timestamp Unix quando o limite será resetado | 1698765492 |
Exemplo Prático
async function checkRateLimit(response: Response): void {
const limit = parseInt(response.headers.get('X-RateLimit-Limit') || '0');
const remaining = parseInt(
response.headers.get('X-RateLimit-Remaining') || '0',
);
const reset = parseInt(response.headers.get('X-RateLimit-Reset') || '0');
console.log(`Rate Limit: ${remaining}/${limit}`);
// Alerta quando próximo do limite
if (remaining < limit * 0.2) {
const resetDate = new Date(reset * 1000);
console.warn(` Apenas ${remaining} requisições restantes!`);
console.warn(`Limite reseta em: ${resetDate.toISOString()}`);
}
}
Erro 429 - Too Many Requests
Quando você excede o limite, a API retorna HTTP 429com detalhes do erro:
{
"type": "urn:frota162-api-v2:error:rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Too many requests. Please retry after 2 seconds",
"instance": "/key/list-cars",
"timestamp": "2024-01-15T10:30:00Z",
"traceId": "550e8400-e29b-41d4-a716-446655440000"
}
**Nota:**O campo retryAfter está disponível no header Retry-After, não no body.
Headers Adicionais no 429
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1698765552
| Header | Descrição | Exemplo |
|---|---|---|
Retry-After | Segundos para aguardar antes de tentar | 60 |
Como Evitar Rate Limiting
1. Monitorar Headers
Sempremonitore os headers X-RateLimit-* em cada resposta:
class RateLimitMonitor {
private warningThreshold = 0.2; // 20%
checkHeaders(response: Response): void {
const limit = parseInt(response.headers.get('X-RateLimit-Limit') || '0');
const remaining = parseInt(
response.headers.get('X-RateLimit-Remaining') || '0',
);
if (remaining < limit * this.warningThreshold) {
this.slowDown();
}
}
private slowDown(): void {
console.warn(' Approaching rate limit, slowing down...');
// Implementar lógica de throttling
}
}
2. Implementar Throttling
Controle a taxa de requisições no seu lado:
class ThrottledClient {
private requestsPerMinute = 8; // Abaixo do limite de 10/min
private queue: Array<() => Promise<any>> = [];
private processing = false;
async request(fn: () => Promise<any>): Promise<any> {
return new Promise((resolve, reject) => {
this.queue.push(async () => {
try {
const result = await fn();
resolve(result);
} catch (error) {
reject(error);
}
});
this.processQueue();
});
}
private async processQueue(): Promise<void> {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
const delayMs = 60000 / this.requestsPerMinute; // ~7.5 segundos entre requisições
while (this.queue.length > 0) {
const fn = this.queue.shift()!;
await fn();
await this.sleep(delayMs);
}
this.processing = false;
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
// Uso
const client = new ThrottledClient();
for (let i = 0; i < 50; i++) {
client.request(() => fetch(`${API_URL}/key/get-car/${i}`));
}
3. Usar Paginação com Delay
Ao buscar grandes volumes, adicione delay entre páginas:
async function getAllVehicles(): Promise<Vehicle[]> {
const allVehicles: Vehicle[] = [];
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(
`${API_URL}/key/list-cars?pagination[page]=${page}&pagination[perpage]=100`,
);
// Verificar rate limit
const remaining = parseInt(
response.headers.get('X-RateLimit-Remaining') || '0',
);
const data = await response.json();
allVehicles.push(...data.cars.data);
hasMore = page < data.cars.last_page;
page++;
// Delay proporcional ao rate limit
if (hasMore) {
const delay = remaining < 3 ? 10000 : 7000; // Mais delay se próximo do limite
await sleep(delay);
}
}
return allVehicles;
}
4. Cache de Dados
Evite requisições desnecessárias com cache:
class CachedApiClient {
private cache = new Map<string, { data: any; expiry: number }>();
async get<T>(endpoint: string, cacheTTL: number = 300000): Promise<T> {
const cached = this.cache.get(endpoint);
// Retornar do cache se válido
if (cached && Date.now() < cached.expiry) {
console.log(' Cache hit:', endpoint);
return cached.data;
}
// Buscar da API
const response = await fetch(`${API_URL}${endpoint}`);
const data = await response.json();
// Armazenar no cache
this.cache.set(endpoint, {
data,
expiry: Date.now() + cacheTTL,
});
return data;
}
}
// Uso
const client = new CachedApiClient();
// Primeira chamada: vai para API
await client.get('/key/get-car/42', 60000); // Cache por 1 minuto
// Chamadas subsequentes: retorna do cache
await client.get('/key/get-car/42'); // Cache hit
5. Webhooks ao invés de Polling
Evite polling:
// NÃO FAÇA ISSO!
setInterval(async () => {
const trips = await fetchTrips(); // A cada segundo!
}, 1000);
Use webhooks:
// Configure webhooks para receber notificações
app.post('/webhooks/partner-gateway', (req, res) => {
const event = req.body;
if (event.type === 'trip.completed') {
handleTripCompleted(event.data);
}
res.status(200).send('OK');
});
Como Lidar com Erro 429
1. Respeitar Retry-After
Semprerespeite o header Retry-After:
async function fetchWithRetry(url: string): Promise<Response> {
const response = await fetch(url);
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
console.log(` Rate limited. Waiting ${retryAfter} seconds...`);
await sleep(retryAfter * 1000);
// Tentar novamente
return fetchWithRetry(url);
}
return response;
}
2. Backoff Exponencial
Para múltiplas tentativas, use backoff exponencial:
async function fetchWithExponentialBackoff(
url: string,
maxRetries: number = 5,
): Promise<Response> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url);
if (response.status === 429) {
const retryAfter =
parseInt(response.headers.get('Retry-After') || '0') * 1000;
const backoffDelay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s, 8s, 16s
const delay = Math.max(retryAfter, backoffDelay);
console.log(` Retry ${attempt + 1}/${maxRetries} after ${delay}ms`);
await sleep(delay);
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
3. Circuit Breaker
Proteja sua aplicação com circuit breaker:
class RateLimitCircuitBreaker {
private consecutiveRateLimits = 0;
private state: 'CLOSED' | 'OPEN' = 'CLOSED';
private openUntil = 0;
async execute<T>(fn: () => Promise<Response>): Promise<Response> {
// Se circuit aberto, aguardar
if (this.state === 'OPEN') {
if (Date.now() < this.openUntil) {
throw new Error('Circuit breaker is OPEN due to rate limiting');
}
this.state = 'CLOSED';
this.consecutiveRateLimits = 0;
}
const response = await fn();
if (response.status === 429) {
this.consecutiveRateLimits++;
// Abrir circuit após 3 rate limits consecutivos
if (this.consecutiveRateLimits >= 3) {
this.state = 'OPEN';
this.openUntil = Date.now() + 60000; // 1 minuto
console.error(' Circuit breaker OPEN due to rate limiting!');
}
} else {
this.consecutiveRateLimits = 0;
}
return response;
}
}
Monitoramento de Rate Limit
Métricas Importantes
Monitore estas métricas na sua integração:
class RateLimitMetrics {
private rateLimitHits = 0;
private totalRequests = 0;
private minRemaining = Infinity;
recordRequest(response: Response): void {
this.totalRequests++;
if (response.status === 429) {
this.rateLimitHits++;
}
const remaining = parseInt(
response.headers.get('X-RateLimit-Remaining') || '0',
);
this.minRemaining = Math.min(this.minRemaining, remaining);
}
getMetrics() {
return {
totalRequests: this.totalRequests,
rateLimitHits: this.rateLimitHits,
rateLimitRate: this.rateLimitHits / this.totalRequests,
minRemaining: this.minRemaining,
};
}
shouldAlert(): boolean {
// Alertar se taxa de rate limit > 1%
return this.rateLimitRate > 0.01;
}
}
Alertas Recomendados
Configure alertas para:
- Taxa de erro 429 > 1%
X-RateLimit-Remaining< 20% do limite- Circuit breaker aberto
- Múltiplos 429s consecutivos
Checklist de Boas Práticas
Implementação
- Monitorar headers
X-RateLimit-*em todas as respostas - Implementar throttling no cliente (8 req/min, 80% do limite)
- Respeitar
Retry-Afterem erros 429 - Usar cache para dados que mudam pouco
- Preferir webhooks a polling
- Adicionar delay entre requisições em lote
Tratamento de Erros
- Implementar retry com backoff exponencial
- Circuit breaker para proteção
- Logging de erros 429 com traceId
- Alertas para taxa alta de rate limiting
Otimização
- Usar paginação adequada (50-100 itens)
- Evitar requisições desnecessárias
- Batch de operações quando possível
- Testar no sandbox antes de produção
Resumo Executivo
As 5 regras de ouro:
- Monitore - Sempre verifique headers
X-RateLimit-* - Throttle - Limite suas requisições a ~8/min (80% do limite)
- Respeite - Aguarde o tempo indicado em
Retry-After - Cache - Evite requisições desnecessárias
- Webhooks - Use notificações ao invés de polling
FAQ
O que acontece se eu exceder o limite?
Você receberá erro HTTP 429e deverá aguardar o tempo indicado em Retry-After antes de tentar novamente.
Os limites são por organização ou por cliente?
Os limites são por cliente(clientId). Todas as organizações do mesmo cliente compartilham o mesmo limite.
Rate limiting afeta autenticação?
Sim. Todos os endpoints /key/* estão sujeitos ao limite de 10 requisições por minuto. Implemente throttling no cliente para evitar erros 429.
Posso personalizar os limites?
Não. Os limites são fixos:
- 10 requisições por minuto
- +2 burst de tolerância
- Janela de 60 segundos
Para solicitar limites diferentes, entre em contato com suporte@frota162.com.br.
Como testar rate limiting?
Use o ambiente sandboxpara testar. Você pode fazer requisições em lote para simular rate limiting sem afetar produção.
Próximos passos
Gere credenciais, monte os headers de autenticação e faça sua primeira requisição ao sandbox.
Entenda os formatos de erro e saiba como tratar HTTP 429, autenticação e erros de validação.
Throttling, cache, webhooks e outras práticas recomendadas para uma integração robusta.
Precisa de ajuda?→ suporte@frota162.com.br