Rate Limits

Entenda os limites de requisição e estratégias para uso eficiente da API.

Visão Geral

Esta página registra as cotas das APIs descritas abaixo, aplicadas pelo Rack::Attack em produção. Os valores exibidos são os padrões definidos no código e podem ser alterados pelo operador nas variáveis indicadas. Quando mais de uma regra corresponde à requisição, vale a primeira cota atingida. Ao exceder uma cota, a API retorna 429 Too Many Requests.

A coluna Configuração distingue regras fixas das configuráveis e informa o padrão usado pelo código. Este inventário garante somente as regras implementadas no backend atual; cotas apenas planejadas ou descritas fora dele não fazem parte do contrato.

Em desenvolvimento e teste, esse middleware fica desabilitado. Portanto, valide limites no ambiente de produção ou em um ambiente iniciado explicitamente como produção, sem usar uma carga que afete usuários reais.

Resposta 429

O contrato atual não adiciona headers X-RateLimit-Limit, X-RateLimit-Remaining ou X-RateLimit-Reset. A opção do Rack::Attack que adicionaria Retry-After também está desabilitada. Não dependa desses headers para controlar retentativas.

http
HTTP/1.1 429 Too Many Requests
Content-Type: text/plain

Retry later

Global e Autenticação

Além das regras específicas, toda requisição conta para o limite global por IP. Não existe uma cota geral por token, inbox ou app. Login com MFA não consome as regras de login comum: usa as duas regras MFA, por IP e por token.

RegraMétodo / rotaLimiteJanelaChaveConfiguração
req/ipQualquer rota, exceto safelists3.0001 minutoIPRACK_ATTACK_LIMIT (padrão 3000)
super_admin_login/ipPOST /super_admin/sign_in55 minutosIPFixo
super_admin_login/emailPOST /super_admin/sign_in515 minutosEmail normalizadoFixo
login/ipPOST /auth/sign_in sem mfa_token55 minutosIPFixo
login/emailPOST /auth/sign_in sem mfa_token1015 minutosEmail normalizadoFixo
reset_password/ipPOST /auth/password530 minutosIPFixo
reset_password/emailPOST /auth/password51 horaEmail normalizadoFixo
resend_confirmation/ipPOST /resend_confirmation530 minutosIPFixo
resend_confirmation/emailPOST /resend_confirmation51 horaEmail normalizadoFixo
resend_confirmation_auth/ipPOST /api/v1/profile/resend_confirmation530 minutosIPFixo
mfa_verification/ipDELETE /api/v1/profile/mfa; POST /api/v1/profile/mfa/verify ou /api/v1/profile/mfa/backup_codes51 minutoIPFixo
mfa_login/ipPOST /auth/sign_in com mfa_token101 minutoIPFixo
mfa_login/tokenPOST /auth/sign_in com mfa_token101 minutomfa_tokenFixo
accounts/ipPOST /api/v1/accounts530 minutosIPFixo

RACK_ATTACK_ALLOWED_IPS acrescenta IPs à safelist; localhost já é permitido. A rota /health também é isenta. Em produção, ENABLE_RACK_ATTACK=false desliga todas as regras.

Widget

Estas três regras existem somente quando ENABLE_RACK_ATTACK_WIDGET_API é true, que é o padrão. O limite global continua valendo em paralelo.

RegraMétodo / rotaLimiteJanelaChaveConfiguração
api/v1/widget/conversationsPOST /api/v1/widget/conversations612 horasIPFixo; ENABLE_RACK_ATTACK_WIDGET_API
api/v1/widget/contactsPATCH ou PUT /api/v1/widget/contacts601 horaIPFixo; ENABLE_RACK_ATTACK_WIDGET_API
widget?website_token={website_token}&cw_conversation={x-auth-token}Qualquer método em /widget sem cw_conversation51 horaIPFixo; ENABLE_RACK_ATTACK_WIDGET_API

APIs Autenticadas

Regras por conta extraem account_id da rota. As regras por usuário de relatórios e meta usam uid quando presente e, caso contrário, api_access_token; sem um desses identificadores, a requisição não entra nessa cota por usuário, mas continua sujeita às demais regras correspondentes.

