WhatsApp error 131050: the opt-out you only learn once
The short answer
Error 131050 means the recipient has switched off marketing messages from your business. Meta's guidance is not to retry. It arrives asynchronously as a failed status on the messages webhook, never in the send response, and Meta documents no endpoint for reading a user's current preference, only the user_preferences webhook event. Checked 11 September 2026.
What does WhatsApp error 131050 mean?
131050 means the person you tried to send a marketing template to has switched off marketing messages from your business. Meta's error reference gives the text word for word:
"Unable to deliver the message. This recipient has chosen to stop receiving marketing messages on WhatsApp from your business." (Meta - WhatsApp error codes)
That sentence repays an exact transcription. Meta's wording is from your business, not "from this business", and the difference is not cosmetic: the preference is scoped to you, the sender, rather than to WhatsApp marketing in general.
The remedy Meta publishes alongside it is equally direct, and it is the only instruction on the row:
"Do not retry sending messages to this user as they will not be received. To be notified whenever a WhatsApp user stops or resumes delivery of marketing template messages from your business, subscribe to the user_preferences webhook." (Meta - WhatsApp error codes)
That second sentence is where the problem starts. Meta is telling you to subscribe to a webhook so that you learn about opt-outs some way other than by hitting this error. Which raises the question no error-code page answers: if you were not subscribed at the moment the customer tapped stop, how do you ever find out?

