On this page
Before you start
The WhatsApp Business API is governed by Meta. Your business, phone number and message templates must be approved by Meta before you can send messages. Make sure you have completed these steps:
- Create a SpringEdge WhatsApp account. Sign up or talk to us to get onboarded on the WhatsApp Business API.
- Verify your business on Meta. Your Meta Business Portfolio (Business Manager) should be verified to unlock higher messaging limits. Follow the Meta business verification guide.
- Register a phone number and display name. Use a number that is not active on the WhatsApp or WhatsApp Business app, and a display name that follows Meta's guidelines. See the phone number & display name requirements.
- Get your message templates approved. Business-initiated messages must use a template approved by Meta. See the template approval guidelines, or create templates with the template API.
- Collect customer opt-in. Only message customers who have agreed to receive WhatsApp messages from you. See the opt-in rules.
- Get your API credentials. After onboarding, SpringEdge shares your
<WHATSAPP_SERVICE_URL>and API key. Use the account details API to look up your phone number ID and WhatsApp Business Account (WABA) ID.
New to WhatsApp Business API? Read the WhatsApp Business API onboarding & Meta verification guide first. It covers business verification, policies, templates, quality rating and messaging limits.
Base URL & authentication
Every request in this documentation starts with <WHATSAPP_SERVICE_URL>. This is your account's WhatsApp service URL, shared with you after onboarding. Replace the placeholder with that URL, including https://.
Authenticate every request with your API key in the apikey header. Requests with a JSON body also need a Content-Type header:
| Header | Value |
|---|---|
apikey |
Your WhatsApp Business API key. |
Content-Type |
application/json for requests with a JSON body. |
Identifiers used in URLs
| Placeholder | Description |
|---|---|
{{phone_number_id}} |
ID of your WhatsApp business phone number. Used to send messages and manage media. |
{{waba_id}} |
ID of your WhatsApp Business Account. Used to create and manage templates. |
{{template_id}} |
ID of a message template, returned when the template is created. |
{{media_id}} |
ID of an uploaded media file, returned by the upload media API. |
Recipient numbers (to) must include the country code without + or leading zeros, e.g. 91XXXXXXXXXX for India.
Keep your API key secret. Call the API only from your server. Never call it from front-end code such as JavaScript, jQuery or HTML, where the key would be visible to anyone. Your API key can also be restricted to specific IP addresses. Ask support to enable this.
Session vs template messages
WhatsApp lets businesses send two kinds of messages:
- Session messages (text, media, location, contacts, interactive and commerce messages) can be sent only within 24 hours of the customer's last message to you. Each new message from the customer reopens this 24-hour customer service window.
- Template messages are pre-approved by Meta and can be sent at any time, including to start a conversation. Use them for notifications, OTPs, reminders and marketing.
So a conversation always starts in one of two ways: the customer messages you, or you send an approved template message. A session message sent to a customer who hasn't messaged you in the last 24 hours is not delivered. That's why this documentation covers template messages first, followed by session messages for replying once the customer responds.
HTTP status codes
| Status | Meaning |
|---|---|
200 OK |
The request was successful. |
201 Created |
The request was successful and a resource was created. |
204 No Content |
The request was successful but there is nothing to return. |
400 Bad Request |
The request could not be understood or is missing required parameters. |
401 Unauthorized |
Authentication failed, or the API key doesn't have permission for this operation. |
403 Forbidden |
Access denied. |
404 Not Found |
The resource was not found. |
405 Method Not Allowed |
The HTTP method is not supported for this resource. |
Send text template
Start here. Per Meta's rules, a conversation must be started either by the customer messaging you, or by you sending an approved template message. Free-form session messages (text, media, location and so on) sent to a customer who hasn't messaged you in the last 24 hours are not delivered. Send a template first, and switch to session messages once the customer replies.
Sends an approved template. name and language.code must exactly match the approved template, e.g. en or en_US. Pass one parameters entry for each variable ({{1}}, {{2}}, …) in the template body, in order.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
Sample request
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "order_confirmation",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Rahul" },
{ "type": "text", "text": "ORD-78542" }
]
}
]
}
}curl -X POST "<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages" \
-H "Content-Type: application/json" \
-H "apikey: YOUR_API_KEY" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "order_confirmation",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Rahul" },
{ "type": "text", "text": "ORD-78542" }
]
}
]
}
}'<?php
$payload = [
'messaging_product' => 'whatsapp',
'recipient_type' => 'individual',
'to' => '91XXXXXXXXXX',
'type' => 'template',
'template' => [
'name' => 'order_confirmation',
'language' => ['code' => 'en'],
'components' => [
[
'type' => 'body',
'parameters' => [
['type' => 'text', 'text' => 'Rahul'],
['type' => 'text', 'text' => 'ORD-78542'],
],
],
],
],
];
$ch = curl_init('<WHATSAPP_SERVICE_URL>/v3/PHONE_NUMBER_ID/messages');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'apikey: YOUR_API_KEY'],
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
echo $response['messages'][0]['id'];import requests
response = requests.post(
"<WHATSAPP_SERVICE_URL>/v3/PHONE_NUMBER_ID/messages",
headers={"apikey": "YOUR_API_KEY"},
json={
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "order_confirmation",
"language": {"code": "en"},
"components": [
{
"type": "body",
"parameters": [
{"type": "text", "text": "Rahul"},
{"type": "text", "text": "ORD-78542"},
],
}
],
},
},
timeout=30,
)
print(response.json())// Node.js 18+ (built-in fetch)
const response = await fetch('<WHATSAPP_SERVICE_URL>/v3/PHONE_NUMBER_ID/messages', {
method: 'POST',
headers: { 'Content-Type': 'application/json', apikey: 'YOUR_API_KEY' },
body: JSON.stringify({
messaging_product: 'whatsapp',
recipient_type: 'individual',
to: '91XXXXXXXXXX',
type: 'template',
template: {
name: 'order_confirmation',
language: { code: 'en' },
components: [
{
type: 'body',
parameters: [
{ type: 'text', text: 'Rahul' },
{ type: 'text', text: 'ORD-78542' },
],
},
],
},
}),
});
console.log(await response.json());Sample response
Every send-message endpoint on this page, template or session, returns this response. Store messages[0].id (the WhatsApp message ID, wamid) to match it with status webhooks.
{
"messaging_product": "whatsapp",
"contacts": [
{
"input": "91XXXXXXXXXX",
"wa_id": "91XXXXXXXXXX"
}
],
"messages": [
{
"id": "wamid.HBgMOTE3OTcyODkyNzEyFQIAERgSQUM3MzRCRjdFREYzOENDNTgw"
}
]
}
Send media template
For templates with an image, video or document header, pass the media in a header component, using link or an uploaded media id. Body parameters can also be localized currency and date_time values.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "template-name",
"language": { "code": "language-and-locale-code" },
"components": [
{
"type": "header",
"parameters": [
{
"type": "image",
"image": { "link": "https://example.com/images/header.jpg" }
}
]
},
{
"type": "body",
"parameters": [
{ "type": "text", "text": "text-string" },
{
"type": "currency",
"currency": {
"fallback_value": "$100.99",
"code": "USD",
"amount_1000": 100990
}
},
{
"type": "date_time",
"date_time": {
"fallback_value": "February 25, 1977",
"day_of_week": 5,
"year": 1977,
"month": 2,
"day_of_month": 25,
"hour": 15,
"minute": 33,
"calendar": "GREGORIAN"
}
}
]
}
]
}
}
For a video or document header, replace image with video or document in both type and the object name. Returns the standard send response.
Send call-to-action template (dynamic URL)
If a template's Visit website button has a dynamic URL such as https://www.website.com/{{1}}, pass the variable part in a button component. index is the button's position in the template, starting at 0.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "{{template_name}}",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "{{text_string}}" },
{ "type": "text", "text": "{{text_string}}" },
{ "type": "text", "text": "{{text_string}}" }
]
},
{
"type": "button",
"sub_type": "url",
"index": "1",
"parameters": [
{ "type": "text", "text": "<Developer defined dynamic URL suffix>" }
]
}
]
}
}
Returns the standard send response.
Send quick reply template
For templates with quick reply buttons, you can attach a payload to each button. It is returned to you in the incoming-message webhook when the customer taps that button.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "{{template_name}}",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "{{text_string}}" },
{ "type": "text", "text": "{{text_string}}" }
]
},
{
"type": "button",
"sub_type": "quick_reply",
"index": "0",
"parameters": [
{ "type": "payload", "payload": "CONFIRM_BOOKING_1024" }
]
},
{
"type": "button",
"sub_type": "quick_reply",
"index": "1",
"parameters": [
{ "type": "payload", "payload": "CANCEL_BOOKING_1024" }
]
}
]
}
}
Returns the standard send response.
Send coupon code template
For templates with a Copy code button, pass the coupon in a copy_code button component. The customer can copy it with one tap.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "copycode_07",
"language": { "code": "en_US" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "25OFF" },
{ "type": "text", "text": "25%" }
]
},
{
"type": "button",
"sub_type": "copy_code",
"index": 0,
"parameters": [
{ "type": "coupon_code", "coupon_code": "25OFF" }
]
}
]
}
}
Returns the standard send response.
Send multi-product (MPM) template
Sends an approved multi-product template that opens a selection of products from your catalogue. thumbnail_product_retailer_id sets the product image shown on the message.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "mpm_25nov1",
"language": { "code": "en_US" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "text", "text": "Pablo" }
]
},
{
"type": "body",
"parameters": []
},
{
"type": "button",
"sub_type": "mpm",
"index": 0,
"parameters": [
{
"type": "action",
"action": {
"thumbnail_product_retailer_id": "61",
"sections": [
{
"title": "Popular Bundles",
"product_items": [
{ "product_retailer_id": "61" },
{ "product_retailer_id": "63" }
]
},
{
"title": "Premium Packages",
"product_items": [
{ "product_retailer_id": "64" }
]
}
]
}
}
]
}
]
}
}
Returns the standard send response.
Send limited-time offer template
Limited-time offer templates show a countdown. Set the expiry in expiration_time_ms as a Unix timestamp in milliseconds. This example also passes a coupon code and a dynamic URL suffix.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "limited_time_offer_dec12",
"language": { "code": "en_US" },
"components": [
{
"type": "header",
"parameters": [
{ "type": "image", "image": { "id": "{{media_id}}" } }
]
},
{
"type": "body",
"parameters": []
},
{
"type": "limited_time_offer",
"parameters": [
{
"type": "limited_time_offer",
"limited_time_offer": { "expiration_time_ms": 1699400090000 }
}
]
},
{
"type": "button",
"sub_type": "copy_code",
"index": 0,
"parameters": [
{ "type": "coupon_code", "coupon_code": "CARIBE25" }
]
},
{
"type": "button",
"sub_type": "url",
"index": 1,
"parameters": [
{ "type": "text", "text": "n3mtql" }
]
}
]
}
}
Returns the standard send response.
Custom tracking data
Add biz_opaque_callback_data to any send request to attach your own reference, such as an order ID, campaign name or template ID. It isn't shown to the customer. It is returned unchanged in the sent, delivered and read status webhooks, so you can track each customer journey or compare the performance of different templates. Maximum 512 characters.
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "template",
"template": {
"name": "order_confirmation",
"language": { "code": "en" },
"components": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "Rahul" },
{ "type": "text", "text": "ORD-78542" }
]
}
]
},
"biz_opaque_callback_data": "{\"source\":\"api\",\"date\":\"2024-03-01\",\"uuid\":\"fuif-0deu-dgyu-5674\"}"
}
Send text message
Session messages only work within the 24-hour window. This and the following message types are delivered only if the customer has messaged you in the last 24 hours. To contact a customer first, send a template message.
Sends a plain text message. Set preview_url to true to show a preview of the first link in the message.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
Sample request
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "text",
"text": {
"preview_url": false,
"body": "Hello! Your order has been shipped."
}
}curl -X POST "<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages" \
-H "Content-Type: application/json" \
-H "apikey: YOUR_API_KEY" \
-d '{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "text",
"text": { "preview_url": false, "body": "Hello! Your order has been shipped." }
}'Returns the standard send response. For PHP, Python and Node.js, use the template samples with this JSON body.
Send image, document & video
Send media from a public HTTPS URL with link, or from a file you've uploaded with id. Set type to image, document or video and use the matching object.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
Sample request
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "image",
"image": {
"link": "https://example.com/images/offer.jpg",
"caption": "Our new collection is here!"
}
}{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "document",
"document": {
"link": "https://example.com/invoices/INV-1024.pdf",
"caption": "Your invoice for order #1024"
}
}{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "video",
"video": {
"link": "https://example.com/videos/product-demo.mp4",
"caption": "Watch how it works"
}
}{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "image",
"image": {
"id": "{{media_id}}",
"caption": "Our new collection is here!"
}
}Returns the standard send response.
Send location message
Sends a map pin with an optional name and address.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "location",
"location": {
"latitude": "12.9716",
"longitude": "77.5946",
"name": "Our Bengaluru Store",
"address": "MG Road, Bengaluru, Karnataka 560001"
}
}
Returns the standard send response.
Send contact message
Shares one or more contact cards. Only name.formatted_name is required. Include the other fields you need.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"to": "91XXXXXXXXXX",
"type": "contacts",
"contacts": [
{
"addresses": [
{
"street": "<ADDRESS_STREET>",
"city": "<ADDRESS_CITY>",
"state": "<ADDRESS_STATE>",
"zip": "<ADDRESS_ZIP>",
"country": "<ADDRESS_COUNTRY>",
"country_code": "<ADDRESS_COUNTRY_CODE>",
"type": "<HOME|WORK>"
}
],
"birthday": "<CONTACT_BIRTHDAY>",
"emails": [
{ "email": "<CONTACT_EMAIL>", "type": "<WORK|HOME>" }
],
"name": {
"formatted_name": "<CONTACT_FORMATTED_NAME>",
"first_name": "<CONTACT_FIRST_NAME>",
"last_name": "<CONTACT_LAST_NAME>",
"middle_name": "<CONTACT_MIDDLE_NAME>",
"suffix": "<CONTACT_SUFFIX>",
"prefix": "<CONTACT_PREFIX>"
},
"org": {
"company": "<CONTACT_ORG_COMPANY>",
"department": "<CONTACT_ORG_DEPARTMENT>",
"title": "<CONTACT_ORG_TITLE>"
},
"phones": [
{ "phone": "<CONTACT_PHONE>", "wa_id": "<CONTACT_WA_ID>", "type": "<HOME|WORK>" }
],
"urls": [
{ "url": "<CONTACT_URL>", "type": "<HOME|WORK>" }
]
}
]
}
Returns the standard send response.
Send interactive list message
Shows a button that opens a menu of options grouped into sections. When the customer picks a row, you receive its id in the incoming-message webhook.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "list",
"header": { "type": "text", "text": "Choose a plan" },
"body": { "text": "Pick the plan that suits you best." },
"footer": { "text": "FOOTER_TEXT" },
"action": {
"button": "View plans",
"sections": [
{
"title": "SECTION_1_TITLE",
"rows": [
{ "id": "SECTION_1_ROW_1_ID", "title": "SECTION_1_ROW_1_TITLE", "description": "SECTION_1_ROW_1_DESCRIPTION" },
{ "id": "SECTION_1_ROW_2_ID", "title": "SECTION_1_ROW_2_TITLE", "description": "SECTION_1_ROW_2_DESCRIPTION" }
]
},
{
"title": "SECTION_2_TITLE",
"rows": [
{ "id": "SECTION_2_ROW_1_ID", "title": "SECTION_2_ROW_1_TITLE", "description": "SECTION_2_ROW_1_DESCRIPTION" },
{ "id": "SECTION_2_ROW_2_ID", "title": "SECTION_2_ROW_2_TITLE", "description": "SECTION_2_ROW_2_DESCRIPTION" }
]
}
]
}
}
}
Returns the standard send response.
Send location request message
Shows a Send location button that asks the customer to share their current location.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "location_request_message",
"body": {
"text": "Let us start with your pickup. You can either manually *enter an address* or *share your current location*."
},
"action": {
"name": "send_location"
}
}
}
Returns the standard send response.
Send address message
Opens a form in WhatsApp that lets the customer fill in a delivery address. Address messages are currently supported in India (IN) and Singapore (SG).
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "address_message",
"body": {
"text": "Thanks for your order! Tell us what address you'd like this order delivered to."
},
"action": {
"name": "address_message",
"parameters": {
"country": "IN"
}
}
}
}
Address form fields
| Field | Display label | Input type | Countries | Limitations |
|---|---|---|---|---|
name |
Name | text | India, Singapore | — |
phone_number |
Phone Number | tel | India, Singapore | Valid phone numbers only |
in_pin_code |
Pin Code | text | India | Max length: 6 |
sg_post_code |
Post Code | number | Singapore | Max length: 6 |
house_number |
Flat/House Number | text | India | — |
floor_number |
Floor Number | text | India | — |
tower_number |
Tower Number | text | India | — |
building_name |
Building/Apartment Name | text | India | — |
address |
Address | text | India, Singapore | — |
landmark_area |
Landmark/Area | text | India | — |
unit_number |
Unit number | text | Singapore | — |
city |
City | text | India, Singapore | — |
state |
State | text | India | — |
Returns the standard send response.
Send single product message
Shows one product from your Meta commerce catalogue. Requires a catalogue connected to your WhatsApp Business Account.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "product",
"body": { "text": "text-body-content" },
"footer": { "text": "text-footer-content" },
"action": {
"catalog_id": "{{catalog_id}}",
"product_retailer_id": "{{retailer_id}}"
}
}
}
Returns the standard send response.
Send multi-product message
Shows several products from your catalogue, grouped into sections.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "product_list",
"header": { "type": "text", "text": "Our bestsellers" },
"body": { "text": "Browse this week's top picks." },
"footer": { "text": "Prices include GST" },
"action": {
"catalog_id": "{{catalog_id}}",
"sections": [
{
"title": "{{section_title}}",
"product_items": [
{ "product_retailer_id": "{{retailer_id}}" },
{ "product_retailer_id": "{{retailer_id}}" }
]
},
{
"title": "{{section_title}}",
"product_items": [
{ "product_retailer_id": "{{retailer_id}}" },
{ "product_retailer_id": "{{retailer_id}}" }
]
}
]
}
}
}
Returns the standard send response.
Send order details (payment)
Sends an order summary with a Review and pay button so the customer can pay inside WhatsApp through your connected payment gateway (razorpay or payu). Amounts are sent as value and offset, where the actual amount is value ÷ offset. For example, value: 100, offset: 100 is ₹1.00.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "order_details",
"header": {
"type": "image",
"image": { "link": "https://example.com/images/product.jpg" }
},
"body": { "text": "Test payment" },
"footer": { "text": "Thank you for shopping with us" },
"action": {
"name": "review_and_pay",
"parameters": {
"reference_id": "EZV2023032712042512044720",
"type": "digital-goods",
"currency": "INR",
"total_amount": { "value": 100, "offset": 100 },
"payment_settings": [
{
"type": "payment_gateway",
"payment_gateway": {
"type": "razorpay",
"configuration_name": "payment-config-id"
}
}
],
"order": {
"status": "pending",
"items": [
{
"retailer_id": "R1",
"product_id": "product-id",
"name": "Test Payment Rs. 1",
"amount": { "value": 100, "offset": 100 },
"quantity": 1
}
],
"subtotal": { "value": 100, "offset": 100 },
"tax": { "value": 0, "offset": 100 }
}
}
}
}
}
Returns the standard send response.
Send order status
Updates the customer on an order you sent earlier. Use the same reference_id. Set order.status to completed or canceled.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/messages
{
"messaging_product": "whatsapp",
"recipient_type": "individual",
"to": "91XXXXXXXXXX",
"type": "interactive",
"interactive": {
"type": "order_status",
"body": { "text": "Your payment could not be completed." },
"action": {
"name": "review_order",
"parameters": {
"reference_id": "EZV2023032712042512044720",
"order": {
"status": "canceled",
"description": "Payment failed"
}
}
}
}
}
Returns the standard send response.
Upload media
Uploads a file and returns a media ID you can use in messages instead of a public link. Send the file as multipart/form-data in a field named sheet.
<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/media
curl -X POST "<WHATSAPP_SERVICE_URL>/v3/{{phone_number_id}}/media" \
-H "apikey: YOUR_API_KEY" \
-F "sheet=@/path/to/file.jpg"
Sample response
{
"response": {
"id": "{{media_id}}"
}
}
Get & download media
Use these endpoints to fetch media files, for example images or documents your customers send you.
Download media directly
Returns the media file itself.
<WHATSAPP_SERVICE_URL>/v3/downloadMedia/{{media_id}}?phone_number_id={{phone_number_id}}
Get media URL
Returns a temporary URL and details for a media file.
<WHATSAPP_SERVICE_URL>/v3/{{media_id}}?phone_number_id={{phone_number_id}}
{
"url": "<WHATSAPP_SERVICE_URL>/v3/whatsapp_business/attachments/?mid=7609700182448254&ext=1716536800&hash=ATtFkAs7t1xlhx9wik43m7NBRARfMzfh6Vi_IvgzzxkQsQ",
"mime_type": "image/png",
"sha256": "ee490eac2a7b038413ab2fb0bfc6db02d9a68e015d92e917fbcee9e324a96810",
"file_size": 436484,
"id": "7609700182448254",
"messaging_product": "whatsapp"
}
Download from media URL
Call the url returned above with your apikey header to download the file.
<WHATSAPP_SERVICE_URL>/v3/whatsapp_business/attachments/?mid=...&ext=...&hash=...
Delete media
<WHATSAPP_SERVICE_URL>/v3/{{media_id}}?phone_number_id={{phone_number_id}}
{ "success": true }
Media file handle (for templates)
When you create a template with an image, video or document header, Meta needs a sample file, passed as a file handle in header_handle. Get one in two steps.
Step 1: Create an upload session
Pass the file size in bytes and its MIME type.
<WHATSAPP_SERVICE_URL>/v3/app/uploads?file_length=164313&file_type=video/mp4
{
"id": "upload:MTphdHRhY2htZW50OjNlYTE1ZTkzLTZkZDktNGIwOS1iOTM3...?sig=ARbUFIDlNcIbRnOalIY"
}
Step 2: Upload the file
Send the file as the raw binary request body to the session ID returned in step 1. The response contains the file handle h.
<WHATSAPP_SERVICE_URL>/v3/{{upload_session_id}}
curl -X POST "<WHATSAPP_SERVICE_URL>/v3/upload:MTphdHRhY2htZW50...?sig=ARbUFIDlNcIbRnOalIY" \
-H "apikey: YOUR_API_KEY" \
--data-binary "@/path/to/video.mp4"
{
"h": "4::dmlkZW8vbXA0:ARa3wu4QWKmzupRJa-dmysHBZrmo4TxDVwJgvvtbhvqMqPb-UC..."
}
Create template
Submits a new message template to Meta for approval. The response status can be APPROVED, PENDING or REJECTED. Read the template guidelines to avoid rejections.
<WHATSAPP_SERVICE_URL>/v3/{{waba_id}}/message_templates
Request fields
| Parameter | Required | Description |
|---|---|---|
name |
Yes | Template name: lowercase letters, numbers and underscores only. |
category |
Yes | MARKETING, UTILITY or AUTHENTICATION. |
language |
Yes | Language code, e.g. en_US, en or hi. |
components |
Yes | Array of HEADER, BODY, FOOTER and BUTTONS components. Only BODY is required. |
allow_category_change |
No | true lets Meta assign the correct category instead of rejecting the template. |
Components
| Component | Details |
|---|---|
HEADER |
format: TEXT, IMAGE, VIDEO or DOCUMENT. A text header can contain one variable, with a sample in example.header_text. Media headers need a sample file handle in example.header_handle. See media file handle. |
BODY |
Main message text. Variables are written {{1}}, {{2}}, … with sample values in example.body_text. |
FOOTER |
Short text shown below the body. |
BUTTONS |
Up to 10 buttons: QUICK_REPLY, URL (static or with one {{1}} at the end, with an example), PHONE_NUMBER and COPY_CODE. |
Sample requests
{
"name": "welcome_message_v1",
"category": "MARKETING",
"language": "en_US",
"allow_category_change": true,
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Welcome {{1}}",
"example": { "header_text": ["Rahul"] }
},
{
"type": "BODY",
"text": "Dear {{1}}, thank you for registering with {{2}} and providing consent to receive notifications on WhatsApp.\n\nPlease save this number. Reply HELP to get started or STOP to unsubscribe.",
"example": { "body_text": [["Rahul", "Company"]] }
},
{
"type": "FOOTER",
"text": "Welcome to Company"
},
{
"type": "BUTTONS",
"buttons": [
{ "type": "QUICK_REPLY", "text": "button1" },
{ "type": "QUICK_REPLY", "text": "button2" },
{ "type": "QUICK_REPLY", "text": "button3" }
]
}
]
}{
"name": "welcome_message_cta_v1",
"category": "MARKETING",
"language": "en_US",
"allow_category_change": true,
"components": [
{
"type": "HEADER",
"format": "TEXT",
"text": "Welcome {{1}}",
"example": { "header_text": ["Rahul"] }
},
{
"type": "BODY",
"text": "Thank you for registering with Company and providing consent to receive notifications on WhatsApp."
},
{
"type": "FOOTER",
"text": "Welcome to Company"
},
{
"type": "BUTTONS",
"buttons": [
{ "type": "PHONE_NUMBER", "text": "Call us", "phone_number": "+9199XXXXXXXX" },
{
"type": "URL",
"text": "Click",
"url": "https://www.website.com/{{1}}",
"example": ["dynamic-url-example"]
}
]
}
]
}{
"name": "sample_image_template_1",
"category": "MARKETING",
"language": "en_US",
"allow_category_change": true,
"components": [
{
"type": "HEADER",
"format": "IMAGE",
"example": {
"header_handle": ["4::aW1hZ2UvanBlZw==:ARZsON6K-8ukPIq2h95wJ9UUCr439vX2odOWPJ0TjP..."]
}
},
{
"type": "BODY",
"text": "Hey user,\nWelcome to the Company.\n\nRegards,\nCompany"
},
{
"type": "FOOTER",
"text": "Reply STOP to unsubscribe"
},
{
"type": "BUTTONS",
"buttons": [
{ "type": "QUICK_REPLY", "text": "Button1" },
{ "type": "QUICK_REPLY", "text": "Button2" },
{ "type": "QUICK_REPLY", "text": "Button3" },
{ "type": "URL", "text": "Visit", "url": "https://www.website.com/" },
{ "type": "PHONE_NUMBER", "text": "Call", "phone_number": "+9199XXXXXXXX" }
]
}
]
}For video or document headers, change format to VIDEO or DOCUMENT and upload a sample file of that type. For a dynamic URL button, use a URL ending in {{1}} with an example, as shown in the second sample.
Sample response
{
"id": "123412341234123",
"status": "APPROVED",
"category": "MARKETING"
}
Get templates
Get all templates
Returns every template on your WhatsApp Business Account with its status and components.
<WHATSAPP_SERVICE_URL>/v3/{{waba_id}}/message_templates
{
"data": [
{
"name": "ltotemp36013m103",
"components": [
{ "type": "BODY", "text": "Hey User, check out our Caribbean packages!" },
{
"type": "LIMITED_TIME_OFFER",
"limited_time_offer": { "text": "Expiring offer!", "has_expiration": true }
},
{
"type": "BUTTONS",
"buttons": [
{ "type": "COPY_CODE", "text": "Copy offer code", "example": ["CARIBE25"] },
{ "type": "URL", "text": "Click", "url": "https://www.website.com/{{1}}", "example": ["dynamic-url-example"] },
{ "type": "PHONE_NUMBER", "text": "call", "phone_number": "+9199XXXXXXXX" }
]
}
],
"language": "en_US",
"status": "APPROVED",
"category": "MARKETING",
"id": "2883983598406625"
}
]
}
Get template by ID
Returns a single template object, in the same format as one item of the list above.
<WHATSAPP_SERVICE_URL>/v3/{{template_id}}
Edit template
Updates a template's components or category. If a template was REJECTED, for example during category validation, you can edit its components, change its category, or create a new template.
<WHATSAPP_SERVICE_URL>/v3/{{template_id}}
{
"name": "image_v3_2",
"category": "MARKETING",
"language": "en_US",
"allow_category_change": true,
"components": [
{
"type": "header",
"format": "image",
"example": { "header_handle": ["4::aW1hZ2UvanBlZw==:ARaL3BstEF5_AxgQlJNl2Th3WNWDgRR..."] }
},
{ "type": "body", "text": "Hey user,\nWelcome to the Company.\n\nRegards,\nCompany" },
{ "type": "footer", "text": "Reply STOP to unsubscribe" },
{
"type": "buttons",
"buttons": [
{ "type": "quick_reply", "text": "Button1" },
{ "type": "quick_reply", "text": "Button2" },
{ "type": "url", "text": "click", "url": "https://www.website.com/" },
{ "type": "phone_number", "text": "Call", "phone_number": "+9199XXXXXXXX" }
]
}
]
}{ "category": "MARKETING" }Sample response
{ "success": true }
Delete template
Delete by name
Deletes every language version of the template with this name.
<WHATSAPP_SERVICE_URL>/v3/{{waba_id}}/message_templates?name={{template_name}}
Delete by name and ID
Deletes only the template with this ID.
<WHATSAPP_SERVICE_URL>/v3/{{waba_id}}/message_templates?hsm_id={{template_id}}&name={{template_name}}
Sample response
{ "success": true }
Get account details
Returns the WhatsApp numbers on your account with their WhatsApp Business Account ID ({{waba_id}}) and phone number ID ({{phone_number_id}}). Call this first to get the IDs used by the other endpoints.
<WHATSAPP_SERVICE_URL>/v3/getuserdetails
{
"code": 200,
"status": "SUCCESS",
"data": [
{
"wanumber": "+9199XXXXXXXX",
"whatsapp_business_account_id": "100249586351323",
"phone_number_id": "111266881902966"
},
{
"wanumber": "+9199XXXXXXXX",
"whatsapp_business_account_id": "100249586351323",
"phone_number_id": "112672835072002"
}
]
}
Status webhooks
To receive message status updates (sent, delivered, read, failed) and incoming customer messages on your server, share a publicly reachable HTTPS callback URL with SpringEdge support. Events are POSTed to it as JSON in Meta's webhook format. Match status updates to your messages using statuses[].id (the wamid returned when sending) or your custom tracking data.
Sample status webhook
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "112365665238904",
"changes": [
{
"value": {
"messaging_product": "whatsapp",
"metadata": {
"display_phone_number": "91XXXXXXXXXX",
"phone_number_id": "10XXXXXXXXXXXXXX"
},
"statuses": [
{
"id": "wamid.HBgMOTE3NTA3MDY2MzMxFQIAERgSQzZGNUVFOTgxMUUyMkI3MzVBAA==",
"status": "delivered",
"timestamp": "1709295133",
"recipient_id": "91XXXXXXXXXX",
"biz_opaque_callback_data": "{\"source\":\"api\",\"date\":\"2024-03-01\",\"uuid\":\"fuif-0deu-dgyu-5674\"}",
"conversation": {
"id": "a34a10abd87c7badad4d1fc5bafadd71",
"origin": { "type": "marketing" }
},
"pricing": {
"billable": true,
"pricing_model": "CBP",
"category": "marketing"
}
}
]
},
"field": "messages"
}
]
}
]
}
Help & support
Need your <WHATSAPP_SERVICE_URL>, a webhook set up, help with template approval or an integration? Email contact@springedge.com or contact us.
