# WhatsApp error 131056: pair rate limit — cause and fix

URL: https://wa.genuka.com/en/docs/errors/131056
Language: English

> WhatsApp error 131056: too many messages to the same recipient in a short time. Meta's pair rate limit (1 message every 6 s) and how to retry it properly.

WhatsApp error 131056 means you sent too many messages to the same recipient in too short a time:
at a steady pace, Meta allows one message every 6 seconds per sender-recipient pair. Wait before
writing to that person again; your sends to other numbers can carry on without any pause at all.

## What does error 131056 mean?

> "Too many messages sent from the sender phone number to the same recipient phone number in a
> short period of time."
> — [Meta, Cloud API error codes](https://developers.facebook.com/documentation/business-messaging/whatsapp/support/error-codes#throttling-errors)

Meta advises waiting and retrying if you mean to message that number, and reminds you that you
can message a **different** number without waiting. The rule behind this code is the **pair rate
limit**
([Meta, About the platform](https://developers.facebook.com/documentation/business-messaging/whatsapp/about-the-platform#rate-limits)):

| Rule                         | Value                                                                                                   |
| ---------------------------- | ------------------------------------------------------------------------------------------------------- |
| Steady pace to one recipient | 1 message every 6 seconds (0.17 messages/s)                                                             |
| Equivalent                   | about 10 messages a minute, 600 an hour                                                                 |
| Allowed burst                | up to 45 messages in 6 seconds, borrowed from future quota                                              |
| After a burst                | wait as long as those messages would have taken at the normal pace: a burst of 20 needs about 2 minutes |
| Retry recommended by Meta    | after 4^X seconds, X starting at 0 and growing by 1 after each failure                                  |

## When does error 131056 happen?

* **A duplicate in a campaign list.** Genuka WA does not deduplicate a campaign's recipients: the
  same number listed twice gets two back-to-back sends.
* **A bot that splits its answer** into five or six bubbles sent in a row.
* **A "Resend code" button** with no minimum delay between two taps.
* **A non-idempotent webhook handler** that replies to every redelivery of the same inbound
  message. Genuka WA webhooks can arrive twice: deduplicate on `X-Genuka-Delivery` or on the
  `wamid`.

### Where do you see it in Genuka WA?

| Channel                          | What you get                                                                    |
| -------------------------------- | ------------------------------------------------------------------------------- |
| `POST /api/v1/messages` response | `400`, `"error": "send_retryable"`, `meta.code: 131056`, `meta.retryable: true` |
| Campaign                         | The recipient is retried, then turns `failed` if all three attempts fail        |
| Dashboard, Logs section          | The refused request and the response body                                       |

One detail matters for campaigns: the launcher's three attempts follow each other within two
seconds (waits of at most 500 ms, then 1 s), less than the 6 seconds of the pair rate limit. A
duplicate in the list therefore usually ends up `failed`. The fix is to deduplicate upstream, not
to stretch the retries.

## How do I fix error 131056?

1. **Stop writing to that recipient for now**, and carry on normally with the others.
2. **Retry on Meta's schedule**: 1 s, then 4 s, then 16 s, then 64 s.
3. **Space sends per recipient**: one queue per number, with at least 6 seconds between two
   messages.

**Node.js**

```ts
const API = "https://wa.genuka.com/api/v1";
const PAIR_GAP_MS = 6_000;
const lastSentTo = new Map<string, number>(); // move this to Redis if you run several workers

async function send(payload: { connectionId: string; to: string } & Record<string, unknown>) {
  const response = await fetch(`${API}/messages`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.GENUKA_WA_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
  });
  return { response, json: await response.json() };
}

export async function sendToRecipient(payload: { connectionId: string; to: string } & Record<string, unknown>) {
  // 1. Respect the minimum gap to this recipient.
  const wait = (lastSentTo.get(payload.to) ?? 0) + PAIR_GAP_MS - Date.now();
  if (wait > 0) await new Promise((resolve) => setTimeout(resolve, wait));

  // 2. On 131056, retry after 4^X seconds: 1 s, 4 s, 16 s, 64 s, so five attempts in all.
  for (let x = 0; x <= 4; x++) {
    const { response, json } = await send(payload);
    lastSentTo.set(payload.to, Date.now());
    if (response.ok) return json.data;
    if (json.meta?.code !== 131056) throw new Error(`${json.error}: ${json.message ?? ""}`);
    if (x === 4) break; // no wait after the last attempt
    await new Promise((resolve) => setTimeout(resolve, 4 ** x * 1_000));
  }
  throw new Error("131056: recipient still rate-limited, reschedule");
}
```

**Python**

```python
import os
import time

import requests

API = "https://wa.genuka.com/api/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['GENUKA_WA_API_KEY']}",
    "User-Agent": "acme-crm/1.0 (+https://example.com)",
}
PAIR_GAP = 6.0
last_sent_to: dict[str, float] = {}  # move this to Redis if you run several workers


def send_to_recipient(payload: dict) -> dict:
    wait = last_sent_to.get(payload["to"], 0) + PAIR_GAP - time.time()
    if wait > 0:
        time.sleep(wait)

    for x in range(5):  # five attempts, with 1 s, 4 s, 16 s, 64 s between them
        response = requests.post(f"{API}/messages", json=payload, headers=HEADERS, timeout=30)
        last_sent_to[payload["to"]] = time.time()
        body = response.json()
        if response.ok:
            return body["data"]
        if body.get("meta", {}).get("code") != 131056:
            raise RuntimeError(f"{body.get('error')}: {body.get('message', '')}")
        if x == 4:
            break  # no wait after the last attempt
        time.sleep(4 ** x)
    raise RuntimeError("131056: recipient still rate-limited, reschedule")
```

## How do I prevent error 131056?

* **Deduplicate your lists before `POST /api/v1/campaigns`**, on the normalized number (digits
  only, with country code): `+237 690 00 00 01` and `237690000001` are the same recipient.
* **Group your bubbles.** One message of up to 4,096 characters beats five short ones sent in a
  row.
* **Put a minimum delay on code resends**, 30 to 60 seconds, which also protects your users from
  abuse.
* **Make webhook handling idempotent**, so a redelivery never triggers a second reply.

## Related error codes

* [130429](https://wa.genuka.com/en/docs/errors/130429): the number's **overall** throughput is reached, across all
  recipients.
* [131048](https://wa.genuka.com/en/docs/errors/131048): sends restricted because of spam reports; insisting on one
  recipient does not help.

## FAQ

### Does error 131056 block my sends to other customers?

No. Meta says so: you can keep messaging other numbers without waiting. Only the sender-recipient
pair concerned is slowed down.

### How many messages can I send one customer per hour?

At a steady pace, about 600, one every 6 seconds. A burst of 45 messages in 6 seconds is
tolerated, but you pay for it afterwards with an equivalent wait.

### Should I retry on a fixed or growing delay?

Growing. Meta recommends 4^X seconds, X starting at 0: 1 s, 4 s, 16 s, 64 s. A short fixed delay
resends the request while the limit is still in force.

## Sources

* [Meta — Error codes](https://developers.facebook.com/documentation/business-messaging/whatsapp/support/error-codes)
* [Meta — About the platform, pair rate limits](https://developers.facebook.com/documentation/business-messaging/whatsapp/about-the-platform#rate-limits)
* [Meta — Throughput](https://developers.facebook.com/documentation/business-messaging/whatsapp/throughput)
