We are sunsetting On-Premises API. Refer to our On-Premises API Sunset document for details, and to learn how to migrate to our next-generation Cloud API.

Sending Interactive Messages

This guide teaches you how to send each interactive message option. Interactive messages give your users a simpler way to find and select what they want from your business on WhatsApp. During testing, chatbots using interactive messaging features achieved significantly higher response rates and conversions compared to those that are text-based.

Types of interactive messages:

  • List Messages: Messages including a menu of up to 10 options. This type of message offers a simpler and more consistent way for users to make a selection when interacting with a business.
  • Reply Button Messages: Messages including up to 3 options —each option is a button. This type of message offers a quicker way for users to make a selection from a menu when interacting with a business. Reply buttons have the same user experience as interactive templates with buttons.
  • Single-Product Messages: Messages with a single product item from the business's inventory. See Share Products With Customers for more information.
  • Multi-Product Messages: Messages containing a selection of up to 30 items from the business's inventory. See Share Products With Customers for more information.
  • Location Request Messages: Messages that request the user's location.
  • Flows Messages: Messages for structured interactions. See Flows Messages for more information.

Interactive Message Specifications

  • Interactive messages can be combined together in the same flow.
  • Users cannot select more than one option at the same time from a list or button message, but they can go back and re-open a previous message.
  • List or reply button messages cannot be used as notifications. Currently, they can only be sent within 24 hours of the last message sent by the user. If you try to send a message outside the 24-hour window, you get an error message.
  • Supported platforms: iOS, Android, and web (Flows messages are not supported on web).

See how text messages compare to interactive messages:


See an example of how List messages and Reply buttons can be combined in the same flow:

Something Went Wrong
We're having trouble playing this video.

Overview

Why You Should Use It

User Comprehension

When compared to text-based lists, interactive messages provide a simpler and more consistent format for people to find and select what they want from a business. During testing, people had higher comprehension levels interacting with these features.

Business Outcomes

During testing, chatbots using interactive messaging features achieved significantly higher response rates and conversions compared to those that are text-based.

Personalized

Populated dynamically in real-time and so can be personalized to the customer or situation. For example, you can show a List message of available time slots for appointment booking, or use Reply buttons to show previous delivery addresses.

No Templates

Interactive Messages do not require templates or pre-approvals.

When You Should Use It

List Messages are best for presenting several options, such as:

  • A customer care or FAQ menu
  • A take-out menu
  • Selection of nearby stores or locations
  • Available reservation times
  • Choosing a recent order to repeat

Reply Buttons are best for offering quick responses from a limited set of options, such as:

  • Airtime recharge
  • Changing personal details
  • Reordering a previous order
  • Requesting a return
  • Adding optional extras to a food order
  • Choosing a payment method

Reply buttons are particularly valuable for ‘personalized’ use cases where a generic response is not adequate.

Flows messages are best for structured communication across one or multiple screens, such as:

  • Booking appointments
  • Browsing products
  • Collecting customer feedback
  • Getting new sales leads

Flows messages enable businesses to offer a richer, more engaging user experience that can help customers get things done faster on WhatsApp without necessarily needing to switch to another app, or visit a website.

How To Use It

At the API level, interactive messages are set by specifying a message’s type to interactive and adding the interactive object. Generally, these messages include 4 main parts: header, body, footer, and action:

{
  "recipient_type": "individual",
  "to" : "whatsapp-id",
  "type": "interactive" 
  "interactive":{
    "type": "list" | "button" | ...,
    "header": {},
    "body": {},
    "footer": {},
    "action": {}
  }
}
For List Messages, this is how the parts fit together:

For Reply Buttons Messages, this is how the parts fit together:

See more information below on how to send these messages.

Get Started

Before you can send each message, you need to get your receiver’s WhatsApp ID with a call to the /contacts node.

We recommend setting up your webhooks to receive message status and inbound message notifications. This way, you can track if your message was sent and the answers you get from the users. See Webhooks for more information.

Step 1: Assemble your interactive object

List Messages

To send a list message, you must assemble an interactive object of type list with the following components:

ObjectDescription

header

Optional.

If you decide to include it, you must set the header’s type to text and add a text field with the desired content. Maximum of 60 characters.


See all available header fields.

body

Required.

Your message’s body. Maximum of 1024 characters.


See all available body fields.

footer

Optional.

Your message’s footer.


See all available footer fields.

action

Required.

Inside action, you must nest:

  • a button field with your button’s content, maximum of 20 characters
  • at least one section object (maximum of 10) with a maximum of 24 characters for the title for section

Inside section, you must add at least one rows object. Maximum of 24 characters for the title for a row and maximum of 72 characters for the description for a row.


See all available action fields.

See all available section fields.

By the end, your interactive object should look something like this:

"interactive":{
  "type": "list",
  "header": {
    "type": "text",
    "text": "your-header-content"
  },
  "body": {
    "text": "your-text-message-content"
  },
  "footer": {
    "text": "your-footer-content"
  },
  "action": {
    "button": "cta-button-content",
    "sections":[
      {
        "title":"your-section-title-content",
        "rows": [
          {
            "id":"unique-row-identifier",
            "title": "row-title-content",
            "description": "row-description-content",           
          }
        ]
      },
      {
        "title":"your-section-title-content",
        "rows": [
          {
            "id":"unique-row-identifier",
            "title": "row-title-content",
            "description": "row-description-content",           
          }
        ]
      },
      ...
    ]
  }
}

Reply Buttons

To send a reply button message, you must assemble an interactive object of type button with the following components:

ObjectDescription

header

Optional.

For button interactive messages, you can use the following header types: text, video, image, or document.


