Rate Limits
No message quota, the abuse protections that answer 429, WhatsApp's own limits and good sending habits.
No message quota
The Wappfy API does not cap how many messages you send. The pace is yours.
What the API does have is a small set of abuse protections. They only catch patterns no legitimate integration needs, and they answer 429 with a Retry-After header.
Abuse protections
| What triggers it | Code | What happens |
|---|---|---|
| Repeated invalid keys: 20 requests with a missing or invalid key from the same IP within 10 minutes | muitas_tentativas | The IP is blocked for 15 minutes: requests from it without a valid key answer 429. Requests with a valid key keep working, even from that IP. |
| Burst: more than 200 requests within 10 seconds with the same key | excesso_de_pedidos | The extra requests are refused. 200 back-to-back requests pass; the sustained rate that passes is about 20 per second. |
| Polling loop: the same read (same key, route and query) more than 60 times within 1 minute | consulta_repetida | The extra reads are refused, which means about one per second sustained. |
The reads that count for consulta_repetida are the state reads: GET /instance, /instance/qr, /chats, /chats/{chatId}/messages, /contacts, /groups, /labels, /profile, and the other group, contact, label and presence reads.
Short cache on reads
Within 10 seconds, the same read can be answered from a cache instead of going to WhatsApp. When that happens the response carries an Age header. Reading every few seconds stays well inside the limit.
Two reads are never cached because they change too fast: the QR code (GET /instance/qr) and a chat's presence (GET /chats/{chatId}/presence). The presence read still counts toward consulta_repetida.
To follow the connection status and your messages, use webhooks (instance.status, message.status), not a polling loop. They arrive as soon as something changes.
Handling 429
{
"error": {
"codigo": "excesso_de_pedidos",
"mensagem": "Pedidos demais em poucos segundos com esta chave. Aguarde o tempo indicado em Retry-After e espace os pedidos."
}
}- Read
codigoto know which limit you hit. - For
muitas_tentativas,excesso_de_pedidosandconsulta_repetida, wait the number of seconds inRetry-After, then resume at a slower pace. - For
bloqueio_temporarioandlimite_do_whatsapp, see below: those come from WhatsApp, not from Wappfy.
WhatsApp's own limits
WhatsApp watches how each number behaves and bans numbers that act like spam bots. When it limits your number, the API answers:
| Code | Meaning |
|---|---|
bloqueio_temporario | WhatsApp blocked sends from this number for a while (WhatsApp error 463). |
limite_do_whatsapp | WhatsApp is rate-limiting this number. |
Stop sending and wait before trying again. Insisting increases the risk of a ban.
To protect your number:
- Space your sends: a few seconds between messages, with some variation, especially to people who never wrote to you.
- Avoid mass sends to cold lists and identical messages in a row.
Size limits
| Limit | Value |
|---|---|
Request body (including base64 media) | 25 MB (413 corpo_grande_demais). Base64 adds about a third, so a file of roughly 18 MB fits. |
File sent by url | 50 MB (413 midia_grande), downloaded by Wappfy within 30 seconds, following up to 3 redirects |
| Text message | 65,536 characters |
| Caption | 1,024 characters |
For files larger than about 18 MB, send them by url.
Good habits
Webhooks over polling
message.status tells you about delivered and read; instance.status tells you the connection dropped.
Idempotency-Key on every send
So an automatic retry never becomes a second message.
Back off on 5xx
Retry 502, 503 and 504 with growing waits (and Retry-After when present). Check the chat first on resultado_incerto.
One key per system
The burst limit is per key, so one busy system doesn't slow down another.

