Whats91
Developers

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

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.

HeaderRequiredDescription
AuthorizationYesUse Authorization: Bearer w91_public_token_here. Compatibility body fields authToken, auth_token, or token are also accepted.
Content-TypeYesUse application/json for text and public media URL templates. Use multipart/form-data when uploading a local header media file as mediaFile.
POST/api/v2/templates
ParameterTypeRequiredDescription
senderIdstringOptionalWhatsApp sender number. Number-scoped tokens can only create templates for the assigned sender.
template.namestringRequiredTemplate name. Must be unique for the selected sender.
template.categorystringRequiredMust be UTILITY for this page.
template.languagestringRequiredLanguage code such as en.
template.body.textstringRequiredTransactional template body using {{1}}, {{2}}, and later placeholders when needed.
template.body.examplesarrayRequiredExample values for each body placeholder.
template.header.mediaUrlstringOptionalPublic HTTPS URL for IMAGE, VIDEO, or DOCUMENT header media.
mediaFilefileOptionalMultipart local header media file. Required when using media headers without header.mediaUrl.
template.buttonsarrayOptionalOptional URL, PHONE_NUMBER, or QUICK_REPLY buttons for transactional actions.
template.metadataobjectOptionalLocal Whats91 metadata, not submitted to Meta.
Utility create request
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 Response
{
  "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
  }
}
Validation Error Response
{
  "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

FieldTypeNotes
template.namestringUnique template name for the selected sender.
template.categorystringUse UTILITY. Promotional language should move to MARKETING.
template.languagestringSupported Meta language code such as en.
template.body.textstringTransactional message body. Variables require examples.
template.body.examplesarrayRequired when body text uses placeholders.

Optional fields

FieldTypeNotes
senderIdstringExplicit sender number for global or multi-number tokens.
template.headerobjectTEXT, IMAGE, VIDEO, or DOCUMENT header.
header.mediaUrlstringPublic HTTPS media URL for IMAGE, VIDEO, or DOCUMENT headers.
mediaFilefileMultipart local file alternative for media headers.
template.footer.textstringOptional footer for operational context.
template.buttonsarrayURL, PHONE_NUMBER, or QUICK_REPLY actions.
template.metadataobjectInternal reference values stored locally by Whats91.

Practical Utility Examples

1. Payment reminder

Request body
{
  "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

Request body
{
  "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

Request body
{
  "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

Request body
{
  "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

Request body
{
  "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

Request body
{
  "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
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"
        }
      ]
    }
  }''
Node.js
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);
PHP
$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;
Python
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())
C#
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