Once you select your type, add the corresponding objects/fields with more information:

  • For video, image, and document types: Add a media object.
  • For text type: Add a text field with the desired content.

Example:

"header": {
      "type": "text" | "image" | "video" | "document",
      "text": "your text"
      # OR
      "document": {
        "id": "your-media-id",
        "filename": "some-file-name"
      }
      # OR
      "document": {
        "link": "the-provider-name/protocol://the-url",
        "provider": {
          "name": "provider-name",
        },
        "filename": "some-file-name"
      },
      # OR
      "video": {
        "id": "your-media-id"
      }
      # OR
      "video": {
        "link": "the-provider-name/protocol://the-url",
        "provider": {
          "name": "provider-name"
        }
      }
      # OR
      "image": {
        "id": "your-media-id"
      }
      # OR
      "image": {
        "link": "http(s)://the-url",
        "provider": {
          "name": "provider-name"
        }
      }
    }

See all available header fields.

body

Required.

See all available body fields.

footer

Optional.

See all available footer fields.

action

Required.

You must add at least one button, and include type, title, and id for your buttons. You cannot add more than 3 buttons. Maximun of 20 characters for title.

You cannot have leading or trailing spaces when setting the ID.


Example:

"action": {
      "buttons": [
        {
          "type": "reply",
          "reply": {
            "id": "unique-postback-id",
            "title": "First Button’s Title" 
          }
        },
        {
          "type": "reply",
          "reply": {
            "id": "unique-postback-id",
            "title": "Second Button’s Title" 
          }
        }
      ] 
    }

See all available action fields.

By the end, your interactive object should look something like this:

"interactive": {
    "type": "button",
    "header": { # optional
      "type": "text" | "image" | "video" | "document",
      "text": "your text"
      # OR
      "document": {
        "id": "your-media-id",
        "filename": "some-file-name"
      }
      # OR
      "document": {
        "link": "the-provider-name/protocol://the-url",
        "provider": {
          "name": "provider-name",
        },
        "filename": "some-file-name"
      },
      # OR
      "video": {
        "id": "your-media-id"
      }
      # OR
      "video": {
        "link": "the-provider-name/protocol://the-url",
        "provider": {
          "name": "provider-name"
        }
      }
      # OR
      "image": {
        "id": "your-media-id"
      }
      # OR
      "image": {
        "link": "http(s)://the-url",
        "provider": {
          "name": "provider-name"
        }
      }
    }, # end header
    "body": {
      "text": "your-text-body-content"
    },
    "footer": { # optional
      "text": "your-text-footer-content"
    },
    "action": {
      "buttons": [
        {
          "type": "reply",
          "reply": {
            "id": "unique-postback-id",
            "title": "First Button’s Title" 
          }
        },
        {
          "type": "reply",
          "reply": {
            "id": "unique-postback-id",
            "title": "Second Button’s Title" 
          }
        }
      ] 
    } # end action   
  } # end interactive

Location Request Messages

Location request messages contain body text and a Send location button that users can tap. Tapping the button displays a location sharing screen which the user can then use to share their location.

To send a location request message, first assemble an interactive object with text you wish to display in the message:

{
  "type": "location_request_message",
  "body": {
    "type": "text",
    "text": "<TEXT>"
  },
  "action": {
    "name": "send_location" 
  }
}
PropertyDescription

type

Set to location_request_message.

body.type

Set to text.

body.text

Set to the text you want to display above the Send location button.

action.name

Set to send_location.

Flows Messages

Flows messages contain a call-to-action button that users can tap. Tapping the button displays your custom Flow.

To send a Flows message, you must assemble an interactive object of type flow. See here the full details.

Step 2: Add common message parameters

Now that you have your interactive object, append the other parameters that make a message: recipient_type, to, and type. Remember to set the type to interactive.

{
  "recipient_type": "individual",
  "to" : "whatsapp-id", // WhatsApp ID of your recipient
  "type": "interactive",
  "interactive":{
    // Your interactive object  
   }
  }

See parameters common to all message types here.

Step 3: Make a POST call to /messages

Make a POST call to the /messages endpoint with the JSON object you have assembled in steps 1 and 2. If your message is sent successfully, you get the following response:

{
  "messages": [{
    "id": "{message-id}"
  }]
}

Step 4: Check Webhooks

If you set up your webhooks, check for changes in your message status as well as any responses coming from users.

Webhooks of users responding to interactive messages include a new component called interactive, which contains information about the user’s choice. See Webhooks, Components for more information.

For example, here's a webhook request describing a user who has shared their location.

{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "12345",
      "changes": [
        {
          "value": {
            "messaging_product": "whatsapp",
            "metadata": {
              "display_phone_number": "12345",
              "phone_number_id": "12345"
            },
            "contacts": [
              {
                "profile": {
                  "name": "John Doe"
                },
                "wa_id": "12345"
              }
            ],
            "messages": [
              {
                "context": {
                  "from": "12345",
                  "id": "test-id"
                },
                "from": "123450",
                "id": "test-id",
                "timestamp": "16632",
                "location": {
                  "address": "1071 5th Ave, New York, NY 10128", #Optional
                  "latitude": 37.421996751527,
                  "longitude": -122.08407156636,
                  "name": "Solomon R. Guggenheim Museum" #Optional
                },
                "type": "location"
              }
            ]
          },
          "field": "messages"
        }
      ]
    }
  ]
}

The location component within the payload contains the user's latitude and longitude. Note that address and name are optional for the user and may not be included.

"location": {
  "address": "1071 5th Ave, New York, NY 10128", #Optional
  "latitude": 40.782910059774,
  "longitude": -73.959075808525,
  "name": "Solomon R. Guggenheim Museum" #Optional
}