Rate limits e quotas
A API do Radar DOU implementa rate limits para garantir a estabilidade do servico e uso justo entre todos os usuarios. Este guia explica os limites de cada plano e como otimizar suas requisicoes.
O que sao Rate Limits?
Rate limits sao restricoes no numero de requisicoes que voce pode fazer em um determinado periodo de tempo. Esses limites protegem a infraestrutura e garantem que todos os usuarios tenham acesso justo ao servico.
- Requisicoes por minuto (RPM): Numero maximo de requisicoes em uma janela de 60 segundos
- Requisicoes por dia (RPD): Limite diario total de requisicoes
- Quota mensal: Total de requisicoes permitidas no ciclo de faturamento
Limites por Plano
| Plano | RPM | RPD | Quota Mensal | Itens/Pagina |
|---|---|---|---|---|
| Free | 10 | 100 | 1.000 | 20 |
| Starter | 30 | 1.000 | 10.000 | 50 |
| Professional | 60 | 5.000 | 50.000 | 100 |
| Enterprise | 120 | 20.000 | 200.000 | 100 |
| Custom | Sob consulta | Sob consulta | Sob consulta | 100 |
Headers de Rate Limit
Todas as respostas da API incluem headers que informam o status atual dos seus limites:
| Header | Descricao | Exemplo |
|---|---|---|
X-RateLimit-Limit | Limite total de requisicoes por minuto | 60 |
X-RateLimit-Remaining | Requisicoes restantes na janela atual | 45 |
X-RateLimit-Reset | Timestamp Unix quando o limite reseta | 1706284800 |
X-DailyLimit-Remaining | Requisicoes restantes no dia | 4500 |
X-MonthlyQuota-Remaining | Requisicoes restantes no mes | 48500 |
Erro 429 - Too Many Requests
Quando voce excede o limite de requisicoes, a API retorna o status 429:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 30
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1706284830
{
"sucesso": false,
"erro": {
"codigo": "RATE_LIMIT_EXCEEDED",
"mensagem": "Limite de requisicoes excedido. Tente novamente em 30 segundos.",
"retry_after": 30,
"tipo_limite": "rpm"
}
}Importante: O header Retry-After indica quantos segundos voce deve aguardar antes de fazer uma nova requisicao.
Implementando Rate Limiting no Cliente
Python - Retry com Backoff Exponencial
import time
import requests
class RateLimitHandler:
def __init__(self, api_key):
self.api_key = api_key
self.base_url = 'https://radardou.com.br/api/v1'
def request(self, endpoint, params=None, max_retries=3):
headers = {'X-API-Key': self.api_key}
for attempt in range(max_retries):
response = requests.get(
f'{self.base_url}{endpoint}',
headers=headers,
params=params
)
# Verificar rate limit restante
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
if remaining < 5:
print(f"Aviso: Apenas {remaining} requisicoes restantes")
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
wait_time = retry_after * (2 ** attempt) # Backoff exponencial
print(f"Rate limit excedido. Aguardando {wait_time}s...")
time.sleep(wait_time)
continue
response.raise_for_status()
return response.json()
raise Exception("Max retries exceeded")
# Uso
handler = RateLimitHandler(api_key='sua_api_key')
resultado = handler.request('/buscar', {'termo': 'licitacao'})JavaScript - Rate Limiter com Fila
class RateLimiter {
constructor(requestsPerMinute) {
this.requestsPerMinute = requestsPerMinute;
this.queue = [];
this.requestTimes = [];
}
async throttle() {
const now = Date.now();
// Remover requisicoes antigas (mais de 1 minuto)
this.requestTimes = this.requestTimes.filter(
time => now - time < 60000
);
if (this.requestTimes.length >= this.requestsPerMinute) {
const oldestRequest = this.requestTimes[0];
const waitTime = 60000 - (now - oldestRequest);
console.log(`Rate limit proximo. Aguardando ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
this.requestTimes.push(Date.now());
}
}
// Uso
const limiter = new RateLimiter(60); // 60 req/min
async function buscarComLimite(termo) {
await limiter.throttle();
const response = await fetch(
`https://radardou.com.br/api/v1/buscar?termo=${termo}`,
{ headers: { 'X-API-Key': API_KEY } }
);
return response.json();
}Otimizacao de Requisicoes
Estrategias para Otimizar o Uso
- Use paginacao eficiente: Solicite o maximo de itens por pagina (ate 100) para reduzir o numero de requisicoes
- Implemente cache: Armazene resultados localmente para evitar buscas repetidas
- Filtre na API: Use parametros de filtro ao inves de filtrar apos receber os dados
- Busque em lote: Agrupe buscas relacionadas em menos requisicoes
- Monitore uso: Acompanhe os headers de rate limit para ajustar o ritmo
Implementando Cache Local
import json
import hashlib
from datetime import datetime, timedelta
from pathlib import Path
class CacheManager:
def __init__(self, cache_dir='.cache', ttl_minutes=30):
self.cache_dir = Path(cache_dir)
self.cache_dir.mkdir(exist_ok=True)
self.ttl = timedelta(minutes=ttl_minutes)
def _get_cache_key(self, endpoint, params):
"""Gera uma chave unica para a requisicao."""
data = json.dumps({'endpoint': endpoint, 'params': params}, sort_keys=True)
return hashlib.md5(data.encode()).hexdigest()
def get(self, endpoint, params):
"""Recupera dados do cache se validos."""
key = self._get_cache_key(endpoint, params)
cache_file = self.cache_dir / f'{key}.json'
if cache_file.exists():
with open(cache_file, 'r') as f:
cached = json.load(f)
cached_time = datetime.fromisoformat(cached['timestamp'])
if datetime.now() - cached_time < self.ttl:
print("Cache hit!")
return cached['data']
return None
def set(self, endpoint, params, data):
"""Armazena dados no cache."""
key = self._get_cache_key(endpoint, params)
cache_file = self.cache_dir / f'{key}.json'
with open(cache_file, 'w') as f:
json.dump({
'timestamp': datetime.now().isoformat(),
'data': data
}, f)
# Uso com a API
cache = CacheManager(ttl_minutes=15)
def buscar_com_cache(termo, **params):
# Tentar cache primeiro
cached = cache.get('/buscar', {'termo': termo, **params})
if cached:
return cached
# Buscar da API
resultado = radar.buscar(termo=termo, **params)
# Salvar no cache
cache.set('/buscar', {'termo': termo, **params}, resultado)
return resultadoMonitoramento de Uso
Acompanhe seu consumo de API no dashboard ou atraves dos headers:
def monitorar_uso(response):
"""Exibe informacoes de uso apos cada requisicao."""
headers = response.headers
print("=== Status de Uso ===")
print(f"RPM: {headers.get('X-RateLimit-Remaining')}/{headers.get('X-RateLimit-Limit')}")
print(f"Diario restante: {headers.get('X-DailyLimit-Remaining')}")
print(f"Mensal restante: {headers.get('X-MonthlyQuota-Remaining')}")
# Alertas
rpm_restante = int(headers.get('X-RateLimit-Remaining', 0))
if rpm_restante < 10:
print("ALERTA: Poucas requisicoes RPM restantes!")
diario_restante = int(headers.get('X-DailyLimit-Remaining', 0))
if diario_restante < 100:
print("ALERTA: Proximo do limite diario!")Quando Fazer Upgrade
Considere fazer upgrade do seu plano quando:
- Voce frequentemente atinge os limites de RPM durante o dia
- Sua quota mensal e consumida antes do fim do ciclo
- Precisa de mais itens por pagina para otimizar buscas
- Seu caso de uso requer processamento em lote intensivo
Dica: O dashboard do Radar DOU mostra graficos de uso historico e projecoes, ajudando voce a identificar o momento ideal para upgrade.
Perguntas Frequentes
O que acontece se eu exceder o limite mensal?
Suas requisicoes serao bloqueadas ate o proximo ciclo de faturamento. Voce pode fazer upgrade a qualquer momento para aumentar sua quota.
Os limites sao por API Key ou por conta?
Os limites sao compartilhados por conta. Todas as API Keys da mesma conta utilizam a mesma quota.
Requisicoes com erro contam no limite?
Requisicoes que retornam erro 4xx ou 5xx nao sao contabilizadas na sua quota mensal, mas ainda contam para o rate limit por minuto.
Precisa de limites customizados? Entre em contato com nossa equipe comercial para discutir um plano Enterprise com limites personalizados para sua necessidade.
Ainda tem dúvidas?
Converse com nosso assistente virtual especializado para obter ajuda personalizada sobre qualquer funcionalidade.
