Visão Geral
A API Owem implementa rate limiting para garantir estabilidade e qualidade do serviço para todos os clientes.
Os limites são aplicados por API Key e por endpoint.
Limites Padrão
| Tipo | Limite | Período |
|---|
| Global | 1000 req | 1 minuto |
| Por Endpoint | 100 req | 1 minuto |
| Transferências PIX | 60 req | 1 minuto |
| Geração de QR Code | 120 req | 1 minuto |
Limites podem variar conforme seu plano. Contate suporte para aumentar
limites.
A API retorna headers informativos em cada resposta:
| Header | Descrição | Exemplo |
|---|
X-RateLimit-Limit | Limite total do período | 1000 |
X-RateLimit-Remaining | Requisições restantes | 847 |
X-RateLimit-Reset | Timestamp de reset (epoch) | 1766610300 |
Exemplo de Resposta
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1766610300
Content-Type: application/json
{"success": true, ...}
Quando Exceder o Limite
Ao exceder o rate limit, você receberá:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": 429,
"success": false,
"message": "Too many requests",
"code": "RATE_LIMIT_EXCEEDED"
}
| Header | Descrição |
|---|
Retry-After | Segundos para aguardar antes de retry |
Implementando Controle de Tráfego
Exponential Backoff
Implemente retry com backoff exponencial para erros 429:
async function callWithRetry(fn, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn()
} catch (error) {
if (error.status === 429 && attempt < maxRetries - 1) {
const delay = Math.pow(2, attempt) * 1000 // 1s, 2s, 4s...
console.log(`Rate limited. Retry in ${delay}ms`)
await sleep(delay)
continue
}
throw error
}
}
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
Token Bucket (Lado do Cliente)
Controle a taxa de requisições do seu lado:
class RateLimiter {
constructor(maxTokens, refillRate) {
this.maxTokens = maxTokens;
this.tokens = maxTokens;
this.refillRate = refillRate; // tokens por segundo
this.lastRefill = Date.now();
}
async acquire() {
this.refill();
if (this.tokens < 1) {
const waitTime = (1 - this.tokens) / this.refillRate * 1000;
await sleep(waitTime);
this.refill();
}
this.tokens -= 1;
return true;
}
refill() {
const now = Date.now();
const elapsed = (now - this.lastRefill) / 1000;
this.tokens = Math.min(this.maxTokens, this.tokens + elapsed * this.refillRate);
this.lastRefill = now;
}
}
// Uso: 100 req/min = ~1.67 req/s
const limiter = new RateLimiter(10, 1.67);
async function callOwemAPI(endpoint) {
await limiter.acquire();
return fetch(`https://api.owem.com.br${endpoint}`, { ... });
}
Queue de Requisições
Para alto volume, use uma fila:
import PQueue from "p-queue"
// 10 requisições simultâneas, 100ms entre cada
const queue = new PQueue({ concurrency: 10, interval: 100, intervalCap: 1 })
async function queuedRequest(endpoint, options) {
return queue.add(() => fetch(`https://api.owem.com.br${endpoint}`, options))
}
// Uso
const results = await Promise.all([
queuedRequest("/v4/i/ledger?page=1"),
queuedRequest("/v4/i/ledger?page=2"),
queuedRequest("/v4/i/ledger?page=3"),
// ... centenas de requisições serão enfileiradas
])
Boas Práticas
Monitore os Headers
Acompanhe X-RateLimit-Remaining para antecipar throttling.
Cache de Consultas
Cache consultas frequentes (saldo, ledger) para reduzir requisições.
Batch quando Possível
Use paginação otimizada ao invés de múltiplas requisições pequenas.
Webhooks > Polling
Use webhooks para eventos ao invés de polling constante.
Exemplo Completo
class OwemClient {
constructor(apiKey, apiSecret) {
this.baseUrl = "https://api.owem.com.br"
this.token = Buffer.from(`${apiKey}:${apiSecret}`).toString("base64")
this.limiter = new RateLimiter(100, 1.67)
}
async request(method, endpoint, body = null) {
await this.limiter.acquire()
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method,
headers: {
Authorization: `Basic ${this.token}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : null,
})
// Atualiza limiter com dados reais
const remaining = parseInt(response.headers.get("X-RateLimit-Remaining"))
const reset = parseInt(response.headers.get("X-RateLimit-Reset"))
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get("Retry-After")) || 60
console.warn(`Rate limited. Waiting ${retryAfter}s`)
await sleep(retryAfter * 1000)
return this.request(method, endpoint, body)
}
return response.json()
}
// Métodos de conveniência
getBalance(accountId) {
return this.request("GET", `/v4/i/bank-accounts/${accountId}/balance`)
}
createQrCode(data) {
return this.request("POST", "/v4/i/pix/in/dynamic-qrcode", data)
}
}
Suporte
Se você precisa de limites maiores para seu caso de uso, entre em contato:
Solicitar Aumento de Limite
Envie um email para [email protected] explicando seu caso de uso.