Create UTILITY templates for transactional updates, invoices, reminders, appointments, orders, and service notifications.
Utility Template Creation
Summary
Create UTILITY templates for transactional updates, invoices, reminders, appointments, orders, and service notifications.
Prerequisites
- Authorization: Bearer w91_live_xxx
- Content-Type: application/json for JSON requests
Related documentation
Use UTILITY templates for account, order, invoice, appointment, ticket, and service updates. These templates should be transactional and tied to an existing customer action or relationship.
Create Utility Template API
Endpoint: POST /api/v2/templates.
| Header | Required | Description |
|---|---|---|
| Authorization | Yes | Use Authorization: Bearer w91_public_token_here. Compatibility body fields authToken, auth_token, or token are also accepted. |
| Content-Type | Yes | Use application/json for text and public media URL templates. Use multipart/form-data when uploading a local header media file as mediaFile. |
/api/v2/templates| Parameter | Type | Required | Description |
|---|---|---|---|
senderId | string | Optional | WhatsApp sender number. Number-scoped tokens can only create templates for the assigned sender. |
template.name | string | Required | Template name. Must be unique for the selected sender. |
template.category | string | Required | Must be UTILITY for this page. |
template.language | string | Required | Language code such as en. |
template.body.text | string | Required | Transactional template body using {{1}}, {{2}}, and later placeholders when needed. |
template.body.examples | array | Required | Example values for each body placeholder. |
template.header.mediaUrl | string | Optional | Public HTTPS URL for IMAGE, VIDEO, or DOCUMENT header media. |
mediaFile | file | Optional | Multipart local header media file. Required when using media headers without header.mediaUrl. |
template.buttons | array | Optional | Optional URL, PHONE_NUMBER, or QUICK_REPLY buttons for transactional actions. |
template.metadata | object | Optional | Local Whats91 metadata, not submitted to Meta. |
curl -X POST "https://graph.whats91.com/api/v2/templates" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"template": {
"name": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hello {{1}}, payment for invoice {{2}} is due on {{3}}.",
"examples": ["Devendar", "INV-1001", "31 March"]
},
"buttons": [
{
"type": "URL",
"text": "Pay now",
"url": "https://example.com/pay/{{1}}",
"example": "https://example.com/pay/INV-1001"
}
]
}
}'{
"success": true,
"message": "Template submitted to Meta",
"data": {
"templateUid": "0e6fb4f1-5a60-4d1d-8ef2-61a6ec8b7103",
"templateId": "w91_1780300000000_ab12cd34",
"templateName": "payment_reminder_v1",
"normalizedTemplateName": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"status": "PENDING",
"senderId": "916268662275",
"phoneNumberId": "1043189608869917",
"wabaId": "643703032991069",
"metaSubmission": {
"submitted": true,
"status": "PENDING"
}
},
"metadata": {
"apiVersion": "v2",
"requestId": "request-uuid",
"processingTimeMs": 320
}
}{
"success": false,
"message": "Header media is required for DOCUMENT template header",
"error_code": "MISSING_HEADER_MEDIA",
"details": {
"headerType": "DOCUMENT",
"acceptedInputs": ["mediaFile", "template.header.mediaUrl"]
},
"metadata": {
"apiVersion": "v2",
"requestId": "request-uuid"
}
}Required fields
| Field | Type | Notes |
|---|---|---|
| template.name | string | Unique template name for the selected sender. |
| template.category | string | Use UTILITY. Promotional language should move to MARKETING. |
| template.language | string | Supported Meta language code such as en. |
| template.body.text | string | Transactional message body. Variables require examples. |
| template.body.examples | array | Required when body text uses placeholders. |
Optional fields
| Field | Type | Notes |
|---|---|---|
| senderId | string | Explicit sender number for global or multi-number tokens. |
| template.header | object | TEXT, IMAGE, VIDEO, or DOCUMENT header. |
| header.mediaUrl | string | Public HTTPS media URL for IMAGE, VIDEO, or DOCUMENT headers. |
| mediaFile | file | Multipart local file alternative for media headers. |
| template.footer.text | string | Optional footer for operational context. |
| template.buttons | array | URL, PHONE_NUMBER, or QUICK_REPLY actions. |
| template.metadata | object | Internal reference values stored locally by Whats91. |
Practical Utility Examples
1. Payment reminder
{
"template": {
"name": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hello {{1}}, payment for invoice {{2}} is due on {{3}}.",
"examples": ["Devendar", "INV-1001", "31 March"]
}
}
}2. Invoice ready with PDF header
{
"template": {
"name": "invoice_ready_pdf",
"category": "UTILITY",
"language": "en",
"header": {
"type": "DOCUMENT",
"mediaUrl": "https://cdn.example.com/invoices/sample-invoice.pdf"
},
"body": {
"text": "Hi {{1}}, your invoice {{2}} is ready for download.",
"examples": ["Devendar", "INV-1001"]
},
"buttons": [
{
"type": "URL",
"text": "View invoice",
"url": "https://example.com/invoices/{{1}}",
"example": "https://example.com/invoices/INV-1001"
}
]
}
}3. Shipping update
{
"template": {
"name": "shipping_update",
"category": "UTILITY",
"language": "en",
"header": { "type": "TEXT", "text": "Shipping update" },
"body": {
"text": "Your package {{1}} is now {{2}}. Expected delivery: {{3}}.",
"examples": ["AWB-12345", "out for delivery", "today"]
},
"buttons": [
{
"type": "URL",
"text": "Track",
"url": "https://example.com/track/{{1}}",
"example": "https://example.com/track/AWB-12345"
}
]
}
}4. Appointment confirmation
{
"template": {
"name": "appointment_confirmation",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hi {{1}}, your appointment with {{2}} is confirmed for {{3}}.",
"examples": ["Devendar", "Whats91 Support", "10:30 AM"]
},
"buttons": [
{ "type": "QUICK_REPLY", "text": "Confirm" },
{ "type": "QUICK_REPLY", "text": "Reschedule" }
]
}
}5. Order status update
{
"template": {
"name": "order_status_update",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Order {{1}} has moved to {{2}}. We will notify you when the next update is available.",
"examples": ["ORD-1001", "packed"]
},
"footer": { "text": "Order updates from Whats91" }
}
}6. Service ticket update
{
"template": {
"name": "service_ticket_update",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Ticket {{1}} is now {{2}}. Assigned team: {{3}}.",
"examples": ["TKT-9001", "in progress", "Cloud API Support"]
},
"buttons": [
{ "type": "PHONE_NUMBER", "text": "Call support", "phone_number": "+919999999999" }
],
"metadata": {
"clientReferenceId": "service-template-001"
}
}
}SDK Examples
Use these examples as starting points for server-side implementations.
curl -X POST "https://graph.whats91.com/api/v2/templates" \
-H "Authorization: Bearer w91_live_xxx" \
-H "Content-Type: application/json" \
-d 'curl -X POST "https://graph.whats91.com/api/v2/templates" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"template": {
"name": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hello {{1}}, payment for invoice {{2}} is due on {{3}}.",
"examples": ["Devendar", "INV-1001", "31 March"]
},
"buttons": [
{
"type": "URL",
"text": "Pay now",
"url": "https://example.com/pay/{{1}}",
"example": "https://example.com/pay/INV-1001"
}
]
}
}''const response = await fetch("https://graph.whats91.com/api/v2/templates", {
method: "POST",
headers: {
"Authorization": "Bearer w91_live_xxx",
"Content-Type": "application/json"
},
body: JSON.stringify(curl -X POST "https://graph.whats91.com/api/v2/templates" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"template": {
"name": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hello {{1}}, payment for invoice {{2}} is due on {{3}}.",
"examples": ["Devendar", "INV-1001", "31 March"]
},
"buttons": [
{
"type": "URL",
"text": "Pay now",
"url": "https://example.com/pay/{{1}}",
"example": "https://example.com/pay/INV-1001"
}
]
}
}')
});
const data = await response.json();
console.log(data);$ch = curl_init("https://graph.whats91.com/api/v2/templates");
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(curl -X POST "https://graph.whats91.com/api/v2/templates" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"template": {
"name": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hello {{1}}, payment for invoice {{2}} is due on {{3}}.",
"examples": ["Devendar", "INV-1001", "31 March"]
},
"buttons": [
{
"type": "URL",
"text": "Pay now",
"url": "https://example.com/pay/{{1}}",
"example": "https://example.com/pay/INV-1001"
}
]
}
}')
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;import requests
response = requests.request(
"POST",
"https://graph.whats91.com/api/v2/templates",
headers={
"Authorization": "Bearer w91_live_xxx",
"Content-Type": "application/json",
},
json=curl -X POST "https://graph.whats91.com/api/v2/templates" \
-H "Authorization: Bearer w91_public_token_here" \
-H "Content-Type: application/json" \
-d '{
"senderId": "916268662275",
"template": {
"name": "payment_reminder_v1",
"category": "UTILITY",
"language": "en",
"body": {
"text": "Hello {{1}}, payment for invoice {{2}} is due on {{3}}.",
"examples": ["Devendar", "INV-1001", "31 March"]
},
"buttons": [
{
"type": "URL",
"text": "Pay now",
"url": "https://example.com/pay/{{1}}",
"example": "https://example.com/pay/INV-1001"
}
]
}
}'
)
print(response.json())using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer w91_live_xxx");
var request = new HttpRequestMessage(HttpMethod.Post, "https://graph.whats91.com/api/v2/templates");
request.Content = new StringContent(
"""curl -X POST \"https://graph.whats91.com/api/v2/templates\" \
-H \"Authorization: Bearer w91_public_token_here\" \
-H \"Content-Type: application/json\" \
-d '{
\"senderId\": \"916268662275\",
\"template\": {
\"name\": \"payment_reminder_v1\",
\"category\": \"UTILITY\",
\"language\": \"en\",
\"body\": {
\"text\": \"Hello {{1}}, payment for invoice {{2}} is due on {{3}}.\",
\"examples\": [\"Devendar\", \"INV-1001\", \"31 March\"]
},
\"buttons\": [
{
\"type\": \"URL\",
\"text\": \"Pay now\",
\"url\": \"https://example.com/pay/{{1}}\",
\"example\": \"https://example.com/pay/INV-1001\"
}
]
}
}'""",
Encoding.UTF8,
"application/json"
);
var response = await client.SendAsync(request);
Console.WriteLine(await response.Content.ReadAsStringAsync());Related APIs
Template
Create MARKETING templates for offers, promotions, launches, and customer engagement campaigns.
Authentication
Create AUTHENTICATION templates for OTP and verification code delivery using Meta copy-code buttons.
Template Send
Send approved WhatsApp templates with Whats91-specific fields, aliases, media headers, and button parameters.
Webhook
Create and manage Whats91 Webhooks v2 event destinations with the canonical public API route.