Pular para o conteúdo

Rate limits

Existe limite de taxa, e ele protege a plataforma contra abuso. O que você precisa saber antes de mais nada é por onde ele conta.

O queLimite
Qualquer requisição à plataforma3.000 por minuto, por endereço IP

Contar por IP tem duas consequências que mudam o desenho da sua integração:

  • Vários tokens não multiplicam a cota. Se os dois rodam no mesmo servidor, dividem o mesmo teto.
  • Vários servidores dividem o teto por servidor. Cada IP tem os seus 3.000 por minuto.

Alguns caminhos pesados têm limite adicional, e este sim conta por conta ou por usuário:

EndpointLimiteConta por
GET /contacts/search100/minutoConta
GET /api/v2/.../reports100/minutoUsuário (ou token)
GET /api/v2/.../reports1.000/minutoConta
POST .../upload60/horaConta
GET .../conversations/{id}/transcript30/horaConta
Gatilho de webhook de fluxo120/minutoURL do fluxo
Envio de formulário público20/horaIP
Conversão de landing page120/horaIP
Conversão de site cadastrado (web_properties/.../conversions)10.000/horaIP e token (lead parcial conta)
Visita de site (web_properties/.../pageviews)300/horaIP
Prova de consentimento (.../consent)60/hora na landing page · 10.000/hora pelo servidor do site · 3.000/hora por tokenIP / token

Há ainda tetos de segurança no login, na redefinição de senha e na verificação em duas etapas — poucas tentativas por período, para travar ataque de força bruta. Não atrapalham integração nenhuma.

A resposta não traz X-RateLimit-Limit, X-RateLimit-Remaining nem X-RateLimit-Reset. Também não traz Retry-After.

Ao estourar o limite, a resposta é:

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

Corpo em texto puro, não em JSON. Se o seu cliente faz response.json() sem olhar o status, ele vai quebrar aqui com um erro de parse que não explica nada — trate o 429 antes de tentar ler o corpo.

import time, requests
def chamar(metodo, url, **kwargs):
espera = 5
for _ in range(6):
r = requests.request(metodo, url, **kwargs)
if r.status_code != 429:
return r
time.sleep(espera) # não há Retry-After: o passo é seu
espera = min(espera * 2, 60)
raise RuntimeError("limite de taxa persistente")

O período do limite geral é de um minuto corrido, então esperar até um minuto sempre resolve.

3.000 por minuto é bastante, mas disparados de uma vez batem no teto em segundos. Espalhe:

import time
POR_SEGUNDO = 20
for item in itens:
processar(item)
time.sleep(1 / POR_SEGUNDO) # 1.200/min, folgado

Ficar perguntando “mudou alguma coisa?” queima cota à toa:

# caro
while True:
r = requests.get(f"{BASE_URL}/conversations?status=open")
processar(r.json())
time.sleep(30)

O webhook avisa quando muda. Lembrando que ele é entregue uma vez só — para o que não pode faltar, combine com uma leitura periódica.

Caixas de entrada, etiquetas, funis e etapas, atributos personalizados: leia uma vez, guarde, atualize de hora em hora.

from functools import lru_cache
@lru_cache(maxsize=1)
def caixas():
return requests.get(f"{BASE_URL}/inboxes", headers=HEADERS).json()

Criar dez mil contatos em dez mil chamadas é o caminho errado. A importação por planilha no painel faz isso em uma operação, sem passar pela API.

Em vez de 40 chamadas de 25 registros, peça per_page=100 e faça 10. O teto de página é 100.

Posso rodar 1.000 requisições em um segundo? Cabe no minuto, mas é o jeito de esbarrar em tudo que tem teto menor. Distribua.

Erro 4xx conta no limite? Conta. O limite é de requisições, não de sucessos.

Dois servidores meus usando o mesmo token dividem a cota? Não, se tiverem IPs diferentes — o limite geral é por IP. Mas os tetos específicos da tabela acima contam por conta, e esses vocês dividem.

Recebo mensagem de WhatsApp em volume. Isso consome minha cota da API? Não. Receber mensagem acontece dentro do app.smart, não pela API.

O limite muda em horário de pico? Não. É constante.

Preciso de mais que isso. E aí? Fale com o suporte descrevendo o volume e o caso. O teto geral é configurável do nosso lado, mas quase sempre o problema real é desenho de integração — e aí a conversa rende mais que o aumento.