Skip to content
Whats91

Send transactional utility messages through Direct Send with an optional time-to-live.

Utility Direct Send

Summary

Send transactional utility messages through Direct Send with an optional time-to-live.

Prerequisites

  • Authorization: Bearer w91_live_xxx
  • Content-Type: application/json for JSON requests

Set category to utility to opt a chat message into Direct Send. Meta matches or generates a utility template from the payload. Use it only for content that Meta allows in the utility category, such as order, delivery, appointment, and account updates.

Fields

FieldAliasesRules
categorydirectSendCategory, direct_send_categoryRequired to opt in. Exactly utility or authentication, lowercase.
ttlSecondsttl_secondsOptional integer. Utility range is 30 to 43200 seconds.
directSendTemplateNamedirect_send_template_nameOptional, utility only. Lowercase letters, digits, and underscores; maximum 512 characters.

Note

When both a camelCase field and its alias are present, the documented camelCase form wins. service is not a Direct Send value on the Whats91-style route; omit category to use the normal session-message path.

POST/api/v3/chat

Send a utility Direct Send message.

cURL
curl -X POST "https://graph.whats91.com/api/v3/chat" \
  -H "Authorization: Bearer w91_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "senderId": "919999999999",
    "to": "918888888888",
    "type": "text",
    "text": "Your order 12345 has shipped and should arrive tomorrow.",
    "category": "utility",
    "ttlSeconds": 3600
  }'
200 OK
{
  "success": true,
  "message": "Message accepted by Meta",
  "data": {
    "messageId": "wamid.xxxxx",
    "message_id": "wamid.xxxxx",
    "queued": false,
    "status": "accepted",
    "senderId": "919999999999",
    "phoneNumberId": "123456789012345",
    "receiverId": "918888888888",
    "messageType": "text",
    "templateName": null,
    "directSend": {
      "requested": true,
      "category": "utility",
      "ttlSeconds": 3600,
      "templateName": null
    }
  },
  "metadata": {
    "apiVersion": "v3",
    "requestId": "request-uid",
    "processingTimeMs": 120
  }
}

Note

If the sender is reconnecting, the queue response includes queued: true, queueUid, reportUid, and the same directSend object. The payload and category stay attached when the queue drains.

Business-Named Templates

Utility Direct Send can request a business-controlled template name. Meta restricts this capability separately. The name is unique within a WABA and does not fall back to onboarding templates if creation fails.

Business-named utility
curl -X POST "https://graph.whats91.com/api/v3/chat" \
  -H "Authorization: Bearer w91_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "918888888888",
    "type": "text",
    "text": "Invoice INV-2091 is ready for download.",
    "category": "utility",
    "directSendTemplateName": "invoice_ready"
  }'

Meta-Native Utility

On the Meta-compatible routes, use Meta field names verbatim: top-level category, top-level ttl_seconds, and direct_send_config.template_name for utility only.

Meta-native utility text
curl -X POST "https://graph.whats91.com/api/v3/123456789012345/messages" \
  -H "Authorization: Bearer w91_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "recipient_type": "individual",
    "to": "918888888888",
    "type": "text",
    "text": { "body": "Your appointment is confirmed for tomorrow at 10:30." },
    "category": "utility",
    "ttl_seconds": 1800
  }'
Meta-native utility interactive
curl -X POST "https://graph.whats91.com/api/v3/messages" \
  -H "Authorization: Bearer w91_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "918888888888",
    "type": "interactive",
    "interactive": {
      "type": "button",
      "body": { "text": "Your shipment is ready." },
      "action": {
        "buttons": [
          { "type": "cta_url", "text": "Track", "url": "https://example.com/track/12345" },
          { "type": "reply", "reply": { "id": "received", "title": "Received" } }
        ]
      }
    },
    "category": "utility"
  }'

Note

On Meta-compatible routes, service is a non-Direct-Send passthrough value. Utility image, video, and document headers pass through without a Whats91 gate, but Meta restricts media-header access during beta.

SDK Examples

Use these examples as starting points for server-side implementations.

cURL
curl -X POST "https://graph.whats91.com/api/v3/chat" \
  -H "Authorization: Bearer w91_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
  "senderId": "919999999999",
  "to": "918888888888",
  "type": "text",
  "text": "Your order 12345 has shipped and should arrive tomorrow.",
  "category": "utility",
  "ttlSeconds": 3600
}'
Node.js
const response = await fetch("https://graph.whats91.com/api/v3/chat", {
  method: "POST",
  headers: {
    "Authorization": "Bearer w91_live_xxx",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    "senderId": "919999999999",
    "to": "918888888888",
    "type": "text",
    "text": "Your order 12345 has shipped and should arrive tomorrow.",
    "category": "utility",
    "ttlSeconds": 3600
  })
});

const data = await response.json();
console.log(data);
PHP
$ch = curl_init("https://graph.whats91.com/api/v3/chat");
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    "Authorization: Bearer w91_live_xxx",
    "Content-Type: application/json"
  ],
  CURLOPT_POSTFIELDS => json_encode([
    "senderId" => "919999999999",
    "to" => "918888888888",
    "type" => "text",
    "text" => "Your order 12345 has shipped and should arrive tomorrow.",
    "category" => "utility",
    "ttlSeconds" => 3600
  ])
]);

$response = curl_exec($ch);
curl_close($ch);
echo $response;
Python
import requests

response = requests.request(
    "POST",
    "https://graph.whats91.com/api/v3/chat",
    headers={
        "Authorization": "Bearer w91_live_xxx",
        "Content-Type": "application/json",
    },
    json={
        "senderId": "919999999999",
        "to": "918888888888",
        "type": "text",
        "text": "Your order 12345 has shipped and should arrive tomorrow.",
        "category": "utility",
        "ttlSeconds": 3600
    }
)

print(response.json())
C#
using System.Text;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer w91_live_xxx");

var request = new HttpRequestMessage(HttpMethod.Post, "https://graph.whats91.com/api/v3/chat");
request.Content = new StringContent(
  """
  {
    "senderId": "919999999999",
    "to": "918888888888",
    "type": "text",
    "text": "Your order 12345 has shipped and should arrive tomorrow.",
    "category": "utility",
    "ttlSeconds": 3600
  }
  """,
  Encoding.UTF8,
  "application/json"
);

var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());