RegraMétodo / rotaLimiteJanelaChaveConfiguração
/api/v1/accounts/:account_id/conversations/:conversation_id/transcriptQualquer método no prefixo /api/v1/accounts/{account_id}/conversations/{conversation_id}/transcript1.0001 horaaccount_idRATE_LIMIT_CONVERSATION_TRANSCRIPT (padrão 1000)
/api/v1/accounts/:account_id/uploadQualquer método no prefixo /api/v1/accounts/{account_id}/upload601 horaaccount_idFixo
/api/v1/accounts/:account_id/contacts/searchQualquer método no prefixo /api/v1/accounts/{account_id}/contacts/search1001 minutoaccount_idRATE_LIMIT_CONTACT_SEARCH (padrão 100)
/api/v2/accounts/:account_id/reports/userQualquer método no prefixo /api/v2/accounts/{account_id}/reports1001 minutouid ou api_access_token + account_idRATE_LIMIT_REPORTS_API_USER_LEVEL (padrão 100)
/api/v2/accounts/:account_id/reportsQualquer método no prefixo /api/v2/accounts/{account_id}/reports1.0001 minutoaccount_idRATE_LIMIT_REPORTS_API_ACCOUNT_LEVEL (padrão 1000)
/api/v1/accounts/:account_id/conversations/meta/userGET /api/v1/accounts/{account_id}/conversations/meta...301 minutouid ou api_access_token + account_idRATE_LIMIT_CONVERSATIONS_META (padrão 30)
whatsapp_templates/createPOST /api/v1/accounts/{account_id}/whatsapp_templates101 horaaccount_idRATE_LIMIT_WHATSAPP_TEMPLATE_CREATE (padrão 10)
whatsapp_templates/updatePUT ou PATCH /api/v1/accounts/{account_id}/whatsapp_templates/{id}301 horaaccount_idRATE_LIMIT_WHATSAPP_TEMPLATE_UPDATE (padrão 30)
whatsapp_templates/destroyDELETE /api/v1/accounts/{account_id}/whatsapp_templates/{id}301 horaaccount_idRATE_LIMIT_WHATSAPP_TEMPLATE_DESTROY (padrão 30)
whatsapp_templates/syncPOST /api/v1/accounts/{account_id}/whatsapp_templates/sync55 minutosaccount_idRATE_LIMIT_WHATSAPP_TEMPLATE_SYNC (padrão 5)

Automações e Webhooks

As credenciais dos webhooks são convertidas em SHA-256 antes de compor a chave armazenada. O webhook de automação de pipeline aceita o token no path, query ou body JSON; sem token, essa regra específica não cria uma chave, embora o limite global por IP continue ativo.

RegraMétodo / rotaLimiteJanelaChaveConfiguração
sequence_external_start_per_accountPOST /api/v1/accounts/{account_id}/pipeline/cards/{id}/sequences/external_start601 minutoaccount_idFixo
sequence_external_start_per_userPOST /api/v1/accounts/{account_id}/pipeline/cards/{id}/sequences/external_start101 minutoapi_access_tokenFixo
sequence_hmac_trigger_per_tokenPOST /webhooks/sequence-trigger/{token}1201 minutoSHA-256 do tokenFixo
sequence_hmac_trigger_per_ipPOST /webhooks/sequence-trigger/{token}2401 minutoIPFixo
pipeline_automation_webhook_per_tokenPOST /api/v1/pipeline_automation_webhooks ou /api/v1/pipeline_automation_webhooks/{token}1201 minutoSHA-256 do token de path/query/bodyFixo
pipeline_bulk_delete_per_tokenPOST /api/v1/accounts/{account_id}/pipeline/bulk_actions/delete301 minutoapi_access_tokenFixo
pipeline_bulk_delete_per_accountPOST /api/v1/accounts/{account_id}/pipeline/bulk_actions/delete1001 minutoaccount_idFixo

Módulo de Atendimentos — Limites por Canal

O módulo de Atendimentos está disponível em todas as licenças. O widget anônimo depende da habilitação operacional do agendamento público na conta; as APIs autenticadas não são bloqueadas por plano nem possuem uma regra própria por token ou por conta — recebem apenas as cotas gerais ou outras regras que também correspondam à rota.

RegraMétodo / rotaLimiteJanelaChaveConfiguração
public_appointments_read/ipGET /public/api/v1/inboxes/{inbox_identifier}/appointments/services, /professionals ou /slots1201 minutoIPRATE_LIMIT_PUBLIC_APPOINTMENT_READ (padrão 120)
public_appointments_booking/ipPOST /public/api/v1/inboxes/{inbox_identifier}/appointments101 horaIPRATE_LIMIT_PUBLIC_APPOINTMENT_BOOKING (padrão 10)

Tratando Erro 429

Quando receber um erro 429, use backoff exponencial para retentar a requisição:

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    // O backend atual não envia Retry-After; mantenha o fallback.
    const retryAfter = response.headers.get("Retry-After");
    const delay = retryAfter
      ? parseInt(retryAfter) * 1000
      : Math.pow(2, attempt) * 1000;

    console.log(`Rate limited. Aguardando ${delay}ms...`);
    await new Promise((resolve) => setTimeout(resolve, delay));
  }

  throw new Error("Max retries exceeded");
}

Boas Práticas

  • Controle localmente a taxa de chamadas; a resposta não informa quantas requisições restam
  • Use backoff exponencial com jitter aleatório para retries
  • Agrupe operações somente quando o endpoint oferecer uma operação em lote
  • Implemente cache local para dados que não mudam frequentemente
  • Use webhooks em vez de polling para receber atualizações em tempo real
  • Não presuma que o valor padrão é o valor implantado: o operador pode sobrescrever as cotas configuráveis