Direct Send API
The Direct Send API lets you send business-initiated Utility messages, such as transactional and account updates, without an open conversation and without a pre-approved template. This makes it faster to send time-sensitive updates.
The Direct Send API is not yet available to all customers and is in beta for authentication messages. To take part, Meta must first verify that your WhatsApp Business Account (WABA) is eligible. If you are interested, ask your CM.com contact to get in touch with the WhatsApp product team.
Supported message types
| Message type | Description |
|---|---|
| Text | Plain text message. |
| CTA URL button | Message with a button that opens a URL. |
| Reply buttons | Message with quick-reply buttons. |
Sending a Direct Send message
Add "category": "utility" to the conversation item. This field is what marks a message as a Direct Send message, without it, the message is treated as a regular session message and is rejected outside the customer service window.
| Field | Required | Description |
|---|---|---|
richContent.conversation[].category | Yes | Must be utility. |
validity | No | Custom validity period. See Validity period. |
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "00316098765432",
"to": [
{ "number": "00316012345678" }
],
"body": {
"type": "auto",
"content": "Your order ORD-12345 has been shipped."
},
"allowedChannels": ["WhatsApp"],
"richContent": {
"conversation": [
{
"category": "utility",
"text": "Your order ORD-12345 has been shipped."
}
]
}
}
]
}
}
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "00316098765432",
"to": [
{ "number": "00316012345678" }
],
"body": {
"type": "auto",
"content": "Your order ORD-12345 has been shipped."
},
"allowedChannels": ["WhatsApp"],
"richContent": {
"conversation": [
{
"category": "utility",
"interactive": {
"type": "button",
"header": {
"type": "image",
"media": {
"mediaName": "CM.com - Be part of it.",
"mediaUri": "https://www.cm.com/cdn/web/blog/content/logo-cmcom.png",
"mimeType": "image/png"
}
},
"body": {
"text": "Your order ORD-12345 has been shipped."
},
"footer": {
"text": "CM.com"
},
"action": {
"buttons": [
{
"type": "openurl",
"id": "track-order",
"title": "Track order",
"url": "https://www.example.com/track/ORD-12345"
}
]
}
}
}
]
}
}
]
}
}
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "00316098765432",
"to": [
{ "number": "00316012345678" }
],
"body": {
"type": "auto",
"content": "Your delivery is scheduled for tomorrow."
},
"allowedChannels": ["WhatsApp"],
"richContent": {
"conversation": [
{
"category": "utility",
"interactive": {
"type": "button",
"body": {
"text": "Your delivery is scheduled for tomorrow. Does that suit you?"
},
"action": {
"buttons": [
{ "type": "reply", "reply": { "id": "delivery-ok", "title": "Yes" } },
{ "type": "reply", "reply": { "id": "delivery-reschedule", "title": "Reschedule" } }
]
}
}
}
]
}
}
]
}
}
Validity period
By default, Meta keeps trying to deliver a Direct Send message for 30 days. You can set a shorter validity period with the validity field of the message. Custom validity periods are only available for Direct Send messages (category is utility).
| Rule | Value |
|---|---|
| Minimum | 30 seconds from the time of sending. |
| Maximum | 12 hours (43,200 seconds) from the time of sending. |
| Default | 30 days, if validity is omitted or empty. |
For the format of validity, see Validity period.
If it is now 2026-04-21T12:00:00.0Z and the message must expire 6 hours from now, set validity to 2026-04-21T18:00:00.0Z.
{
"messages": {
"authentication": {
"productToken": "YOUR_PRODUCT_TOKEN"
},
"msg": [
{
"from": "00316098765432",
"to": [
{ "number": "00316012345678" }
],
"body": {
"type": "auto",
"content": "Your verification link expires in 6 hours."
},
"validity": "2026-04-21T18:00:00.0Z",
"allowedChannels": ["WhatsApp"],
"richContent": {
"conversation": [
{
"category": "utility",
"text": "Your verification link expires in 6 hours."
}
]
}
}
]
}
}
Validity errors and expiry
| Situation | Result |
|---|---|
validity is less than 30 seconds from now | Meta rejects the message. |
validity is more than 12 hours from now | Meta rejects the message. |
| Message not delivered within the validity period | Meta drops the message. It is permanently removed from the queue and is never delivered. |
Meta does not generate an error when it drops a message because the validity period has expired. This applies to both the default and a custom validity period. If you have not received a delivered status report when the validity period ends, assume the message was not delivered.