# Erreur WhatsApp 131049 : message marketing non délivré

URL: https://wa.genuka.com/docs/errors/131049
Language: French

> Erreur WhatsApp 131049 : Meta a retenu votre template marketing pour préserver l'engagement. La limite par utilisateur, et quand renvoyer sans aggraver.

L'erreur WhatsApp 131049 signifie que Meta n'a pas livré un template marketing à ce destinataire,
le plus souvent parce qu'il a atteint sa limite marketing du moment. Ce n'est ni un bug ni une
sanction de votre numéro. Attendez au moins 24 heures avant de le retenter, sauf s'il a un numéro
américain : là, attendre ne sert à rien.

## Que signifie l'erreur 131049 ?

> « This message was not delivered to maintain healthy ecosystem engagement. »
> — [Meta, codes d'erreur de la Cloud API](https://developers.facebook.com/documentation/business-messaging/whatsapp/support/error-codes#other-errors)

Meta ajoute : « If you do receive this error code and suspect it is due to the limit, wait at
least 24 hours before resending the template message. » La limite en question est la **limite par
utilisateur des templates marketing**
([Meta, Per-user marketing template message limits](https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/marketing-templates/per-user-limits)) :

* WhatsApp peut limiter le nombre de templates marketing qu'une personne reçoit **de toutes les
  entreprises confondues** sur une période, quand elle est peu susceptible de les lire.
* La limite s'adapte à chaque personne : son taux de lecture récent des messages marketing, et le
  nombre de messages déjà présents dans sa boîte, venus de proches comme d'entreprises.
* Chaque template marketing **livré** compte. Si la personne répond, une fenêtre de service de
  24 heures s'ouvre, et les messages marketing envoyés dans cette fenêtre ne comptent pas.
* Renvoyer plusieurs fois en 24 heures à quelqu'un qui a atteint sa limite peut rendre ce
  destinataire injoignable jusqu'à 24 heures de plus, avec le même code 131049. Vos autres
  destinataires ne sont pas touchés.
* La limite n'est pas active pour les envois depuis un numéro de l'Espace économique européen, du
  Royaume-Uni, du Japon ou de Corée du Sud, ni vers un utilisateur de ces pays.

### Pourquoi mes destinataires américains échouent-ils toujours ?

Parce que Meta ne leur livre plus aucun template marketing. Sur la même page :

> « WhatsApp does not currently deliver marketing template messages to WhatsApp users with United
> States phone numbers (numbers composed of a +1 dialing code and a US area code). »

Ce n'est **pas** la limite par utilisateur : ce blocage ne se lève pas au bout de 24 heures, et
Meta n'annonce pas de date de fin. Meta parle seulement d'« une erreur », sans donner de code ;
des intégrateurs indiquent qu'il s'agit de 131049, en place depuis le 1er avril 2025
([Message Central](https://www.messagecentral.com/blog/whatsapp-marketing-usa-allowed)). Seuls
les indicatifs régionaux américains sont visés, pas tous les numéros en +1.

* **Retirez ces numéros de vos campagnes `MARKETING`.** En campagne, un 131049 reçu dès l'appel
  laisse le destinataire `pending` : un numéro américain y restera à chaque relance.
* **Passez par un autre type de message** : un template `UTILITY` ou `AUTHENTICATION` quand le
  contenu s'y prête (ces catégories ne sont pas touchées selon la même source), ou une réponse dans
  la fenêtre de service de 24 heures qu'ouvre un message du client.
* **Ne les replanifiez pas toutes les 24 heures** : chaque envoi que Meta accepte avant de le faire
  échouer compte dans le quota de votre abonnement Genuka WA.

## Quand l'erreur 131049 apparaît-elle ?

Elle ne concerne que les templates de catégorie `MARKETING`, et arrive dans le webhook de statut :
Meta l'écrit noir sur blanc, l'échec est notifié par le webhook `messages` avec le statut `failed`.
Voici l'exemple que donne Meta, tel que Genuka WA vous le transmet dans `data` :

```json title="Webhook message_status (extrait)"
{
  "type": "message_status",
  "field": "messages",
  "data": {
    "id": "wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBI0QUQ2MjA4NEYyRkExNjMyREUA",
    "status": "failed",
    "timestamp": "1751142888",
    "recipient_id": "16505551234",
    "errors": [
      {
        "code": 131049,
        "title": "This message was not delivered to maintain healthy ecosystem engagement.",
        "message": "This message was not delivered to maintain healthy ecosystem engagement.",
        "error_data": {
          "details": "In order to maintain a healthy ecosystem engagement, the message failed to be delivered."
        },
        "href": "/documentation/business-messaging/whatsapp/support/error-codes"
      }
    ]
  }
}
```

### Où la voir dans Genuka WA ?

| Canal                                                          | Ce que vous recevez                                                                                  |
| -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Webhook `message_status`                                       | `data.status: "failed"`, `data.errors[0].code: 131049`                                               |
| Campagne, échec signalé par webhook                            | Le destinataire passe `failed`, avec le message de Meta dans `errorMessage`                          |
| Campagne, refus dès l'appel                                    | Le destinataire reste `pending` : il n'est pas compté en échec, et un nouveau lancement le reprendra |
| Réponse de `POST /api/v1/messages`, si Meta refuse dès l'appel | `400`, `"error": "send_recipient_throttled"`, `meta.code: 131049`                                    |

Genuka WA classe ce code en `recipient_throttled` : le message est correct, le destinataire aussi,
c'est le moment qui ne va pas. Il n'est jamais réessayé dans la foulée, puisque cela ne ferait
qu'allonger le blocage.

## Comment corriger l'erreur 131049 ?

1. **Ne renvoyez rien dans les 24 heures.** C'est la seule consigne de Meta, et la plus enfreinte :
   une relance immédiate ne passe pas et peut prolonger le blocage.
2. **Mettez ces destinataires de côté.** Stockez, à partir du webhook, le numéro et l'heure de
   l'échec. `GET /api/v1/campaigns/{id}/recipients?status=failed&limit=1000` vous donne aussi la
   liste côté campagne, plafonnée à 1 000 lignes et sans pagination : au-delà, fiez-vous à ce que
   vous avez stocké depuis le webhook.
3. **Relancez-les plus tard, dans une nouvelle campagne**, au moins 24 heures après l'échec, sans
   les numéros américains. Une campagne déjà lancée ne renvoie que ses destinataires encore
   `pending`.

**Node.js**

```ts
import { parsePhoneNumberFromString } from "libphonenumber-js";

const RETRY_AFTER_MS = 24 * 60 * 60 * 1000;

// Appelé par votre route webhook, une fois la signature vérifiée.
export async function onMessageStatus(event: {
  type: string;
  data: { status: string; recipient_id: string; errors?: { code: number }[] };
}) {
  if (event.type !== "message_status" || event.data.status !== "failed") return;
  if (!event.data.errors?.some((error) => error.code === 131049)) return;

  // Un numéro américain ne recevra pas plus de marketing dans 24 heures : on le sort des campagnes.
  if (parsePhoneNumberFromString(`+${event.data.recipient_id}`)?.country === "US") {
    await db.marketingExclusion.upsert({ waId: event.data.recipient_id, reason: "us_marketing" });
    return;
  }

  // Votre stockage : une table « à relancer » avec la date à partir de laquelle c'est permis.
  await db.marketingRetry.upsert({
    waId: event.data.recipient_id,
    notBefore: new Date(Date.now() + RETRY_AFTER_MS),
  });
}
```

**Python**

```python
from datetime import datetime, timedelta, timezone

import phonenumbers

RETRY_AFTER = timedelta(hours=24)


# Appelé par votre route webhook, une fois la signature vérifiée.
def on_message_status(event: dict) -> None:
    data = event.get("data", {})
    if event.get("type") != "message_status" or data.get("status") != "failed":
        return
    if not any(error.get("code") == 131049 for error in data.get("errors", [])):
        return

    # Un numéro américain ne recevra pas plus de marketing dans 24 heures : on le sort des campagnes.
    number = phonenumbers.parse("+" + data["recipient_id"])
    if phonenumbers.region_code_for_number(number) == "US":
        exclude_from_marketing(data["recipient_id"])  # votre fonction
        return

    # Votre stockage : une table « à relancer » avec la date à partir de laquelle c'est permis.
    save_marketing_retry(
        wa_id=data["recipient_id"],
        not_before=datetime.now(timezone.utc) + RETRY_AFTER,
    )
```

## Comment éviter l'erreur 131049 ?

* **Ciblez les personnes qui lisent.** La limite dépend du taux de lecture récent de chaque
  destinataire : une liste de clients actifs passe mieux qu'un fichier entier.
* **Invitez à répondre.** Une réponse ouvre une fenêtre de 24 heures dans laquelle vos messages
  marketing ne comptent plus dans la limite.
* **Espacez vos campagnes** vers les mêmes personnes, et retirez de vos listes ceux qui
  accumulent les 131049.
* **Mesurez la livraison sur les webhooks**, pas sur le nombre d'envois acceptés : une campagne
  marketing peut afficher 100 % d'envois acceptés et une part de 131049 à l'arrivée.

## Quels codes sont liés ?

* [131050](https://wa.genuka.com/docs/errors/131050) : la personne a refusé vos messages marketing ; là, il ne faut
  plus jamais renvoyer.
* [131048](https://wa.genuka.com/docs/errors/131048) : c'est **votre numéro** qui est restreint, pour cause de
  signalements, et non un destinataire.
* [131026](https://wa.genuka.com/docs/errors/131026) : le destinataire ne peut rien recevoir du tout.

## FAQ

### L'erreur 131049 pénalise-t-elle mon numéro ?

Non. Meta précise que le blocage lié aux relances excessives ne touche pas votre capacité à
envoyer des messages marketing à d'autres utilisateurs. C'est une limite par destinataire.

### Les templates utilitaires et d'authentification sont-ils concernés ?

La limite décrite par Meta porte sur les templates marketing. Un code de connexion ou une
confirmation de commande dans un template `AUTHENTICATION` ou `UTILITY` n'y est pas soumis.

### Combien de temps dure la limite ?

Meta ne donne pas de durée fixe : la limite s'adapte à l'engagement de chacun. La règle est de ne
pas renvoyer avant 24 heures au minimum.

### Pourquoi certains de mes destinataires européens ne sont-ils jamais en 131049 ?

Parce que la limite n'est pas active vers les utilisateurs de l'Espace économique européen, du
Royaume-Uni, du Japon et de Corée du Sud, ni depuis un numéro de ces pays.

### Un template marketing non livré en 131049 est-il facturé ?

Pas par Meta, qui ne facture un template que lorsqu'il est livré
([Meta, Pricing](https://developers.facebook.com/documentation/business-messaging/whatsapp/pricing)).
Côté Genuka WA, l'envoi accepté par Meta a déjà compté dans le quota de votre abonnement : une
relance trop rapide coûte donc un message de quota sans rien livrer.

## Sources

* [Meta — Error codes](https://developers.facebook.com/documentation/business-messaging/whatsapp/support/error-codes)
* [Meta — Per-user marketing template message limits](https://developers.facebook.com/documentation/business-messaging/whatsapp/templates/marketing-templates/per-user-limits)
* [Meta — Status webhook reference](https://developers.facebook.com/documentation/business-messaging/whatsapp/webhooks/reference/messages/status)
* [Meta — Pricing](https://developers.facebook.com/documentation/business-messaging/whatsapp/pricing)
* [Message Central — WhatsApp marketing in the USA](https://www.messagecentral.com/blog/whatsapp-marketing-usa-allowed)
