NAV
shell

Introduction

Welcome to the Service4U Whatsapp API! This documentation contains API for messaging using our Whatsapp API.

We have language bindings in Shell. You can view code examples in the dark area to the right.

Sending Free-Form Messages

You can use the API to send the following free-form messages types:

All of these message types, except for reaction messages, can be designated as a reply, which causes the delivered message to appear along with a contextual bubble displaying the content of the message that you are replying to.

Request Syntax

Use the POST WhatsApp Business Phone Number > Messages endpoint to send free-form messages to customers:

POST http://example.com/<WHATSAPP_BUSINESS_PHONE_NUMBER>/messages

Post body

{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "<TO>",
  "type": "<TYPE>",

  /* TEXT MESSAGES ONLY */
  "text": {<TEXT>}

  /* REACTION MESSAGES ONLY */
  "reaction": {<REACTION>}

  /* MEDIA MESSAGES ONLY. FOR EXAMPLE, FOR IMAGE MEDIA: */
  "image": {<IMAGE>}

  /* LOCATION MESSAGES ONLY */
  "location": {<LOCATION>}

  /* CONTACTS MESSAGES ONLY */
  "contacts": {<CONTACTS>}

  /* INTERACTIVE MESSAGES ONLY */
  "interactive": {<INTERACTIVE>}
}

All free-form send message requests use the following object format.

Properties

Placeholder Description Sample Value
<TO>

String

The WhatsApp ID or phone number of the customer to send the message to. See Phone Number Formats +16315551234
<TYPE>

String

Indicates message type. text
<TEXT>

Object

Text messages contents. See Text Messages.
<REACTION>

Object

Reaction message contents. See Reaction Messages.
<IMAGE>

Object

Media message contents. The property name should match the type of media message you are sending (image for an image message, video for a video message, etc.). See Media Messages.
<LOCATION>

Object

Location message contents. See Location Messages.
<CONTACTS>

Object

Contacts message contents. See Contacts Messages.
<INTERACTIVE>

Object

Interactive message contents. See Interactive Messages.

The examples throughout this document describe the post body payload requirements for each of the free-form message types.

Response Syntax

{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "<INPUT>",
      "wa_id": "<WA_ID>"
    }
  ],
  "messages": [
    {
      "id": "<ID>"
    }
  ]
}

Upon sucess the API will respond with:

Response Properties

Placeholder Description Sample Value
<INPUT>

String

The customer phone number that the message was sent to. This may not match wa_id. +16315551234
<WA_ID>

String

WhatsApp ID of the customer who the message was sent to. This may not match input. +16315551234
<ID>

String

WhatsApp message ID. You can use the ID listed after "wamid." to track your message status. wamid.HBgLMTY1MDM4Nzk0MzkVAgAR

GBI3N0EyQUJDMjFEQzZCQUMzODMA

Phone Number Formats

Plus signs (+), hyphens (-), parenthesis ((,)), and spaces are supported in send message requests.

We highly recommend that you include both the plus sign and country calling code when sending a message to a customer. If the plus sign is omitted, your business phone number's country calling code is prepended to the customer's phone number. This can result in undelivered or misdelivered messages.

For example, if your business is in India (country calling code 91) and you send a message to the following customer phone number in various formats:

Number In Send Message Request Number Message Delivered To Outcome
+16315551234 +16315551234 Correct number
+1 (631) 555-1234 +16315551234 Correct number
(631) 555-1234 +916315551234 Potentially wrong number
1 (631) 555-1234 +9116315551234 Potentially wrong number

Text Messages

Sample request:

curl -X  POST \
'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '
    {
      "messaging_product": "whatsapp",
      "recipient_type": "individual",
      "to": "PHONE_NUMBER",
      "type": "text",
      "text": { // the text object
        "preview_url": false,
        "body": "MESSAGE_CONTENT"
        }
    }'

If you would like to add preview URL, add the preview_url field:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "text",
  "text": { // the text object
    "preview_url": true,
    "body": "Message content including a URL begins with https:// or http://"
  }
}'

To send a text message, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=text. Then, add a text object.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Reaction Messages

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "reaction",
  "reaction": {
    "message_id": "wamid.HBgLM...",
    "emoji": "\uD83D\uDE00"
  }
}'

