Skip to content

Engineering

WhatsApp error 131047 (re-engagement message): what it means and how to fix it

Why free-form replies fail with 131047 once 24 hours pass since the customer's last message, how to resend as an approved template, and how to check the window in code before sending.

By Broadchat teamPublished 8 min read

In short

WhatsApp error 131047 means you tried to send a free-form (non-template) message more than 24 hours after the customer last messaged or called you, so the customer service window is closed. Meta's fix is simple: send an approved message template instead. When the customer replies, a new 24-hour window opens and free-form messages work again. To avoid it, check the time of the customer's last inbound message before you send anything that is not a template.

Key takeaways

  • 131047 is returned when a free-form message is sent outside the 24-hour customer service window; webhooks usually title it "Re-engagement message".
  • The window starts only when the customer messages or calls you, and resets with each new inbound message; your own messages never extend it.
  • The only fix Meta lists is to send an approved template; any reply from the customer then reopens the window for 24 hours.
  • Store the last inbound timestamp per contact and switch to a template automatically when it is older than 24 hours.
  • A message that fails with 131047 is not delivered, so Meta does not charge for it; the template you send instead is charged by its category.

WhatsApp error 131047 means the customer service window with that person has closed. Meta's error reference says: "More than 24 hours have passed since the recipient last replied to the sender number." Its listed solution is one line: "Send the recipient a template message instead." Nothing is wrong with your number, your token or the recipient. You tried to send a free-form message (text, image, document, interactive buttons and so on) at a time when WhatsApp only accepts pre-approved message templates.

What the 24-hour rule actually is

Meta's messaging docs define the customer service window like this: when a WhatsApp user messages you or calls you, a 24-hour timer starts. If they message or call again before it expires, the timer resets to 24 hours. While it is open you can send any service message type. When it closes, you can only send template messages.

Three details catch people out:

  1. Only the customer opens the window. Your outgoing messages, delivery receipts and read receipts do not start or extend it. If you sent five messages yesterday and the customer never answered, the window is closed today.
  2. It is measured from the customer's last message, not the first. A long conversation that ended at 4:10 pm on Monday closes at 4:10 pm on Tuesday.
  3. It is per customer and per business number. A customer who messaged your sales number has not opened a window with your support number.

In webhook payloads the error title is usually shown as Re-engagement message, which is why people search for both terms. Meta advises building error handling on the numeric code, not the title, because titles change.

Why it happens in real projects

The error is easy to understand and still very common, because the 24-hour boundary hides in places nobody looks at:

  • Late human replies. A customer writes at 9 pm on Saturday, the shop opens on Monday, and the agent's reply fails.
  • Bot follow-ups that are scheduled too far out. A chatbot that waits 25 hours and then sends "Did you get a chance to look at the brochure?" as plain text will always fail.
  • Integrations that send plain text. Order, shipping or payment updates pushed from a store or CRM as a text message instead of a template work only for customers who happened to message recently.
  • The wrong timestamp. Code that measures the window from the last message in the thread, including your own outbound messages, thinks the window is open when it is not.
  • Coexistence numbers. On a number shared between the WhatsApp Business app and the Cloud API, messages the business sends from the phone app do not open a window for the API.

What the failure looks like

In practice the send request is often accepted with a message ID, and the failure arrives a moment later in the status webhook. The values below are illustrative:

{
  "statuses": [
    {
      "id": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgSQ0Y...",
      "status": "failed",
      "timestamp": "1761818400",
      "recipient_id": "919876543210",
      "errors": [
        {
          "code": 131047,
          "title": "Re-engagement message",
          "message": "Re-engagement message",
          "error_data": {
            "details": "More than 24 hours have passed since the recipient last replied to the sender number."
          }
        }
      ]
    }
  ]
}

Log the recipient_id, the code and the ID of the message you tried to send. When the same code appears for every message to one contact, it is the window. When it appears for a whole campaign of free-form messages, the campaign should have used a template.

How to fix it: resend as a template

Pick an approved template that says what you wanted to say and send it with type: template. Templates are sent through the same /messages endpoint; only the body of the request changes:

{
  "messaging_product": "whatsapp",
  "to": "919876543210",
  "type": "template",
  "template": {
    "name": "appointment_followup",
    "language": {
      "code": "en"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "Arjun"
          },
          {
            "type": "text",
            "text": "Thursday 6 Nov, 11:30 am"
          }
        ]
      }
    ]
  }
}

Template name and language code must match WhatsApp Manager exactly, and the number of parameters must match the variables, or you will swap 131047 for a template error such as 132001 or 132000. Our guide to sending a template message through the API walks through the components.

Which template to use depends on what the free-form message was for:

