Skip to main content

Guides

The WhatsApp 24-hour window, explained properly

The WhatsApp Business API accepts a message sent outside the 24-hour window and returns 200. That 200 does not mean it arrived. Here is what happens next, and what it takes to actually reach someone who has not written to you yet.

By Komplian Team5 min read

There is an uncomfortable moment almost everyone hits the first time they automate WhatsApp: the dashboard says the message was sent, the API returned 200, there is a message id, and the customer swears nothing arrived.

It is not a bug in your integration. It is the 24-hour window, and it is worth understanding before you build anything on top of it.

What the 24-hour window actually is

WhatsApp separates two situations that look identical from a business point of view and are not identical to the platform:

  1. You are replying to someone. The contact wrote to you and you answer. WhatsApp calls this a service conversation and lets you send free-form text: whatever you like, however you like.
  2. You are starting the conversation. The contact has not written, or wrote a while ago. Here WhatsApp does not let you improvise.

The boundary between the two is a 24-hour window counted from the contact's last inbound message. Inside it, free text. Outside it, only a template Meta has approved in advance.

The word inbound matters: the window is not opened by your message, it is opened by theirs. And every message they send resets it.

The 200 that means nothing

Here is the trap that costs people whole afternoons.

When you send outside the window, Meta's API does not reject you. It answers 200, hands you a wamid, and everything looks fine. The message has been accepted, which is not the same as delivered.

The real verdict arrives afterwards, by webhook, as status updates:

sent  β†’  delivered  β†’  read

…or:

failed  β†’  131047  "Re-engagement message"

That 131047 is the platform telling you: I accepted your message, but more than 24 hours have passed since that person wrote to you, so I dropped it.

If your system treats the 200 as success, your dashboard will report 500 messages sent when 120 arrived. And you will not know, because nothing visibly failed.

The rule: a 200 from Meta means accepted for processing. The only status that means delivered is delivered, and it arrives later, by webhook. Any metric built on the 200 is inflated.

So how do you reach a cold contact

With an approved template. That is the only route.

A template is a message you register with Meta in advance, a reviewer approves, and which can contain variables ({{1}}, {{2}}…) you fill in at send time. Outside the 24-hour window an approved template gets through; nothing else does.

This has a design consequence people tend to discover late: any automation that writes to someone who has never written to you must use a template, always. A "new lead" flow that sends a free-text welcome is doomed by definition: a contact who has never written to you has opened no window.

The dynamic URL button trap

One specific case deserves a warning, because Meta's template editor will happily let you build it and then it cannot be sent.

If you register a template with a URL button and put a variable inside the address, something like https://yourdomain.com/order/{{1}}, that button is marked dynamic. From then on, every send is required to include a button component carrying that value. If your automation tool has no field to fill it in, Meta answers:

131008  Required parameter is missing

Every single time. The template is approved, it looks perfect in the editor, and it can never be sent.

Unless you control the send at a low level, the advice is simple: use static URL buttons. Put the variable in the message body, not inside the link.

The three rules, together

SituationWhat you can sendWhat happens if you get it wrong
Within 24 h of their last messageFree textNothing
Outside the windowApproved template only200, then 131047
Template with a dynamic URL buttonNothing, in practice131008 on every attempt

What your tooling should do about it

If you are evaluating a messaging platform or building your own, these are the questions that separate a serious integration from one that will bite you:

  • Does it know the window state before sending? Deciding afterwards is too late.
  • Does it skip the send and tell you why, rather than firing anyway and letting Meta drop it silently?
  • Does it store the real status that arrives by webhook, or does it keep the initial 200?
  • Does it catch an unsendable template, the dynamic button case, before trying?

The safest default is to mark a send that cannot arrive as skipped, with the reason recorded, rather than counting it as sent. A dashboard reporting green while messages are being dropped is worse than one reporting red: a red number gets investigated, while a green one lets a business lose customers for months without anyone noticing.

Summary

  • The 24-hour window is opened by the contact's message, not yours.
  • Outside it, only an approved template gets through.
  • A 200 is accepted, not delivered. The real status arrives by webhook.
  • 131047 = outside the window. 131008 = missing dynamic button parameter.
  • Any automation that makes first contact needs a template, no exceptions.

If your WhatsApp campaigns report perfect delivery and strange conversion, start here: you are very likely measuring acceptances, not deliveries.

Keep reading

All articles