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 Status | Allowed Messages | How to Send |
|---|---|---|
| Open (customer messaged within 24h) | All types: text, media, interactive, reactions | POST /api/v1/messages |
| Closed (no customer message in 24h) | Template messages only | POST /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
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",
},
)
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()
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
| Scenario | Window Status | Recommended Approach |
|---|---|---|
| Customer asks a question | Open | Reply with text, media, or interactive message |
| Customer taps a button reply | Open (refreshed) | Continue the conversation freely |
| Sending order confirmation | Unknown | Use a template message |
| Following up after 2 days | Closed | Use a template message |
| Sending a marketing promotion | Closed | Use a MARKETING template |
| Sending an OTP code | Unknown | Use 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
- Send a Template Message -- sending templates with variables
- Understanding Templates -- template categories and structure
- Meta Template Library -- get an approved template in one call when the window has closed
- Getting Started with WhatsApp -- WhatsApp integration overview