You wanted to sendUse a template likeLikely category
A late answer to a customer's question"Hi {{1}}, sorry for the delay. We have an answer to your question. Reply YES to see it."Utility, if it only refers to their request
An order, delivery or payment updateOrder update with order number and statusUtility
A follow-up nudge or offerMessage with a reason to reply and a quick-reply buttonMarketing
A login or verification codeAuthentication template with a copy-code buttonAuthentication

Meta decides the final category, and a "follow-up" that promotes something is marketing whatever you call it. See how template categories are decided.

A good re-engagement template invites a reply. A quick-reply button such as Yes, continue reopens the window the moment the customer taps it, and you can carry on with free-form messages from there.

A worked example

Priya runs the front desk at Sunrise Clinic in Pune. Arjun messages at 6:40 pm on Monday asking whether Dr Mehta has a slot this week. Priya sees it at 7:15 pm on Tuesday and types a normal reply. It fails with 131047, because 24 hours ended at 6:40 pm.

Instead she sends the clinic's approved appointment_followup template with Arjun's name and the suggested slot, plus two quick-reply buttons: Book this slot and Other times. Arjun taps Book this slot at 7:30 pm. A new window opens, and Priya confirms the booking in plain text, attaching the clinic's location pin.

Preventing 131047 in code

The cheapest fix is to never send the doomed request. Keep the time of the last inbound message for every contact (from the messages webhook, not from your own sends) and decide before you send:

const WINDOW_MS = 24 * 60 * 60 * 1000;
const SAFETY_MS = 2 * 60 * 1000; // do not cut it fine

function canSendFreeForm(lastInboundAt: Date | null, now = new Date()): boolean {
  if (!lastInboundAt) return false; // never messaged us: template only
  return now.getTime() - lastInboundAt.getTime() < WINDOW_MS - SAFETY_MS;
}

// if (!canSendFreeForm(contact.lastInboundAt)) sendTemplate(...) else sendText(...)

Two more habits help. Treat a 131047 response as a signal to queue the same intent as a template, not as a generic failure to retry; retrying free-form text will fail every time until the customer writes again. And schedule bot follow-ups to fire well inside the window, or switch them to a template step.

Cost of switching to a template

A failed 131047 message is not delivered, and Meta charges only for delivered messages. The template you send instead is charged by its category (marketing, utility or authentication). Replies inside an open window are service messages: since 1 Oct 2026 Meta gives each business number 1,000 free service messages a month and charges after that. Current rates are on our WhatsApp API pricing page.

How Broadchat shows this

In the Broadchat Inbox, each chat shows whether the 24-hour window is open, and you can filter chats by open or expired window. When it has expired, the reply box shows "24-hour reply window has expired. You can only send template messages to this contact." and free-form sending is blocked on the server, so agents pick a template instead of hitting 131047. If a message does fail, the reason appears under the message bubble, and Message info shows Meta's error code. Chatbot flows and integrations that send outside the window can still meet the error, so keep their follow-ups as templates.

For the full list of codes, see the WhatsApp API error codes cheat-sheet, and for the background, the plain-English guide to the WhatsApp Business API. Agencies can offer an inbox with these safeguards under their own brand through the white-label program.

Sources

  1. WhatsApp error codes — Meta for Developers, checked 30 October 2026
  2. Send service messages (customer service windows) — Meta for Developers, checked 30 October 2026
  3. Pricing on the WhatsApp Business Platform — Meta for Developers, checked 30 October 2026
  4. WhatsApp Business Platform changelog — Meta for Developers, checked 30 October 2026

Broadchat team · Product and partner success team

The people who build and support Broadchat, the white-label WhatsApp Business API platform. We write from what we see while onboarding partners and their clients on the official WhatsApp Cloud API, and we check every article against Meta's current documentation.

Last updated:

Frequently asked questions

What does WhatsApp error 131047 mean?

More than 24 hours have passed since the customer last messaged or called your business number, so the customer service window is closed and free-form messages are rejected. Send an approved message template instead.

Why is 131047 called "Re-engagement message"?

That is the title Meta's webhooks use for the code. It refers to re-engaging a customer after the window has closed, which you can only do with a template. Build your error handling on the number 131047 rather than the title, as Meta recommends.

Does my own message reset the 24-hour window?

No. Only an inbound message or call from the customer starts or resets the window. Messages, templates and receipts you send do not extend it.

Will retrying the same message fix 131047?

No. A free-form message will keep failing until the customer writes to you again. Send a template, ideally with a quick-reply button, and continue in free-form once they reply.

Am I charged for a message that fails with 131047?

Meta charges only for delivered messages, and a 131047 message is not delivered. The template you send in its place is charged according to its category.

See Broadchat on a real WhatsApp number

A short walkthrough of campaigns, chatbots, the team inbox and the partner panel, built around your use case.