What Service Messages Are
Service messages are free-form messages sent through the Cloud API /messages endpoint. They are the counterpart to template messages: where templates are pre-approved formats sent in any window, service messages are composed on the fly and only sendable inside an open customer service window (CSW).
| Service messages | Template messages | |
|---|---|---|
| Pre-approval required? | No | Yes |
| When can you send? | Inside an open 24-hour CSW only | Any time, with a paid send if outside CSW |
| Composition | Free-form | Bound to approved template structure |
| Categories | Service (or free_customer_service for utility templates inside CSW) | MARKETING / UTILITY / AUTHENTICATION |
Pricing object category | service | marketing, utility, authentication, etc. |
Use service messages to respond conversationally inside an active customer interaction. To message a user outside any CSW, you must use marketing, utility, or authentication templates.
Service Pages in This Section
- Interactive Service Messages — CTA URL button, list, media carousel, reply buttons, location request
- Address Messages (India) — interactive form to collect a shipping address from Indian recipients
- Reaction Messages — emoji reactions on a previous user message
- Media Messages — image, video, audio, document, sticker
- Contacts & Location Messages — share contact cards or location coordinates
The Customer Service Window
When a WhatsApp user messages or calls you, a 24-hour timer (the customer service window or CSW) starts. While that window is open, you can send any service message type listed below. Each new inbound message or call from the user resets the timer to 24 hours.
When the window closes, you can only send pre-approved template messages.
You may only send messages to WhatsApp users who have opted in to receiving messages from you — the open window is a permission to respond, not a license to broadcast.
In rare cases, an inbound message from a user may not open the CSW for you to respond. This is a known platform-level edge case.
Message Types
The service-message types you can send during an open CSW:
| Type | What it is | Where documented |
|---|---|---|
text | Text body with optional link preview | Messaging Overview |
image | Single image with optional caption | Media Messages |
video | Video with optional caption | Media Messages |
audio | Voice message or basic audio | Media Messages |
document | File with download icon | Media Messages |
sticker | Static or animated WebP sticker | Media Messages |
location | Location coordinates | Contacts & Location |
contacts | Contact card with up to 257 contacts | Contacts & Location |
reaction | Emoji reaction on a previous user message | Reactions |
interactive (cta_url) | URL mapped to a button | Interactive Service Messages |
interactive (list) | List of options in a modal | Interactive Service Messages |
interactive (button) | Up to 3 reply buttons | Interactive Service Messages |
interactive (carousel) | Horizontally scrollable media cards | Interactive Service Messages |
interactive (location_request_message) | Send-location button | Interactive Service Messages |
interactive (address_message) | Address-collection form (India only) | Address Messages |
interactive (flow) | Structured Flow message | Meta WhatsApp Flows docs |
Core Endpoint
All service messages use the same endpoint:
POST https://graph.facebook.com/<GRAPH_VERSION>/<PHONE_NUMBER_ID>/messages
The body shape is consistent across types — the type field selects the message kind and the matching property carries the contents:
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "12015550123",
"type": "<MESSAGE_TYPE>",
"<MESSAGE_TYPE>": { /* contents */ }
}
recipient_type is individual for 1-to-1 messages or group for group messaging (see Meta's Groups API docs).
A successful response returns the WhatsApp message ID immediately, but does not confirm delivery — delivery status arrives asynchronously via a status webhook. For full status-lifecycle behavior, see Messaging Overview.
WhatsApp User Phone Number Formats
Plus signs (+), hyphens, parentheses, and spaces are all permitted in the to field. Strongly include both the + and country calling code — without them, your business phone number's own country code may be prepended, sending the message to the wrong recipient.
| Sent | Delivered to | Outcome (business in India, country code 91) |
|---|---|---|
+16315551234 | +16315551234 | Correct |
+1 (631) 555-1234 | +16315551234 | Correct |
(631) 555-1234 | +916315551234 | Wrong number — country code prepended |
1 (631) 555-1234 | +9116315551234 | Wrong number — country code prepended |
For Brazil and Mexico, Cloud API may modify the prefix automatically — this is by design, not a bug.
Contextual Replies
You can send a service message as a contextual reply to a specific previous message. WhatsApp displays it with a quote bubble pointing to the message you're replying to. Pass the original message's wamid in the context object on your send call:
{
"messaging_product": "whatsapp",
"to": "12015550123",
"context": { "message_id": "wamid.HBgLM..." },
"type": "text",
"text": { "body": "Yes, that order ships tomorrow." }
}
This makes it easier for the user to know which specific message you are replying to — useful in long, multi-thread conversations.
Media Caching (Hosted URLs)
When you send media via the link property (a URL on your public server) instead of id (an uploaded media asset), Cloud API fetches the asset and caches it for 10 minutes. Subsequent sends with the same URL within that window reuse the cached copy.
To bypass the cache (e.g. you re-uploaded under the same path), append a random query string:
First send: https://link.to.media/sample.jpg → fetched, cached 10 min
Second send: https://link.to.media/sample.jpg → cached copy reused
Third send: https://link.to.media/sample.jpg?abc123 → fetched, cached 10 min
This is also why Meta recommends id over link for production sends — uploaded media has a stable identifier and avoids the caching footgun entirely. See Media Messages → Send Media by Media ID.
Delivery Sequence of Multiple Messages
When sending a series of messages, delivery order is not guaranteed to match request order. If sequence matters (e.g. an intro message before a follow-up question), wait for the delivered status webhook on message N before sending message N+1.
For high-volume bursts where strict ordering doesn't matter (e.g. a list of independent updates), pipeline freely.
Time-To-Live (TTL) and Dropped Messages
If Cloud API can't deliver a message immediately (recipient offline, network issue), it retries for a default TTL window:
| Message kind | Default TTL |
|---|---|
| All service messages | 30 days |
| Authentication templates | 10 minutes |
| All other templates | 30 days |
You can customize TTL per template (utility, authentication, and marketing-via-MM-API only). See Meta's Time-to-live documentation for the full TTL parameter reference.
If you don't receive a delivered status webhook before the TTL elapses, assume the message was dropped. Failed sends emit a failed status webhook, but with a small possible delay — build a buffer before treating absence as failure.
Message Quality
Quality is computed from the last seven days of recipient feedback signals, weighted by recency: blocks, reports, mutes, archives, and the reasons users provide when blocking you.
To keep quality high:
- Follow the WhatsApp Business Messaging Policy.
- Only message users who have explicitly opted in.
- Make messages personalized and useful — avoid generic greetings.
- Don't send too many messages per day.
- Optimize content and length for the audience.
Per-number status, quality rating, and messaging limits are visible in WhatsApp Manager → Account tools → Phone numbers, and are also surfaced via Health Monitoring in Dualhook. High-traffic numbers can shift quality state within minutes — see Capacity, Quality & Limits for monitoring guidance.
Pricing
Service messages are billed under the service pricing category — but inside an open CSW most service messages are free because they're either non-template (always free in CSW) or utility templates (free in CSW). See Pricing → Free vs Billed Messages for the full matrix.
The status-webhook pricing.type will be free_customer_service for free sends and regular for billable ones — the Pricing Object in Status Webhooks section covers all combinations.