The honest answer is that you do not, and Meta offers no way to catch up. An opt-out list on the WhatsApp Business Platform is an event-sourced projection whose completeness is capped by your webhook uptime, and 131050 is less a per-message error than an audit signal saying your copy of the truth has already drifted.
- What does WhatsApp error 131050 mean?
- Where does 131050 actually arrive, if not in the API response?
- Is there any API to read a user's marketing preference?
- What does the user_preferences webhook payload contain?
- What happens to your opt-out list while the webhook endpoint is down?
- How is 131050 different from 131049?
- Do utility and authentication templates still reach an opted-out user?
- What does the customer actually tap to switch marketing off?
- What should happen in your own system the moment a stop arrives?
- Does honouring 131050 cover what WhatsApp's policy requires?
Where does 131050 actually arrive, if not in the API response?
Several of the pages ranking for this code imply you catch it where you catch everything else: in the response to POST /messages. Code written that way will never see it. Meta states the general rule on the error page itself:
"Cloud API errors are returned either synchronously as a Graph API response, asynchronously via Webhook, or sometimes through both methods." (Meta - WhatsApp error codes)
131050 is in the asynchronous group, and Meta says which one outright. The changelog entry that introduced the code, dated 18 November 2024, reads:
"Added error code 131050 for messages webhooks, indicating message non-delivery due user marketing preferences." (Meta - WhatsApp changelog)
Messages webhooks. Not the send response. The same changelog entry adds the user_preferences field itself, which is why the two have always been documented as a pair.
What happens instead is easy to miss. Your send is accepted, you get a message id, and then a failed status arrives on the messages webhook carrying 131050 in its errors array. If your pipeline treats a successful POST /messages as a delivered send, or logs webhook statuses to a table nobody queries, the opt-out is recorded somewhere in your infrastructure and visible nowhere.
| Signal | Arrives | What it costs to obtain |
|---|---|---|
user_preferences webhook |
The instant the user changes the setting | Nothing. Subscribe once |
131050 on a failed status |
After you attempt a send | One marketing message you were told not to send |
| A read API | Never. Not documented | Not available |
That changes what "handling 131050" means. Catching it in your send path is not error handling; it is the discovery mechanism of last resort, and every discovery through it is a message that should not have gone out.
Is there any API to read a user's marketing preference?
No, and this is the single most useful thing to know about the code.
Meta's user_preferences reference documents a webhook and nothing else: a Triggers section, a Syntax block, a parameter table and an example payload. No GET endpoint, no field on the contact object carrying a current preference, and nothing in the developer documentation pointing at one in WhatsApp Manager either. The reference's whole job is stated in one line:
"The user_preferences webhook notifies you of changes to a WhatsApp user's marketing message preferences." (Meta - user_preferences webhook reference)
Changes. Not state. A negative claim deserves the same scrutiny as a positive one, so to be precise about what was checked: the user_preferences reference documents no read operation, and neither the messages webhook reference nor the error-codes page names one either. If Meta ships a lookup later, that page is where it would appear.
The consequence is structural. Every other list you keep about a customer can be rebuilt from a source of record. This one cannot. There is no backfill, no replay of missed events, and no reconciliation call that returns every user who has switched you off. Your opt-out list is whatever your endpoint happened to catch, and nothing will tell you what it missed.
What does the user_preferences webhook payload contain?
This is the payload Meta publishes as its own example, reproduced as written:
{
"object": "whatsapp_business_account",
"entry": [{
"id": "102290129340398",
"changes": [{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "15550783881",
"phone_number_id": "106540352242922"
},
"contacts": [{ "wa_id": "16505551234" }],
"user_preferences": [{
"wa_id": "16505551234",
"detail": "User requested to resume marketing messages",
"category": "marketing_messages",
"value": "resume",
"timestamp": 1731705721
}]
},
"field": "user_preferences"
}]
}]
}
A stop event is the same shape with the opposite values. Meta's parameter table describes three of those four fields, in these words:
| Field | What Meta's parameter table says | Value on a stop |
|---|---|---|
value |
"Marketing message preference." | stop |
detail |
"Description of marketing message preference." | User requested to stop marketing messages |
timestamp |
"Unix timestamp indicating when the webhook was triggered." | Integer |
category |
No row at all | marketing_messages |
That last row is worth pausing on. category appears only inside the example payload, hardcoded, with no entry in the parameter table and therefore no documented list of the values it can take. marketing_messages is the only one anybody has seen. Write your handler so an unrecognised category is stored and skipped rather than assumed to be marketing.
One more detail in that reference repays a careful read: a caution attached to the user identifier, noting that a WhatsApp user's ID and phone number may not always match. A suppression table keyed strictly on a normalised E.164 number works right up until it silently does not, and the failure mode is an opt-out that was received, parsed, stored under a key nothing looks up, and then contradicted by a campaign.
What happens to your opt-out list while the webhook endpoint is down?
Nothing visible. That is the problem.
A user_preferences event fires once, at the moment the setting changes. Meta's webhooks documentation is explicit about what happens when your server does not take it:
"If any update sent to your server fails, we will retry immediately, then try a few more times with decreasing frequency over the next 36 hours." (Meta - Webhooks, Getting started)
and, on the same page, "Unacknowledged responses will be dropped after 36 hours." The sentence that makes this article necessary is there too:
"You will not be able to query historical webhook event notification data, so be sure to capture and store any webhook payload content that you want to keep." (Meta - Webhooks, Getting started)
So the hole is not vaguely "a period of downtime". It is precisely whatever your endpoint failed to acknowledge inside 36 hours, and it is permanent.
The hole also has no shape. You cannot count it, you cannot list the affected numbers, and the only way to find one is to send the message you were told not to send and watch a 131050 come back. A lapsed certificate, a four-minute deploy or a firewall change does the damage, and it surfaces weeks later in a campaign report. The diagnostic path is the same as for any missed inbound event, covered in why a verified WhatsApp webhook can still receive nothing.
This is why "subscribe to the webhook" is a true instruction and an incomplete answer. The practical mitigations are unglamorous: alert on the absence of user_preferences events rather than only on their content, record your endpoint's downtime windows where a campaign owner can see them, and treat every 131050 as a report that your store was already wrong.
How is 131050 different from 131049?
These two are conflated constantly, including on pages that list both. They differ in kind, and the correct response to each is the opposite of the response to the other.
131049 is Meta's own per-user frequency cap:
"WhatsApp may limit the number of marketing template messages a WhatsApp user receives from any business in a given period of time when they are less likely to be receptive and engage with those messages." (Meta - Per-user marketing template message limits)
and the same page states how it reaches you:
"If a marketing template message is not delivered due to per-user marketing template limit enforcement or a business has repeatedly attempted to resend a message to a user that has reached their limit, the messages webhook is triggered with status set to failed and error code set to 131049." (Meta - Per-user marketing template message limits)
Note "from any business". 131049 counts across every sender and the customer took no action to cause it. 131050 counts only against you, and the customer chose it.
| What differs | 131049 | 131050 |
|---|---|---|
| Who decided | The recipient | |
| Scope | Across every business | Your business only |
| Lifetime | Temporary | Standing until the user resumes |
The retry advice follows. Meta's guidance on 131049 is to wait at least 24 hours before resending; its guidance on 131050 is not to retry at all. A queue treating both as "failed, back off and try later" will eventually retry an opt-out, and repeatedly messaging someone who asked you to stop is a policy problem rather than a delivery one. What error 131049 means and what to do about it covers that code on its own terms.
Do utility and authentication templates still reach an opted-out user?
Several of the pages ranking for this code say yes. I could not find that stated anywhere in Meta's documentation, and this page is not going to launder an inference into a fact.
What Meta does state is narrower. The preference carries category: "marketing_messages" and no other category. The error text names marketing messages specifically. The user_preferences reference describes stopping and resuming marketing messages and says nothing about any other message type. The user-facing control, described below, is about offers and announcements.
From that it is reasonable to infer that a utility or authentication template is unaffected, and most implementations already rely on the inference. It is still an inference. Treat it as a working assumption rather than a guarantee to promise a customer, and where it matters commercially, an OTP that must arrive or a delivery notification someone is waiting on, confirm it against your own send records for a user you know has opted out rather than against anyone's blog, including this one.
What does the customer actually tap to switch marketing off?
The control the customer sees and the string your code receives are not the same words, which is why searching Meta's developer documentation for the user-facing name returns nothing useful.
Meta's newsroom describes the consumer surface:
"WhatsApp gives people tools to share feedback on messages they receive from businesses using the interested and not interested buttons when they receive offers and announcements such as a coupon for a holiday sale, information about new products, back-in-stock alerts, or reminders about upcoming sales and events. They can also turn off/on the option to receive these types of messages at any time." (Meta Newsroom - Ways to manage your business chats on WhatsApp, 3 April 2025)
So the customer sees Offers and announcements, plus Interested and Not interested buttons. Your API sees marketing_messages. Nothing in either vocabulary points at the other, and the webhook is deliberately blind to half of that surface:
"Note: This webhook triggers only when a user stops or resumes marketing messages. It does not trigger when a user indicates Interested or Not interested feedback through the Offers and announcements setting." (Meta - user_preferences webhook reference)
Meta collects that feedback and never forwards it. A customer can press Not interested on three of your campaigns in a row and your own data will show three delivered messages and no dissent at all. If your campaign reporting looks healthy and your reach is capped anyway, this is one of the invisible inputs.
What should happen in your own system the moment a stop arrives?
Four things, in this order, and none of them is a retry.
- Persist it before you acknowledge it. Write the event to durable storage and return 200 after the write, not before. A 200 tells Meta to stop retrying, and a 200 from a handler that then throws is how an opt-out is lost while both sides believe it was delivered.
- Key the record on the identifier Meta sent, with the phone number stored alongside rather than as the primary key, for the reason in the payload section above.
- Enforce it at send time, per recipient, not at campaign launch. A campaign built on Monday and sent on Thursday has a three-day window in which a
stopcan arrive, and an audience frozen at launch will happily send into it. - Record the
resumeas carefully as thestop. The values are symmetrical and a customer who turns marketing back on has told you something valuable. A store that only ever writes suppressions cannot represent that.

