Pular para o conteúdo principal
Guia

Rate Limiting (v2)

2 min de leituraVale para 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.

Por que existe?
  • 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çãoLimiteBurstJanelaConfigurável?
HMAC10 req/min+260sFixo

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

HeaderDescriçãoExemplo
X-RateLimit-LimitLimite total de requisições na janela (1 min)10
X-RateLimit-RemainingRequisições restantes na janela atual7
X-RateLimit-ResetTimestamp Unix quando o limite será resetado1698765492

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
HeaderDescriçãoExemplo
Retry-AfterSegundos para aguardar antes de tentar60

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-After em 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:

  1. Monitore - Sempre verifique headers X-RateLimit-*
  2. Throttle - Limite suas requisições a ~8/min (80% do limite)
  3. Respeite - Aguarde o tempo indicado em Retry-After
  4. Cache - Evite requisições desnecessárias
  5. 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

Precisa de ajuda?suporte@frota162.com.br