To send reaction messages, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=reaction. Then, add a reaction object.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

If the message you are reacting to is more than 30 days old, doesn't correspond to any message in the conversation, has been deleted, or is itself a reaction message, the reaction message will not be delivered and you will receive a webhook with the code 131009.

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Media Messages

Sample request using image with link:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM-PHONE-NUMBER-ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE-NUMBER",
  "type": "image",
  "image": {
    "link" : "https://IMAGE_URL"
  }
}'

Use the POST WhatsApp Business Phone Number > Messages endpoint to send a media message. Use the type property to indicate the media asset's type (audio, document, image, sticker, or video) and either the id or link property to indicate its ID (which you must generate) or location on your public server.

If using id, you must first upload your media asset to our servers and capture the returned media ID. If using link, your asset must be on a publicly accessible server or the message will fail to send.

Media assets can be cached. See Media HTTP Caching.

Sample request using media ID:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM-PHONE-NUMBER-ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE-NUMBER",
  "type": "image",
  "image": {
    "id" : "MEDIA-OBJECT-ID"
  }
}'

Example

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. If you are using a link to send the media, please check the callback events delivered to your Webhook server whether the media has been downloaded successfully.

Media HTTP Caching

Cache-Control: <CACHE_CONTROL>
Last-Modified: <LAST_MODIFIED>
ETag: <ETAG>

The Cloud API supports media HTTP caching. If you are using a link (link) to a media asset on your server (as opposed to the ID (id) of an asset you have uploaded to our servers), you can instruct us to cache your asset for reuse with future messages by including the headers below in your server response when we request the asset. If none of these headers are included, we will not cache your asset.

Cache-Control

The Cache-Control header tells us how to handle asset caching. We support the following directives:

Last-Modified

Indicates when the asset was last modified. Used with Cache-Control: no-cache. If the Last-Modified value is different from a previous response and Cache-Control: no-cache is included in the response, we will update our cached version of the asset with the asset in the response. Example: Date: Tue, 22 Feb 2022 22:22:22 GMT.

ETag

Sample Response with Headers

HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT
ETag: "33a64df5"
Cache-Control: max-age=604800

<IMAGE_PAYLOAD>

The ETag header is a unique string that identifies a specific version of an asset. Example: ETag: "33a64df5". This header is ignored unless both Cache-Control and Last-Modified headers are not included in the response. In this case, we will cache the asset according to our own, internal logic (which we do not disclose).

Location Messages

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "to": "PHONE_NUMBER",
  "type": "location",
  "location": {
    "longitude": LONG_NUMBER,
    "latitude": LAT_NUMBER,
    "name": LOCATION_NAME,
    "address": LOCATION_ADDRESS
  }
}'

To send location messages, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=location. Then, add a location object.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Contacts Messages

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "to": "PHONE_NUMBER",
  "type": "contacts",
  "contacts": [{
      "addresses": [{
          "street": "STREET",
          "city": "CITY",
          "state": "STATE",
          "zip": "ZIP",
          "country": "COUNTRY",
          "country_code": "COUNTRY_CODE",
          "type": "HOME"
        },
        {
          "street": "STREET",
          "city": "CITY",
          "state": "STATE",
          "zip": "ZIP",
          "country": "COUNTRY",
          "country_code": "COUNTRY_CODE",
          "type": "WORK"
        }],
      "birthday": "YEAR_MONTH_DAY",
      "emails": [{
          "email": "EMAIL",
          "type": "WORK"
        },
        {
          "email": "EMAIL",
          "type": "HOME"
        }],
      "name": {
        "formatted_name": "NAME",
        "first_name": "FIRST_NAME",
        "last_name": "LAST_NAME",
        "middle_name": "MIDDLE_NAME",
        "suffix": "SUFFIX",
        "prefix": "PREFIX"
      },
      "org": {
        "company": "COMPANY",
        "department": "DEPARTMENT",
        "title": "TITLE"
      },
      "phones": [{
          "phone": "PHONE_NUMBER",
          "type": "HOME"
        },
        {
          "phone": "PHONE_NUMBER",
          "type": "WORK",
          "wa_id": "PHONE_OR_WA_ID"
        }],
      "urls": [{
          "url": "URL",
          "type": "WORK"
        },
        {
          "url": "URL",
          "type": "HOME"
        }]
    }]
}'

