Skip to main content

24-Hour Messaging Window

WhatsApp Business API enforces a 24-hour customer service window that determines what types of messages you can send. Understanding this rule is essential for building reliable WhatsApp integrations.

How It Works

The 24-hour window opens when a customer sends you a message. During this window, you can send any message type freely. When the window closes, you can only send pre-approved template messages.

Customer sends a message
|
v
24-hour window OPENS
|
|-- You can send: text, media, interactive, reactions, etc.
|
24 hours later...
|
v
24-hour window CLOSES
|
|-- You can ONLY send: approved template messages

Rules at a Glance

Window StatusAllowed MessagesHow to Send
Open (customer messaged within 24h)All types: text, media, interactive, reactionsPOST /api/v1/messages
Closed (no customer message in 24h)Template messages onlyPOST /api/v1/whatsapp-templates/{id}/send

What Reopens the Window

The 24-hour window restarts (resets to a full 24 hours) every time a customer sends you a message. This includes:

  • Text messages
  • Media messages (images, documents, audio, video)
  • Button/list reply selections
  • Reactions
warning

Messages from your side (outbound) do not reopen the window. Only inbound messages from the customer reset the timer.

Handling the Window in Your Integration

Strategy 1: Respond to Inbound Messages

The simplest approach. When you receive a message.received webhook event, the window is guaranteed to be open:

# Webhook handler -- window is open
def handle_message_received(event):
conversation_id = event["data"]["conversation_id"]

# Safe to send any message type (reply to the existing conversation)
requests.post(
f"{BASE_URL}/messages",
headers=HEADERS,
json={
"conversation_id": conversation_id,
"text": "Thanks for reaching out! How can I help?",
"message_type": "text",
},
)
note

The text-message body field is text (a top-level string). There is no content wrapper — sending nested content is silently ignored.

Strategy 2: Use Templates for Outbound Initiation

When you need to reach out to a customer proactively (order updates, reminders, notifications), always use a template:

# Proactive outreach -- always use a template
def send_order_update(contact_id, order_id, delivery_date):
requests.post(
f"{BASE_URL}/whatsapp-templates/tpl_order_update/send",
headers=HEADERS,
json={
"contact_id": contact_id,
# Positional template: ordered list fills {{1}}, {{2}}, ...
# (For a NAMED template, pass a dict keyed by parameter name instead.)
"variable_values": [order_id, delivery_date],
},
)

Strategy 3: Graceful Fallback

Try sending a free-form message first. If it fails because the window is closed, fall back to a template:

def send_message_with_fallback(contact_id, channel_id, text, template_id, template_vars):
# Try free-form message first
response = requests.post(
f"{BASE_URL}/messages",
headers=HEADERS,
json={
"contact_id": contact_id,
"channel_id": channel_id,
"text": text,
"message_type": "text",
},
)

if response.status_code == 422:
# Window closed -- fall back to template
response = requests.post(
f"{BASE_URL}/whatsapp-templates/{template_id}/send",
headers=HEADERS,
json={
"contact_id": contact_id,
# template_vars: list (positional) or dict (named/numeric keys)
"variable_values": template_vars,
},
)

return response.json()
danger

Do not rely on the fallback strategy for time-sensitive notifications. If the window is closed, the initial request fails and you lose time on the retry. For proactive messaging, always start with a template.

Common Scenarios

ScenarioWindow StatusRecommended Approach
Customer asks a questionOpenReply with text, media, or interactive message
Customer taps a button replyOpen (refreshed)Continue the conversation freely
Sending order confirmationUnknownUse a template message
Following up after 2 daysClosedUse a template message
Sending a marketing promotionClosedUse a MARKETING template
Sending an OTP codeUnknownUse an AUTHENTICATION template

Error When Window Is Closed

If you attempt to send a non-template message outside the 24-hour window, you receive:

{
"detail": "24-hour messaging window has expired. Use a template message to re-engage.",
"error_code": "VALIDATION_ERROR"
}

Next Steps