Erro 131056 WhatsApp API: Rate Limit Hit — Como Resolver
Guia completo para resolver o erro 131056 (rate limit hit) da WhatsApp Business API. Causas, subcódigos, pair rate limit e soluções com código.
O que é o Erro 131056?
O erro 131056 é o rate limit hit da WhatsApp Business API. Ele ocorre quando sua aplicação excede os limites de envio de mensagens — seja o limite global da conta, o limite por número de telefone, ou o pair rate limit (limite entre seu número business e um número específico de consumidor).
{
"error": {
"message": "(#131056) (business account, consumer account) pair rate limit hit",
"type": "OAuthException",
"code": 131056,
"error_subcode": 2494055,
"fbtrace_id": "..."
}
}
Este é um dos erros mais comuns em operações de alta escala e pode impactar seriamente suas campanhas se não for tratado corretamente.
Tipos de Rate Limit que Causam o 131056
O erro 131056 não é um único limite — ele pode ser disparado por três tipos diferentes de rate limiting:
1. Pair Rate Limit (Business ↔ Consumer)
O mais frequente. Ocorre quando você envia muitas mensagens para o mesmo número em um curto período.
Seu número Business → Número do Cliente = PAR
Limites aproximados:
- Máximo de ~80 mensagens por segundo por par
- Máximo de ~256 mensagens de template por conversa ativa
- Se o usuário não responde, a Meta reduz o limite progressivamente
2. Limite por Número de Telefone (Throughput)
Ocorre quando seu número Business envia mensagens rápido demais, independente do destino.
Cloud API:
- Limite padrão: 80 msg/s
- Limite máximo: 1.000 msg/s (para contas elegíveis que solicitam aumento)
Business App:
- Limite padrão: ~10 msg/min
- Limite máximo: N/A
3. Limite de Conversas por 24h (Tier)
Ocorre quando você excede o número de novas conversas que pode iniciar em 24h.
- Não verificado: 250 conversas/24h
- Tier 1: 1.000 conversas/24h
- Tier 2: 10.000 conversas/24h
- Tier 3: 100.000 conversas/24h
- Tier 4: Ilimitado
Subcódigos de Erro
O erro 131056 pode vir com diferentes subcódigos que indicam qual tipo de rate limit foi atingido:
- 2494055 — Pair rate limit: Muitas mensagens para o mesmo usuário
- 2494056 — Account rate limit: Limite global da conta atingido
- 2494057 — Spam rate limit: Detectado padrão de spam
- 2494058 — Throughput limit: Muitas chamadas à API por segundo
Causas Comuns
1. Spam para o Mesmo Usuário
O cenário mais comum: enviar múltiplas mensagens de template para o mesmo número sem esperar resposta.
// ❌ ERRADO: bombardear o mesmo número
for (const template of templates) {
await sendTemplate(userPhone, template); // Vai dar 131056
}
// ✅ CORRETO: espaçar e limitar por usuário
const MAX_TEMPLATES_PER_USER = 3;
const DELAY_BETWEEN_MESSAGES = 5000; // 5 segundos
for (let i = 0; i < Math.min(templates.length, MAX_TEMPLATES_PER_USER); i++) {
await sendTemplate(userPhone, templates[i]);
await new Promise(r => setTimeout(r, DELAY_BETWEEN_MESSAGES));
}
2. Campanha em Massa Sem Rate Limiting
Enviar para toda a base de uma vez sem controle de velocidade.
3. Retry Agressivo
Quando o primeiro envio falha e o sistema tenta reenviar imediatamente sem backoff.
4. Múltiplos Sistemas Enviando
Dois ou mais sistemas (CRM, chatbot, campanhas) enviando pelo mesmo número sem coordenação.
Soluções
1. Implementar Rate Limiter com Bottleneck
import Bottleneck from 'bottleneck';
// Limiter global: respeita o throughput da Cloud API
const globalLimiter = new Bottleneck({
minTime: 15, // ~66 msg/s (abaixo do limite de 80)
maxConcurrent: 10,
reservoir: 5000,
reservoirRefreshAmount: 5000,
reservoirRefreshInterval: 60 * 1000
});
// Limiter por usuário: evita pair rate limit
const userLimiters = new Map();
function getUserLimiter(userId) {
if (!userLimiters.has(userId)) {
userLimiters.set(userId, new Bottleneck({
minTime: 3000, // 1 msg a cada 3 segundos por usuário
maxConcurrent: 1,
reservoir: 10, // Máximo 10 msgs por janela
reservoirRefreshAmount: 10,
reservoirRefreshInterval: 60 * 60 * 1000 // Renova a cada hora
}));
}
return userLimiters.get(userId);
}
async function safeSendMessage(to, message) {
const userLimiter = getUserLimiter(to);
return globalLimiter.schedule(() =>
userLimiter.schedule(() =>
sendWhatsAppMessage(to, message)
)
);
}
2. Backoff Exponencial com Jitter
Quando receber o 131056, não faça retry imediato. Use backoff com jitter para evitar thundering herd:
async function sendWithBackoff(to, message, attempt = 1, maxAttempts = 5) {
try {
return await sendWhatsAppMessage(to, message);
} catch (error) {
if (error.code === 131056 && attempt < maxAttempts) {
// Backoff exponencial com jitter
const baseDelay = Math.pow(2, attempt) * 1000;
const jitter = Math.random() * 1000;
const delay = baseDelay + jitter;
console.log(
`[131056] Rate limit para ${to}. ` +
`Tentativa ${attempt}/${maxAttempts}. ` +
`Aguardando ${(delay / 1000).toFixed(1)}s...`
);
await new Promise(r => setTimeout(r, delay));
return sendWithBackoff(to, message, attempt + 1, maxAttempts);
}
throw error;
}
}
3. Fila com BullMQ e Rate Limiting
Para operações de alta escala, use filas com controle de velocidade:
import { Queue, Worker } from 'bullmq';
const messageQueue = new Queue('whatsapp-messages', {
connection: { host: 'localhost', port: 6379 }
});
// Enfileirar mensagem
async function queueMessage(to, message, priority = 'normal') {
await messageQueue.add(
'send',
{ to, message },
{
priority: priority === 'urgent' ? 1 : 10,
attempts: 5,
backoff: {
type: 'exponential',
delay: 3000
},
// Agrupar por destinatário para evitar pair rate limit
group: { id: to }
}
);
}
// Worker com rate limiting embutido
const worker = new Worker(
'whatsapp-messages',
async job => {
return await sendWhatsAppMessage(job.data.to, job.data.message);
},
{
connection: { host: 'localhost', port: 6379 },
limiter: {
max: 50, // 50 mensagens
duration: 1000 // por segundo
},
concurrency: 5
}
);
worker.on('failed', (job, error) => {
if (error.code === 131056) {
console.log(`Rate limit para ${job.data.to}. Retry automático.`);
}
});
4. Monitorar e Pausar Automaticamente
class RateLimitMonitor {
constructor() {
this.rateLimitCount = 0;
this.totalSent = 0;
this.windowStart = Date.now();
}
recordSent() {
this.totalSent++;
}
recordRateLimit() {
this.rateLimitCount++;
}
getRateLimitPercentage() {
if (this.totalSent === 0) return 0;
return (this.rateLimitCount / this.totalSent) * 100;
}
shouldPause() {
// Pausar se mais de 5% das mensagens dão rate limit
return this.getRateLimitPercentage() > 5;
}
shouldSlowDown() {
// Reduzir velocidade se mais de 2% dão rate limit
return this.getRateLimitPercentage() > 2;
}
reset() {
this.rateLimitCount = 0;
this.totalSent = 0;
this.windowStart = Date.now();
}
}
const monitor = new RateLimitMonitor();
async function sendWithMonitoring(to, message) {
if (monitor.shouldPause()) {
console.log('⚠️ Taxa de rate limit alta. Pausando por 60s...');
await new Promise(r => setTimeout(r, 60000));
monitor.reset();
}
try {
const result = await sendWhatsAppMessage(to, message);
monitor.recordSent();
return result;
} catch (error) {
if (error.code === 131056) {
monitor.recordRateLimit();
}
throw error;
}
}
Diferença entre 131056 e Outros Erros
- 131056 — Rate limit hit: ✅ Sim, retry com backoff
- 131047 — Janela 24h expirada: ❌ Não (use template)
- 131026 — Mensagem não entregável: ❌ Não (número inválido)
- 130429 — Cloud API throttle: ✅ Sim, retry com backoff
A diferença crucial: o 131056 é temporário. Aguardar e tentar novamente resolve. Os outros erros indicam problemas que retry não resolve.
Prevenção: Boas Práticas
-
Warm-up gradual: Nunca envie no limite máximo em contas novas. Comece com 10% e suba ao longo de 14 dias.
-
Respeite o opt-out: Usuários que bloqueiam ou denunciam reduzem seu Quality Rating e aumentam a chance de rate limiting.
-
Coordene sistemas: Se múltiplos serviços enviam pelo mesmo número, use uma fila centralizada.
-
Monitore o Quality Rating: Quality Rating baixo = limites mais agressivos.
async function checkQualityAndLimits() {
const response = await fetch(
`https://graph.facebook.com/v22.0/${phoneNumberId}` +
`?fields=quality_rating,messaging_limit_tier`,
{
headers: {
'Authorization': `Bearer ${accessToken}`
}
}
);
const data = await response.json();
console.log('Quality:', data.quality_rating);
console.log('Tier:', data.messaging_limit_tier);
return data;
}
- Use headers de resposta: A Cloud API retorna headers indicando uso de rate limit. Monitore-os:
async function sendAndCheckHeaders(to, message) {
const response = await fetch(/* ... */);
// Headers de rate limit
const remaining = response.headers.get('x-ratelimit-remaining');
const reset = response.headers.get('x-ratelimit-reset');
if (remaining && parseInt(remaining) < 10) {
console.log(`⚠️ Apenas ${remaining} chamadas restantes. Reset em ${reset}s`);
}
return response.json();
}
Conclusão
O erro 131056 é recuperável — ao contrário de outros erros da WhatsApp API, basta aguardar e tentar novamente. A chave é:
- Implementar rate limiting antes de enviar (prevenir > remediar)
- Backoff exponencial com jitter nos retries
- Fila centralizada para coordenar múltiplos sistemas
- Monitoramento ativo para pausar quando a taxa de erros sobe
Precisa de ajuda para escalar sua operação WhatsApp sem rate limits? Fale comigo para consultoria especializada.