To send contacts messages, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=contact. Then, add a contacts object.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Interactive Messages

List Messages sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "interactive",
  "interactive": {
    "type": "list",
    "header": {
      "type": "text",
      "text": "HEADER_TEXT"
    },
    "body": {
      "text": "BODY_TEXT"
    },
    "footer": {
      "text": "FOOTER_TEXT"
    },
    "action": {
      "button": "BUTTON_TEXT",
      "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"
            }
          ]
        }
      ]
    }
  }
}'

Reply Button sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "interactive",
  "interactive": {
    "type": "button",
    "body": {
      "text": "BUTTON_TEXT"
    },
    "action": {
      "buttons": [
        {
          "type": "reply",
          "reply": {
            "id": "UNIQUE_BUTTON_ID_1",
            "title": "BUTTON_TITLE_1"
          }
        },
        {
          "type": "reply",
          "reply": {
            "id": "UNIQUE_BUTTON_ID_2",
            "title": "BUTTON_TITLE_2"
          }
        }
      ]
    }
  }
}'

Interactive messages include List Messages and Reply Buttons. To send interactive messages, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=interactive. Then, add an interactive object.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Replies

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: ACCESS_TOKEN' \
 -d '{
   "messaging_product": "whatsapp",
   "context": {
     "message_id": "MESSAGE_ID"
   },
   "to": "<phone number> or <wa_id>",
   "type": "text",
   "text": {
     "preview_url": False,
     "body": "your-text-message-content"
   }
 }'

You can send any message as a reply to a previous message in a conversation by including the previous message's ID in the context object. The recipient will receive the new message along with a contextual bubble that displays the previous message's content.

Sample response:

{
  "messaging_product": "whatsapp",
  "contacts": [{
    "input": "PHONE_NUMBER",
    "wa_id": "WHATSAPP_ID",
  }]
  "messages": [{
    "id": "wamid.ID",
  }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Note: if the previous message is more than 30 days old or doesn't correspond to any message in the conversation, the message will be sent normally instead of as a reply.

Address Messages

Address messages give your users a simpler way to share the shipping address with the business on WhatsApp.

Address messages are interactive messages that contain the 4 main parts: header, body, footer, and action. Inside the action component business specifies the name “address_message” and relevant parameters.

Currently address messages are supported in the following two countries: India and Singapore. Below table outlines which fields are supported in which country specifically.

Field Name Display Label Input Type Supported Countries Limitations
name Name text India, Singapore None
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 None
floor_number Floor Number text India None
tower_number Tower Number text India None
building_name Building/Apartment Name text India None
address Address text India, Singapore None
landmark_area Landmark/Area text India None
unit_number Unit number text Singapore None
city City text India, Singapore None
state State text India None

Sample API call

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
          "messaging_product": "whatsapp",
          "recipient_type": "individual",
          "to": "PHONE_NUMBER",
          "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" :"COUNTRY_ISO_CODE"
                   }
              }
          }
    }'

This is a sample API call for the address message. The country attribute is a mandatory field in the action parameters. If it is not included, there will be a validation error.

Error Handling

If the area code of the phone number for the given country is not correct, businesses will be unable to request the address message from the recipient. For example, businesses will be unable to request an address message from a recipient that has the country as “Singapore” but has a phone number with an area code of "91".

Address messages will not allow simultaneous passing of conflicting fields. For example, you cannot pass in sg_post_code when country is set to “IN”.

Once the address message is sent, the business waits for the user to fill in the address and send it back. The user entered address is shared through the webhook registered in the setup process.

Address Message Steps

The steps involved in an Address Message are the following:

  1. Business sends an address message with the action name address_message to the user
  2. User interacts with the message by clicking on the CTA, which brings up an Address Message screen. The user fills out their address and submits the form
  3. After the address message form is submitted by the user, the partner receives a webhook notification, which contains the details of the address submitted by the user

Sample India Address Message

Sample Singapore Address Message

The following sequence diagram shows a typical integration flow for an address message.

Additional Action parameters

The business can pass additional attributes such as values, validation_errors, or saved_addresses as part of the interactive action parameters. You can find information on each of their usage below.

