WhatsApp Error 131047: 24-Hour Window Expired | ChatShree
Skip to content
Troubleshooting

WhatsApp error 131047: re-engagement message required

Quick answer

Error 131047 means you tried to send a free-form (session) message to a user whose 24-hour customer service window has already closed. Meta requires you to send an approved template first to re-open the conversation. It is not a bug โ€” it is Meta's core anti-spam rule. Fix it by detecting the window state before sending, defaulting to a utility template for re-engagement, and never letting your inbox agents type free-form after the window expires.

Disclaimer: WhatsApp session-window rules and pricing have shifted multiple times in 2025-2026. Cross-check current behaviour against Meta's official pricing and error docs.

The 131047 error in one sentence

Meta returned error 131047 because your business tried to send a non-template message to a user whose 24-hour customer service window has closed. The window closes exactly 24 hours after the user's last inbound message to you. After that, only pre-approved templates are allowed until the user replies again.

Why the 24-hour rule exists

WhatsApp is not an email inbox. Meta's foundational anti-spam rule is that businesses cannot start conversations with users on a whim โ€” every conversation must either be initiated by an approved template (which the user's phone treats as an interruption) or continued inside an active customer-service window (which the user opted into by messaging first).

131047 is the API-level enforcement of that rule. If your code doesn't respect the window, Meta's servers reject the message before it ever hits the user's device.

Session messages vs template messages

AspectSession (free-form)Template
When allowedInside 24-hour window onlyAny time
Approval requiredNoYes, per template
Media & interactiveFull supportLimited to approved variables
Cost modelSession/service pricing (paid from Oct 2026)Per-template category rate
Fails with 131047 when window closed?YesNo

How to detect window state programmatically

Every BSP tracks the last inbound message timestamp per contact. Before you send anything free-form, run this check:

const lastInboundAt = contact.lastInboundAt; // ISO timestamp
const now = Date.now();
const windowOpen = lastInboundAt &&
  (now - new Date(lastInboundAt).getTime()) < 24 * 60 * 60 * 1000;

if (windowOpen) {
  sendSessionMessage(contact.wa_id, text);
} else {
  sendTemplate(contact.wa_id, "re_engagement_utility", [...]);
}

If your BSP doesn't expose lastInboundAt, ask them โ€” every serious WhatsApp platform surfaces it. Without that field you're guessing.

Six fixes that eliminate 131047 in production

1. Add a window guard in your send layer

Every outbound-message code path should route through a single function that checks window state and picks between session and template. Never let application code call the free-form send API directly.

2. Create a re-engagement utility template

Get a utility-category template approved with copy like: "Hi {{1}}, we noticed your order #{{2}} needs your input. Reply YES to continue." This becomes your default outbound when the window is closed but a legitimate business reason exists.

3. Warn agents in the inbox UI

Human agents cause most 131047s. When an agent opens a conversation whose window has closed, the inbox should visibly gray out the message input, show "Window expired โ€” send a template to re-open", and present the approved re-engagement template as a one-click option. ChatShree's inbox does exactly this by default.

4. Buffer outbound during off-hours

If a user messages you at 11pm and your bot is scheduled to respond in a 9am batch, the window closes to 22 hours by the time you reply. If your batch runs at 11:05pm the next day, you'll get 131047 for every contact. Send acknowledgments in real time โ€” even a "We received your message" auto-reply โ€” to preserve the window.

5. Track window expiry as a first-class event

Fire an event 23 hours after the last inbound. In that hour, decide: do we have anything to say? If yes, send it as session. If not, let the window close naturally. Don't wait to be blocked at hour 24.5.

6. Retry with a template fallback

Your send wrapper should catch 131047, log it, and immediately retry as an approved template if one is configured for the flow. Do not surface the error to the end business user unless the retry also fails.

What 131047 does not mean

  • It does not mean the user blocked you.
  • It does not mean your number is banned.
  • It does not mean your template was rejected.
  • It does not mean the user's phone is off โ€” Meta doesn't attempt delivery at all.

If you're seeing 131047 alongside 131031 or 368 errors, the phone number itself is in trouble โ€” see our guides on error 131031 and error 368.

Pricing implications after October 2026

Historically, session messages inside the 24-hour window were free. From October 2026, Meta moved service (session) messages onto a paid model in most markets. That means every session message now has a cost, and the tradeoff between "send free session now" versus "wait and send paid template later" has shifted. Review our full breakdown at WhatsApp service messages are no longer free.

Daily monitoring checklist

  1. Pull all 131047 errors from the previous 24 hours.
  2. Group by source: bot, human agent, automation, webhook handler.
  3. For each source with more than 10 occurrences, audit whether the window check is present.
  4. Confirm your re-engagement utility template is still approved (templates can be paused).
  5. Check that "last inbound" timestamps in your CRM match the BSP's records โ€” drift here breaks the guard.

A note on template quality

If your re-engagement template starts pushing marketing content ("Also, check out our new offer!"), Meta may re-categorise it as marketing and trigger 131049 (per-user marketing cap) for many recipients. Keep utility templates strictly transactional.

How ChatShree prevents 131047

ChatShree tracks window state per contact in real time, blocks agents from sending session messages when the window is closed, and offers a one-click "send re-engagement template" action in the inbox. Bots and automations built inside our flow builder automatically insert a window check before every non-template send. In practice, teams that migrate to ChatShree see 131047 rates drop by more than 90% within the first week.

The takeaway

Error 131047 is not a Meta bug โ€” it is the load-bearing rule that keeps WhatsApp usable. The fix is architectural: every outbound send goes through a window check, and every conversation-closing event either triggers a re-engagement template or exits gracefully. Get that discipline right and 131047 becomes a metric you look at once a week, not a fire you fight every day.

Frequently asked questions

What triggers error 131047?

You sent a message with type 'text', 'image', 'document', 'interactive' or similar as a free-form send to a user who has not messaged you in the last 24 hours. Meta blocks all non-template messages outside that window and returns 131047.

How do I re-open the conversation?

Send a pre-approved template (utility, marketing or authentication category) to the user. Once they reply to any of your messages, a fresh 24-hour customer service window opens and you can send free-form messages again.

Does the 24-hour window reset every time the user messages me?

Yes. Every inbound message from the user starts a new 24-hour countdown from that message's timestamp. Multiple inbound messages don't extend the window past 24 hours from the latest one.

Is the customer service window free?

Meta's pricing has evolved through 2024-2026. Session messages inside the customer service window were free until October 2026, after which service messages moved to paid pricing. Check the WhatsApp Business Platform pricing page for the current model in your country.

Can I send a template inside an open window?

Yes. Templates work whether the window is open or closed. Templates always incur their per-message charge based on category (utility, marketing, authentication).

Why does my chatbot keep hitting 131047?

The bot is queuing outbound messages without checking window state. Add a window-state check before every outbound: if the last inbound is older than 24 hours, send a template; otherwise send free-form. Most BSPs expose a 'last inbound at' field on the contact record.

Sources