The third point is where platforms differ, and it is worth asking yours directly. In WabaCRM the audience is a stored filter until launch and the dispatcher re-checks consent per recipient as it sends, so an opt-out landing mid-campaign stops the remaining messages rather than only the next campaign. Whatever the platform, the question is the same: at what moment is the suppression list read, and what happens to a send queued before the stop arrived.
Does honouring 131050 cover what WhatsApp's policy requires?
Not on its own, and this is the part a purely technical reading of the error misses. The WhatsApp Business Messaging Policy sets the obligation wider than any one signal:
"You must respect all requests (either on or off WhatsApp) by a person to block, discontinue, or otherwise opt out of communications from you via WhatsApp, including removing that person from your contacts list." (WhatsApp Business Messaging Policy)
"Either on or off WhatsApp" is doing the work there. A customer who replies STOP in the chat, emails your support address, tells a salesperson on the phone, or unsubscribes from your mailing list has made a request you are required to respect, and none of those produces a user_preferences event or a 131050. Meta's own opt-in guidance points the same way, asking businesses to provide clear instructions for how people can opt out of receiving specific categories of messages, and honour those requests.
So 131050 is the floor, not the ceiling. The platform preference is one input to a suppression list that also has to absorb keyword replies, off-platform requests and your own consent record. The consent side of that is covered in what WhatsApp actually requires from an opt-in, and the two halves are worth designing together: a business that collects consent carefully and then keeps its opt-outs in an incomplete event log has only solved the half that shows up in an audit.
Every Meta quotation on this page was read from Meta's own documentation on 11 September 2026. Meta changes that documentation without notice; the linked pages are authoritative and this one is not.
Questions people also ask
Can a business reverse a 131050 opt-out from its side?
Does the user_preferences webhook need its own subscription?
Will 131050 appear even if I never subscribed to user_preferences?
Does switching marketing off stop every business or just mine?
Is the wa_id in the payload always the customer's phone number?
- whatsapp error 131050
- user_preferences webhook
- whatsapp marketing opt-out
- whatsapp cloud api errors
- marketing template messages