Action Parameter Usage
values Businesses prefill this for address fields (eg. prefilling the city address field with “Singapore”)
saved_addresses For businesses, they can pass in saved addresses previously associated with the user. For users, they are presented with the option to choose the saved address instead of manually filling it in
validation_errors Businesses can throw errors in the address fields and WhatsApp will prevent the user from submitting the address until the issue(s) are/is resolved.

Send Address Message to a user

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d ' {
            "messaging_product": "whatsapp",
            "recipient_type": "individual",
            "to": "PHONE_NUMBER",
            "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": "JSON Payload"
                 }
            }
     }'

Make a POST call to /PHONE_NUMBER_ID/messages using the WhatsApp API to send an end-to-end encrypted address message to the user:

India

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
      "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",
              "values": {
                 "name": "CUSTOMER_NAME",
                 "phone_number": "+91xxxxxxxxxx"
              }
           }
        }
      }
   }'

Singapore

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
      "messaging_product": "whatsapp",
      "recipient_type": "individual",
      "to": "+65xxxxxxxxxx",
      "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": "SG",
              "values": {
                  "name": "CUSTOMER_NAME",
                  "phone_number": "+65xxxxxxxxxx"
              }
           }
        }
      }
   }'

To send an address message without any saved addresses, WhatsApp will prompt the user or business with an address form to enter a new address.

India

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d 
'{
  "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",
          "saved_addresses": [
             {
                 "id": "address1",
                 "value": {
                    "name": "CUSTOMER_NAME",
                    "phone_number": "+91xxxxxxxxxx",
                    "in_pin_code": "400063",
                    "floor_number": "8",
                    "building_name": "",
                    "address": "Wing A, Cello Triumph,IB Patel Rd",
                    "landmark_area": "Goregaon",
                    "city": "Mumbai"
                 }
             }
          ]
       }
    }
  }
}'

Singapore

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d 
'{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "+65xxxxxxxxxx",
  "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": "SG",
         "values": {
             "name": "CUSTOMER_NAME",
             "phone_number": "+65xxxxxxxxxx"
         },
         "saved_addresses": [
            {
                "id": "address1",
                "value": {
                   "name": "CUSTOMER_NAME",
                   "phone_number": "+65xxxxxxxxxx",
                   "sg_post_code": "018937",
                   "address": "9 Straits View, Marina One West Tower",
                   "unit_number": "Suite 29-00",
                   "city": "Singapore"
                }
            }
         ]
      }
    }
  }
}'

To send an address message with saved addresses, WhatsApp will prompt the user or business with an option to select among the saved addresses or add an address option. Users can ignore the saved address and enter a new address.

Check Your Response

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes a messages object with an ID for the newly created message.

An unsuccessful response contains an error message.

Send an Address Message with Validation Errors

India

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d 
'{
  "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",
          "values": {
             "name": "CUSTOMER_NAME",
             "phone_number": "+91xxxxxxxxxx",
             "in_pin_code": "666666",
             "address": "Some other location",
             "city": "Delhi"
          },
          "validation_errors": {
             "in_pin_code": "We could not locate this pin code."
          }
       }
    }
  }
}'

Singapore

curl -X  POST \
'https://graph.facebook.com/v15.0/FROM_PHONE_NUMBER_ID/messages' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d 
'{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "12065550107",
  "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": "SG",
           "values": {
              "name": "CUSTOMER_NAME",
              "phone_number": "+65xxxxxxxxxx",
              "sg_post_code": "666666",
              "address": "Some other location",
              "city": "Singapore"
           },
           "validation_errors": {
              "sg_post_code": "We could not locate this pin code."
           }
        }
     }
  }
}'

An address message should be re-sent to the user in the case of a validation error on the business server. The business should send back the set of values previously entered by the user, along with the respective validation errors for each invalid field, as shown in the sample payloads on the right side.

Receive Notifications for Address Submissions

{
    "messages": [
        {
           "id": "gBGGFlAwCWFvAgmrzrKijase8yA",
           "from": "PHONE_NUMBER",
           "Interactive": {
               "type":  "nfm_reply",
               "action":  "address_message",
               "nfm_reply": {
                   "name": "address_message",
                    "response_json": “<response_json from client>”,
                    "body": “<body text from client>”,
            }
           "timestamp": "1670394125",
           "type": "interactive"  
        }
    ]
}

Businesses will receive address submission notifications through webhooks, such as the one shown on the right side.

The webhook notification has the following values.

Field Name Type Description
interactive Object Holds the response from the client
type String Would be nfm_reply indicating it is a Native Flow Response (NFM) from the client
nfm_reply Object Holds the data received from the client
response_json String The values of the address fields filled by the user in JSON format that are always present
body (Optional) String Body text from client, what the user sees
name (Optional) String Would be address_message indicating the type of NFM action response from the client
{
   "messages": [
      {
          "context": {
      "from": "FROM_PHONE_NUMBER_ID",
      "id": "wamid.HBgLMTIwNjU1NTAxMDcVAgARGBI3NjNFN0U5QzMzNDlCQjY0M0QA"
           },
          "from": "PHONE_NUMBER",
         "id": "wamid.HBgLMTIwNjU1NTAxMDcVAgASGCA5RDhBNENEMEQ3RENEOEEzMEI0RUExRDczN0I1NThFQwA=",
         "timestamp": "1671498855",
         "type": "interactive",
         "interactive": {
     "type": "nfm_reply",
    "nfm_reply": {
          "response_json": "{\"saved_address_id\":\"address1\",\"values\":{\"in_pin_code\":\"400063\",\"building_name\":\"\",\"landmark_area\":\"Goregaon\",\"address\":\"Wing A, Cello Triumph, IB Patel Rd\",\"city\":\"Mumbai\",\"name\":\"CUSTOMER_NAME\",\"phone_number\":\"+91xxxxxxxxxx\",\"floor_number\":\"8\"}}",
                    "body": "CUSTOMER_NAME\n +91xxxxxxxxxx\n 400063, Goregaon, Wing A, Cello Triumph,IB Patel Rd, Mumbai, 8",
                    "name": "address_message"
                }
            }
        }
    ]
}

An address message reply as an NFM response type for an India address message request is show on the right side.

Feature Not Supported

{
  "statuses": [
    {
      "errors": [
        {
          "code": 1026,
          "href": "https://developers.facebook.com/docs/whatsapp/api/errors/",
          "title": "Receiver Incapable"
        }
      ],
      "id": "gBGGFlAwCWFvAgkyHMGKnRu4JeA",
      "message": {
        "recipient_id": "+91xxxxxxxxxx"
      },
      "recipient_id": "91xxxxxxxxxx",
      "status": "failed",
      "timestamp": "1670394125",
      "type": "message"
    }
  ]
}

In the case where the client does not support address_message, messages are silently dropped and an error message is sent back to the business in a webhook. The webhook notification that would be sent back is shown on the right side:

Delivery Sequence of Multiple Messages

When sending a series of messages, the order in which messages are delivered is not guaranteed to match the order of your API requests. If you need to ensure the sequence of message delivery, confirm receipt of a delivered status in a messages webhook before sending the next message in your message sequence.

Sending Template Messages

WhatsApp message templates are specific message formats that businesses use to send out notifications or customer care messages to people that have opted in to notifications. Messages can include appointment reminders, shipping information, issue resolution or payment updates.

Before sending a template message, you need to create a template. If your account is not verified yet, you can use one of our pre-approved templates.

Currently, you can send the following template types:

All API calls mentioned in this guide must be authenticated with an access token. Developers can authenticate their API calls with the access token generated in the App Dashboard > WhatsApp > API Setup panel. Business Solution Providers (BSPs) must authenticate themselves with an access token with the whatsapp_business_messaging permission.

Pacing

Newly created or unpaused marketing templates are subject to template pacing. See [Template Pacing.]

Text-Based Message Templates

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "template",
  "template": {
    "name": "TEMPLATE_NAME",
    "language": {
      "code": "LANGUAGE_AND_LOCALE_CODE"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "text-string"
          },
          {
            "type": "currency",
            "currency": {
              "fallback_value": "VALUE",
              "code": "USD",
              "amount_1000": NUMBER
            }
          },
          {
            "type": "date_time",
            "date_time": {
              "fallback_value": "DATE"
            }
          }
        ]
      }
    ]
  }
}'

To send a text-based message template, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=template. Then, add a template object.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Media-Based Message Templates

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "template",
  "template": {
    "name": "TEMPLATE_NAME",
    "language": {
      "code": "LANGUAGE_AND_LOCALE_CODE"
    },
    "components": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "image",
            "image": {
              "link": "https://URL"
            }
          }
        ]
      },
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "TEXT-STRING"
          },
          {
            "type": "currency",
            "currency": {
              "fallback_value": "VALUE",
              "code": "USD",
              "amount_1000": NUMBER
            }
          },
          {
            "type": "date_time",
            "date_time": {
              "fallback_value": "MONTH DAY, YEAR"
            }
          }
        ]
      }
    ]
  }
}'

To send a media-based message template, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=template. Then, add a template object. Supports Media HTTP Caching.

Use the POST WhatsApp Business Phone Number > Messages endpoint to send a media-based template message. Set the type property to template and use the template property to define your template object and its media object.

When defining your media object, you can either upload your media asset to our servers and use its media ID (using the id property), or host the asset on your server and use its URL (using the link property). If using link, your asset must be on a publicly accessible server or the message will fail to send.

Media assets can be cached. See Media HTTP Caching.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Interactive Message Templates

Sample request:

curl -X  POST \
 'https://graph.facebook.com/v17.0/FROM_PHONE_NUMBER_ID/messages' \
 -H 'Authorization: Bearer ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -d '{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "template",
  "template": {
    "name": "TEMPLATE_NAME",
    "language": {
      "code": "LANGUAGE_AND_LOCALE_CODE"
    },
    "components": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "image",
            "image": {
              "link": "http(s)://URL"
            }
          }
        ]
      },
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "TEXT_STRING"
          },
          {
            "type": "currency",
            "currency": {
              "fallback_value": "VALUE",
              "code": "USD",
              "amount_1000": NUMBER
            }
          },
          {
            "type": "date_time",
            "date_time": {
              "fallback_value": "MONTH DAY, YEAR"
            }
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "quick_reply",
        "index": "0",
        "parameters": [
          {
            "type": "payload",
            "payload": "PAYLOAD"
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "quick_reply",
        "index": "1",
        "parameters": [
          {
            "type": "payload",
            "payload": "PAYLOAD"
          }
        ]
      }
    ]
  }
}'

Interactive message templates expand the content you can send recipients beyond the standard message template and media messages template types to include interactive buttons using the components object. There are two types of predefined buttons:

These buttons can be attached to text messages or media messages. Once your interactive message templates have been created and approved, you can use them in notification messages as well as customer service/care messages.

To send an interactive message template, make a POST call to /PHONE_NUMBER_ID/messages and attach a message object with type=template. Then, add a template object with your chosen button.

Example:

{
  "messaging_product": "whatsapp",
  "contacts": [{
      "input": "PHONE_NUMBER",
      "wa_id": "WHATSAPP_ID",
    }]
  "messages": [{
      "id": "wamid.ID",
    }]
}

A successful response includes an object with an identifier prefixed with wamid. Use the ID listed after wamid to track your message status.

Location-based Message Templates

To send a template that uses a location header your request must include a location header object.

Syntax

{
  "type": "header",
  "parameters": [
    {
      "type": "location",
      "location": {
        "latitude": "<LATITUDE>",
        "longitude": "<LONGITUDE>",
        "name": "<NAME>",
        "address": "<ADDRESS>"
      }
    }
  ]
}

Properties

Placeholder Description Sample Value
<ADDRESS< Address that will appear after the <NAME< value, below the generic map at the top of the message. 1 Hacker Way, Menlo Park, CA 94025
<LATITUDE< Location latitude 37.483307
<LONGITUDE< Location longitude. 122.148981
<NAME< Text that will appear immediately below the generic map at the top of the message. Pablo Morales

Example Request

curl -L 'https://graph.facebook.com/v16.0/106540352242922/messages' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer EAAJB...' \
-d '
{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "12245554792",
  "type": "template",
  "template": {
    "name": "order_delivery_update",
    "language": {
      "code": "en_US"
    },
    "components": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "location",
            "location": {
              "latitude": "37.483307",
              "longitude": "122.148981",
              "name": "Pablo Morales",
              "address": "1 Hacker Way, Menlo Park, CA 94025"
            }
          }
        ]
      },
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "Pablo"
          },
          {
            "type": "text",
            "text": "566701"
          }
        ]
      }
    ]
  }
}'

This is an example request to send an existing template that uses the following components:

Authentication Template Messages With One-Time Password Buttons

See Sending Authentication Templates with One-Time Password Buttons.

Delivery Sequence of Multiple Messages

When sending a series of messages, the order in which messages are delivered is not guaranteed to match the order of your API requests. If you need to ensure the sequence of message delivery, confirm receipt of a delivered status in a messages webhook before sending the next message in your message sequence.

Sending Authentication Templates with One-Time Password Buttons

This document explains how to send approved authentication templates with one-time password buttons.

Request

Use the WhatsApp Business Phone Number > Messages endpoint to send an authentication template message with a one-time password button.

Syntax

POST /<WHATSAPP_BUSINESS_PHONE_NUMBER_ID>/messages

Post Body

{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "<CUSTOMER_PHONE_NUMBER>",
  "type": "template",
  "template": {
    "name": "<TEMPLATE_NAME>",
    "language": {
      "code": "<TEMPLATE_LANGUAGE_CODE>"
    },
    "components": [
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "<ONE-TIME PASSWORD>"
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "url",
        "index": "0",
        "parameters": [
          {
            "type": "text",
            "text": "<ONE-TIME PASSWORD>"
          }
        ]
      }
    ]
  }
}

Properties

Placeholder Description Sample Value
<CUSTOMER_PHONE_NUMBER> The customer's WhatsApp phone number. 12015553931
<ONE-TIME PASSWORD> The one-time password or verification code to be delivered to the customer.

Note that this value must appear twice in the payload.

J$FpnYnP
<TEMPLATE_LANGUAGE_CODE> The template's language and locale code. en_US
<TEMPLATE_NAME> The template's name. verification_code

Response

{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "<INPUT>",
      "wa_id": "<WA_ID>"
    }
  ],
  "messages": [
    {
      "id": "<ID>"
    }
  ]
}

Upon success, the API will respond with:

Response Contents

Placeholder Description Sample Value
<ID> WhatsApp message ID. wamid.HBgLMTY1MDM4Nzk

0MzkVAgARGBJDOEI3ODgxNzQzMjJB

QTdEQTcA

<INPUT> Customer WhatsApp phone number (same as customer ID). 12015553931
<WA_ID> Customer ID (same as customer WhatsApp phone number). 12015553931

Example

Example Request

curl -L 'https://graph.facebook.com/v17.0/105954558954427/messages' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer EAAJB...' \
-d '{
      "messaging_product": "whatsapp",
      "recipient_type": "individual",
      "to": "12015553931",
      "type": "template",
      "template": {
        "name": "verification_code",
        "language": {
          "code": "en_US"
      },
      "components": [
        {
          "type": "body",
          "parameters": [
            {
              "type": "text",
              "text": "J$FpnYnP"
            }
          ]
        },
        {
          "type": "button",
          "sub_type": "url",
          "index": "0",
          "parameters": [
            {
              "type": "text",
              "text": "J$FpnYnP"
            }
          ]
        }
      ]
    }
  }'

Example Response

{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "12015553931",
      "wa_id": "12015553931"
    }
  ],
  "messages": [
    {
      "id": "wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBI4Qzc5QkNGNTc5NTMyMDU5QzEA"
    }
  ]
}

Sending Multi-Product Template Messages

This document explains how to send multi-product message (MPM) templates in template messages.

Components

MPM template messages must have:

Use the MPM button component to define sections and their titles that will appear when the customer taps the View items button, and to designate which products appear in each of those sections.

Request

To send an approved MPM template in a template message, send a POST request to the WhatsApp Business Phone Number > Messages endpoint. Use the POST body to define the contents of the message and to describe any variables to inject into the template itself.

Syntax

POST /<BUSINESS_PHONE_NUMBER_ID>/messages

Post Body

{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "<TO>",
  "type": "template",
  "template": {
    "name": "<NAME>",
    "language": {
      "code": "<CODE>"
    },
    "components": [

      /* Header component required if template uses a header variable */
      {
        "type": "header",
        "parameters": [
          {
            "type": "text",
            "text": "<HEADER_TEXT>"
          }
        ]
      },

      /* Body component required if template uses a body variable */
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "<BODY_TEXT>"
          }
        ]
      },

      /* MPM button component always required */
      {
        "type": "button",
        "sub_type": "mpm",
        "index": 0,
        "parameters": [
          {
            "type": "action",
            "action": {
              "thumbnail_product_retailer_id": "<THUMBNAIL_PRODUCT_RETAILER_ID>",
              "sections": [
                {
                  "title": "<TITLE>",
                  "product_items": [
                    {
                      "product_retailer_id": "<PRODUCT_RETAILER_ID>"
                    },
                    ... // Additional item objects (up to 30)
                  ]
                },
                ... // Add section objects (up to 10)
              ]
            }
          }
        ]
      }
    ]
  }
}

Properties

Placeholder Description Sample Value
<BODY_TEXT> Required if template uses variables.

String or array of strings. Text to replace body variable(s) defined in the template.

10OFF
<CODE> Template language and locale code. en_US
<HEADER_TEXT> Required if template uses a variable.

Text to replace header variable defined in the template.

Pablo
<NAME> Template name. abandoned_cart
<PRODUCT_RETAILER_ID> SKU number of the item you want to appear in the section.

SKU numbers are labeled as Content ID in the Commerce Manager.

Supports up to 30 products total, across all sections.

2lc20305pt
<THUMBNAIL_PRODUCT_RETAILER_ID> Item SKU number. Labeled as Content ID in the Commerce Manager.

The thumbnail of this item will be used as the template message's header image.

2lc20305pt
<TITLE> Section title text.

You can define up to 10 sections.

Maximum 24 characters. Markdown is not supported.

Popular Bundles
<TO> Customer phone number. 16505551234

Response

{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "<INPUT>",
      "wa_id": "<WA_ID>"
    }
  ],
  "messages": [
    {
      "id": "<ID>"
    }
  ]
}

Upon success, the API will respond with:

Response Contents

Placeholder Description Sample Value
<ID> WhatsApp message ID. wamid.HBgLMTY1MDM4Nzk0MzkVAgARG

BJDOEI3ODgxNzQzMjJBQTdEQTcA

<INPUT> Customer WhatsApp phone number. 16505551234
<WA_ID> Customer WhatsApp ID. 16505551234

Example

Example Request

curl 'https://graph.facebook.com/v17.0/106540352242922/messages' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer EAAJB...' \
-d '
{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "16505551234",
  "type": "template",
  "template": {
    "name": "abandoned_cart",
    "language": {
      "code": "en_US"
    },
    "components": [
      {
        "type": "header",
        "parameters": [
          {
            "type": "text",
            "text": "Pablo"
          }
        ]
      },
      {
        "type": "body",
        "parameters": [
          {
            "type": "text",
            "text": "10OFF"
          }
        ]
      },
      {
        "type": "button",
        "sub_type": "mpm",
        "index": 0,
        "parameters": [
          {
            "type": "action",
            "action": {
              "thumbnail_product_retailer_id": "2lc20305pt",
              "sections": [
                {
                  "title": "Popular Bundles",
                  "product_items": [
                    {
                      "product_retailer_id": "2lc20305pt"
                    },
                    {
                      "product_retailer_id": "nseiw1x3ch"
                    }
                  ]
                },
                {
                  "title": "Premium Packages",
                  "product_items": [
                    {
                      "product_retailer_id": "n6k6x0y7oe"
                    }
                  ]
                }
              ]
            }
          }
        ]
      }
    ]
  }
}'

This example sends an approved template named "abandoned_cart" and injects a variable (the customer's first name) into the template header and a discount code into the template body. It also defines two sections ("Popular Bundles" and "Premium Packages") and identifies the products (a total of 3) that should be injected into those sections.

Example Response

{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "16505551234",
      "wa_id": "16505551234"
    }
  ],
  "messages": [
    {
      "id": "wamid.HBgLMTY1MDM4Nzk0MzkVAgARGBJDOEI3ODgxNzQzMjJBQTdEQTcA"
    }
  ]
}