Send WhatsApp template messages

This document provides guidance to send WhatsApp Template messages using Advanced Communication Messages SDK.

Why do I need to send a template message?

A business can only send template messages until the user sends a message to the business.

A business or a user can initiate a conversation window, but the business is limited on which kinds of messages they can send. Only after the user sends a message to the business, the business is allowed to send text or media messages to the user during the active conversation. Once the 24 hour conversation window expires, the conversation must be reinitiated. To learn more about conversations, see the definition at WhatsApp Business Platform.

For further WhatsApp requirements on templates, refer to the WhatsApp Business Platform API references:

Choosing a template

When a WhatsApp Business Account is created through the Azure portal during embedded signup, a set of sample templates may be automatically available for you to try out. See the usage for a few of these sample templates at Examples.

Create template

To create your own templates, use the Meta WhatsApp Manager. Follow the instructions in the Meta Business Help Center at Create message templates for your WhatsApp Business account.

List templates

You can view your templates in the Azure portal by going to your Azure Communication Service resource > Templates.

Screenshot that shows an Azure Communication Services resource in the Azure portal, viewing the 'Templates' tab.

By selecting a template, you can view the template details.
The content field of the template details may include parameter bindings. The parameter bindings can be denoted as:

  • A "format" field with a value such as IMAGE.
  • Double brackets surrounding a number, such as {{1}}. The number, indexed started at 1, indicates the order in which the binding values must be supplied to create the message template.

Screenshot that shows template details.

Alternatively, you can view and edit all of your WhatsApp Business Account's templates in the WhatsApp Manager > Account tools > Message templates.

To list out your templates programmatically, you can fetch all templates for your channel ID:

MessageTemplateClient messageTemplateClient = new MessageTemplateClient(connectionString);
Pageable<MessageTemplateItem> templates = messageTemplateClient.GetTemplates(channelRegistrationId);

Quick reference

Templates with no parameters

If the template takes no parameters, you don't need to supply the values or bindings when creating the MessageTemplate.

var messageTemplate = new MessageTemplate(templateName, templateLanguage); 

Example

Templates with text parameters in the body

Use MessageTemplateText to define parameters in the body denoted with double brackets surrounding a number, such as {{1}}. The number, indexed started at 1, indicates the order in which the binding values must be supplied to create the message template.

Template definition body:

{
  "type": "BODY",
  "text": "Message with two parameters: {{1}} and {{2}}"
},

Message template assembly:

var param1 = new MessageTemplateText(name: "first", text: "First Parameter");
var param2 = new MessageTemplateText(name: "second", text: "Second Parameter");

WhatsAppMessageTemplateBindings bindings = new();
bindings.Body.Add(new(param1.Name));
bindings.Body.Add(new(param2.Name));

var messageTemplate = new MessageTemplate(templateName, templateLanguage);
messageTemplate.Bindings = bindings;
messageTemplate.Values.Add(param1);
messageTemplate.Values.Add(param2);

Examples

Templates with media in the header

Use MessageTemplateImage, MessageTemplateVideo, or MessageTemplateDocument to define the media parameter in a header.

Template definition header requiring image media:

{
  "type": "HEADER",
  "format": "IMAGE"
},

The "format" can require different media types. In the .NET SDK, each media type uses a corresponding MessageTemplateValue type.

Format MessageTemplateValue Type File Type
IMAGE MessageTemplateImage png, jpg
VIDEO MessageTemplateVideo mp4
DOCUMENT MessageTemplateDocument pdf

For more information on supported media types and size limits, see WhatsApp's documentation for message media.

Message template assembly for image media:

var url = new Uri("< Your media URL >");

var media = new MessageTemplateImage("image", url);
WhatsAppMessageTemplateBindings bindings = new();
bindings.Header.Add(new(media.Name));

var messageTemplate = new MessageTemplate(templateName, templateLanguage);
template.Bindings = bindings;
template.Values.Add(media);

Examples

Templates with quick reply buttons

Use MessageTemplateQuickAction to define the payload for quick reply buttons.

MessageTemplateQuickAction objects and have the following three attributes.
Specifically for quick reply buttons, follow these guidelines to create your MessageTemplateQuickAction object.

  • name
    The name is used to look up the value in MessageTemplateWhatsAppBindings.
  • text
    The text attribute isn't used.
  • payload
    The payload assigned to a button is available in a message reply if the user selects the button.

Template definition buttons:

{
  "type": "BUTTONS",
  "buttons": [
    {
      "type": "QUICK_REPLY",
      "text": "Yes"
    },
    {
      "type": "QUICK_REPLY",
      "text": "No"
    }
  ]
}

The order that the buttons appear in the template definition should match the order in which the buttons are defined when creating the bindings with MessageTemplateWhatsAppBindings.

Message template assembly:

var yes = new MessageTemplateQuickAction(name: "Yes", payload: "User said yes");
var no = new MessageTemplateQuickAction(name: "No", payload: "User said no");

var yesButton = new WhatsAppMessageTemplateBindingsButton(WhatsAppMessageButtonSubType.QuickReply.ToString(), yes.Name);
var noButton = new WhatsAppMessageTemplateBindingsButton(WhatsAppMessageButtonSubType.QuickReply.ToString(), no.Name);

WhatsAppMessageTemplateBindings bindings = new();
bindings.Buttons.Add(yesButton);
bindings.Buttons.Add(noButton);

var messageTemplate = new MessageTemplate(templateName, templateLanguage);
messageTemplate.Bindings = bindings;
template.Values.Add(yes);
template.Values.Add(no);

For more information on the payload in quick reply responses from the user, see WhatsApp's documentation for Received Callback from a Quick Reply Button.

Example

Templates with call to action buttons

Use MessageTemplateQuickAction to define the url suffix for call to action buttons.

MessageTemplateQuickAction objects and have the following three attributes.
Specifically for call to action buttons, follow these guidelines to create your MessageTemplateQuickAction object.

  • name
    The name is used to look up the value in MessageTemplateWhatsAppBindings.
  • text
    The text attribute defines the text that is appended to the URL.
  • payload
    The payload attribute isn't required.

Template definition buttons:

{
  "type": "BUTTONS",
  "buttons": [
    {
      "type": "URL",
      "text": "Take Survey",
      "url": "https://www.example.com/{{1}}"
    }
  ]
}

The order that the buttons appear in the template definition should match the order in which the buttons are defined when creating the bindings with MessageTemplateWhatsAppBindings.

Message template assembly:

var urlSuffix = new MessageTemplateQuickAction(name: "text", text: "url-suffix-text");

var urlButton = new WhatsAppMessageTemplateBindingsButton(WhatsAppMessageButtonSubType.Url.ToString(), urlSuffix.Name);

WhatsAppMessageTemplateBindings bindings = new();
bindings.Buttons.Add(urlButton);

var messageTemplate = new MessageTemplate(templateName, templateLanguage);
messageTemplate.Bindings = bindings;
messageTemplate.Values.Add(urlSuffix);

Example

Examples

These examples utilize sample templates available to WhatsApp Business Accounts created through the Azure portal embedded signup.

Use sample template sample_template

The sample template named sample_template takes no parameters.

Screenshot that shows template details for template named sample_template.

Assemble the MessageTemplate by referencing the target template's name and language.

string templateName = "sample_template"; 
string templateLanguage = "en_us"; 

var sampleTemplate = new MessageTemplate(templateName, templateLanguage); 

Use sample template sample_shipping_confirmation

Some templates take parameters. Only include the parameters that the template requires. Including parameters not in the template is invalid.

Screenshot that shows template details for template named sample_shipping_confirmation.

In this sample, the body of the template has one parameter:

{
  "type": "BODY",
  "text": "Your package has been shipped. It will be delivered in {{1}} business days."
},

Parameters are defined with the MessageTemplateValue values and MessageTemplateWhatsAppBindings bindings. Use the values and bindings to assemble the MessageTemplate.

string templateName = "sample_shipping_confirmation"; 
string templateLanguage = "en_us"; 

var threeDays = new MessageTemplateText("threeDays", "3");

WhatsAppMessageTemplateBindings bindings = new();
bindings.Body.Add(new(threeDays.Name));

MessageTemplate shippingConfirmationTemplate  = new(templateName, templateLanguage);
shippingConfirmationTemplate.Bindings = bindings;
shippingConfirmationTemplate.Values.Add(threeDays);

Use sample template sample_movie_ticket_confirmation

Templates can require various types of parameters such as text and images.

Screenshot that shows template details for template named sample_movie_ticket_confirmation.

In this sample, the header of the template requires an image:

{
  "type": "HEADER",
  "format": "IMAGE"
},

And the body of the template requires four text parameters:

{
  "type": "BODY",
  "text": "Your ticket for *{{1}}*\n*Time* - {{2}}\n*Venue* - {{3}}\n*Seats* - {{4}}"
},

Create one MessageTemplateImage and four MessageTemplateText variables. Then, assemble your list of MessageTemplateValue and your MessageTemplateWhatsAppBindings by providing the parameters in the order that the parameters appear in the template content.

string templateName = "sample_movie_ticket_confirmation"; 
string templateLanguage = "en_us"; 
var imageUrl = new Uri("https://aka.ms/acsicon1");

var image = new MessageTemplateImage("image", imageUrl);
var title = new MessageTemplateText("title", "Contoso");
var time = new MessageTemplateText("time", "July 1st, 2023 12:30PM");
var venue = new MessageTemplateText("venue", "Southridge Video");
var seats = new MessageTemplateText("seats", "Seat 1A");

WhatsAppMessageTemplateBindings bindings = new();
bindings.Header.Add(new(image.Name));
bindings.Body.Add(new(title.Name));
bindings.Body.Add(new(time.Name));
bindings.Body.Add(new(venue.Name));
bindings.Body.Add(new(seats.Name));

MessageTemplate movieTicketConfirmationTemplate = new(templateName, templateLanguage);
movieTicketConfirmationTemplate.Values.Add(image);
movieTicketConfirmationTemplate.Values.Add(title);
movieTicketConfirmationTemplate.Values.Add(time);
movieTicketConfirmationTemplate.Values.Add(venue);
movieTicketConfirmationTemplate.Values.Add(seats);
movieTicketConfirmationTemplate.Bindings = bindings;

Use sample template sample_happy_hour_announcement

This sample template uses a video in the header and two text parameters in the body.

Screenshot that shows template details for template named sample_happy_hour_announcement.

Here, the header of the template requires a video:

{
  "type": "HEADER",
  "format": "VIDEO"
},

The video should be a URL to hosted mp4 video. For more information on supported media types and size limits, see WhatsApp's documentation for message media.

And the body of the template requires two text parameters:

{
  "type": "BODY",
  "text": "Happy hour is here! 🍺😀🍸\nPlease be merry and enjoy the day. 🎉\nVenue: {{1}}\nTime: {{2}}"
},

Create one MessageTemplateVideo and two MessageTemplateText variables. Then, assemble your list of MessageTemplateValue and your MessageTemplateWhatsAppBindings by providing the parameters in the order that the parameters appear in the template content.

string templateName = "sample_happy_hour_announcement";
string templateLanguage = "en_us";
var videoUrl = new Uri("< Your .mp4 Video URL >");

var video = new MessageTemplateVideo("video", videoUrl);
var venue = new MessageTemplateText("venue", "Fourth Coffee");
var time = new MessageTemplateText("time", "Today 2-4PM");
WhatsAppMessageTemplateBindings bindings = new();
bindings.Header.Add(new(video.Name));
bindings.Body.Add(new(venue.Name));
bindings.Body.Add(new(time.Name));

MessageTemplate happyHourAnnouncementTemplate = new(templateName, templateLanguage);
happyHourAnnouncementTemplate.Values.Add(venue);
happyHourAnnouncementTemplate.Values.Add(time);
happyHourAnnouncementTemplate.Values.Add(video);
happyHourAnnouncementTemplate.Bindings = bindings;

Use sample template sample_flight_confirmation

This sample template uses a document in the header and three text parameters in the body.

Screenshot that shows template details for template named sample_flight_confirmation.

Here, the header of the template requires a document:

{
  "type": "HEADER",
  "format": "DOCUMENT"
},

The document should be a URL to hosted pdf document. For more information on supported media types and size limits, see WhatsApp's documentation for message media.

And the body of the template requires three text parameters:

{
  "type": "BODY",
  "text": "This is your flight confirmation for {{1}}-{{2}} on {{3}}."
},

Create one MessageTemplateDocument and three MessageTemplateText variables. Then, assemble your list of MessageTemplateValue and your MessageTemplateWhatsAppBindings by providing the parameters in the order that the parameters appear in the template content.

string templateName = "sample_flight_confirmation";
string templateLanguage = "en_us";
var documentUrl = new Uri("< Your .pdf document URL >");

var document = new MessageTemplateDocument("document", documentUrl);
var firstName = new MessageTemplateText("firstName", "Kat");
var lastName = new MessageTemplateText("lastName", "Larssen");
var date = new MessageTemplateText("date", "July 1st, 2023");

WhatsAppMessageTemplateBindings bindings = new();
bindings.Header.Add(new(document.Name));
bindings.Body.Add(new(firstName.Name));
bindings.Body.Add(new(lastName.Name));
bindings.Body.Add(new(date.Name));

MessageTemplate flightConfirmationTemplate = new(templateName, templateLanguage);
flightConfirmationTemplate.Values.Add(document);
flightConfirmationTemplate.Values.Add(firstName);
flightConfirmationTemplate.Values.Add(lastName);
flightConfirmationTemplate.Values.Add(date);
flightConfirmationTemplate.Bindings = bindings;

Use sample template sample_issue_resolution

This sample template adds two prefilled reply buttons to the message. It also includes one text parameter in the body.

Screenshot that shows template details for template named sample_issue_resolution.

Here, the body of the template requires one text parameter:

{
  "type": "BODY",
  "text": "Hi {{1}}, were we able to solve the issue that you were facing?"
},

And the template includes two prefilled reply buttons, Yes and No.

{
  "type": "BUTTONS",
  "buttons": [
    {
      "type": "QUICK_REPLY",
      "text": "Yes"
    },
    {
      "type": "QUICK_REPLY",
      "text": "No"
    }
  ]
}

Quick reply buttons are defined as MessageTemplateQuickAction objects and have three attributes:

  • name
    The name is used to look up the value in MessageTemplateWhatsAppBindings.
  • text
    Using the quick reply buttons, the text attribute isn't used.
  • payload
    The payload assigned to a button is available in a message reply if the user selects the button.

For more information on buttons, see WhatsApp's documentation for Button Parameter Object.

Create one MessageTemplateText and two MessageTemplateQuickAction variables. Then, assemble your list of MessageTemplateValue and your MessageTemplateWhatsAppBindings by providing the parameters in the order that the parameters appear in the template content. The order also matters when defining your binding's buttons.

string templateName = "sample_issue_resolution";
string templateLanguage = "en_us";

var name = new MessageTemplateText(name: "name", text: "Kat");
var yes = new MessageTemplateQuickAction(name: "Yes"){ Payload =  "Kat said yes" };
var no = new MessageTemplateQuickAction(name: "No") { Payload = "Kat said no" };

WhatsAppMessageTemplateBindings bindings = new();
bindings.Body.Add(new(name.Name));
bindings.Buttons.Add(new(WhatsAppMessageButtonSubType.QuickReply.ToString(), yes.Name));
bindings.Buttons.Add(new(WhatsAppMessageButtonSubType.QuickReply.ToString(), no.Name));

MessageTemplate issueResolutionTemplate = new(templateName, templateLanguage);
issueResolutionTemplate.Values.Add(name);
issueResolutionTemplate.Values.Add(yes);
issueResolutionTemplate.Values.Add(no);
issueResolutionTemplate.Bindings = bindings;

Use sample template sample_purchase_feedback

This sample template adds a button with a dynamic URL link to the message. It also uses an image in the header and a text parameter in the body.

If using the precreated sample template sample_purchase_feedback, you need to modify the URL Type of its button from Static to Dynamic.
Go to your Message templates in the WhatsApp manager and edit the template for sample_purchase_feedback. In the dropdown for URL Type, change it from Static to Dynamic. Include a sample URL if necessary.

Screenshot that shows editing URL Type in the WhatsApp manager.

Now, if you view the template details in the Azure portal, you see: Screenshot that shows template details for template named sample_purchase_feedback.

In this sample, the header of the template requires an image:

{
  "type": "HEADER",
  "format": "IMAGE"
},

Here, the body of the template requires one text parameter:

{
  "type": "BODY",
  "text": "Thank you for purchasing {{1}}! We value your feedback and would like to learn more about your experience."
},

And the template includes a dynamic URL button with one parameter:

{
  "type": "BUTTONS",
  "buttons": [
    {
      "type": "URL",
      "text": "Take Survey",
      "url": "https://www.example.com/{{1}}"
    }
  ]
}

Call to action buttons for website links are defined as MessageTemplateQuickAction objects and have three attributes:

  • name
    The name is used to look up the value in MessageTemplateWhatsAppBindings.
  • text
    Using the call to action button for website links, the text attribute defines the text that is appended to the URL.
    For this example, our text value is survey-code. In the message received by the user, they're presented with a button that links them to the URL https://www.example.com/survey-code.
  • payload
    Using the call to action button for website links, the payload attribute isn't required.

For more information on buttons, see WhatsApp's documentation for Button Parameter Object.

Create one MessageTemplateImage, one MessageTemplateText, and one MessageTemplateQuickAction variable. Then, assemble your list of MessageTemplateValue and your MessageTemplateWhatsAppBindings by providing the parameters in the order that the parameters appear in the template content. The order also matters when defining your binding's buttons.

string templateName = "sample_purchase_feedback";
string templateLanguage = "en_us";
var imageUrl = new Uri("https://aka.ms/acsicon1");

var image = new MessageTemplateImage(name: "image", uri: imageUrl);
var product = new MessageTemplateText(name: "product", text: "coffee");
var urlSuffix = new MessageTemplateQuickAction(name: "text") { Text = "survey-code" };

WhatsAppMessageTemplateBindings bindings = new();
bindings.Header.Add(new(image.Name));
bindings.Body.Add(new(product.Name));
bindings.Buttons.Add(new(WhatsAppMessageButtonSubType.Url.ToString(), urlSuffix.Name));

MessageTemplate purchaseFeedbackTemplate = new("sample_purchase_feedback", "en_us");
purchaseFeedbackTemplate.Values.Add(image);
purchaseFeedbackTemplate.Values.Add(product);
purchaseFeedbackTemplate.Values.Add(urlSuffix);
purchaseFeedbackTemplate.Bindings = bindings;

Full code example

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Azure;
using Azure.Communication.Messages;
using Azure.Communication.Messages.Models.Channels;

namespace SendTemplateMessages
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            Console.WriteLine("Azure Communication Services - Send WhatsApp Template Messages\n");

            string connectionString = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_CONNECTION_STRING");

            NotificationMessagesClient notificationMessagesClient = new NotificationMessagesClient(connectionString);

            var channelRegistrationId = new Guid("<Your Channel ID>");
            var recipientList = new List<string> { "<Recipient's WhatsApp Phone Number>" };

            // List out available templates for a channel ID
            MessageTemplateClient messageTemplateClient = new MessageTemplateClient(connectionString);
            Pageable<MessageTemplateItem> templates = messageTemplateClient.GetTemplates(channelRegistrationId);
            foreach (WhatsAppMessageTemplateItem template in templates)
            {
                Console.WriteLine("Name: {0}\tLanguage: {1}\tStatus: {2}\tContent: {3}\n",
                    template.Name, template.Language, template.Status, template.Content);
            }

            // Send Sample Template sample_template
            MessageTemplate sampleTemplate = AssembleSampleTemplate();
            var sampleTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, sampleTemplate);
            var result = await notificationMessagesClient.SendAsync(sampleTemplateContent);
            PrintResponse(result);
           
            // Send sample template sample_shipping_confirmation
            MessageTemplate shippingConfirmationTemplate = AssembleSampleShippingConfirmation();
            var shippingConfirmationTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, shippingConfirmationTemplate);
            result = await notificationMessagesClient.SendAsync(shippingConfirmationTemplateContent);
            PrintResponse(result);

            // Send sample template sample_movie_ticket_confirmation
            MessageTemplate movieTicketConfirmationTemplate = AssembleSampleMovieTicketConfirmation();
            var movieTicketConfirmationTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, movieTicketConfirmationTemplate);
            result = await notificationMessagesClient.SendAsync(movieTicketConfirmationTemplateContent);
            PrintResponse(result);

            // Send sample template sample_happy_hour_announcement
            MessageTemplate happyHourTemplate = AssembleSampleHappyHourAnnouncement();
            var happyHourTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, happyHourTemplate);
            result = await notificationMessagesClient.SendAsync(happyHourTemplateContent);
            PrintResponse(result);

            // Send sample template sample_flight_confirmation
            MessageTemplate flightConfirmationTemplate = AssembleSampleFlightConfirmation();
            var flightConfirmationTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, flightConfirmationTemplate);
            result = await notificationMessagesClient.SendAsync(flightConfirmationTemplateContent);
            PrintResponse(result);

            // Send sample template sample_issue_resolution
            MessageTemplate issueResolutionTemplate = AssembleSampleIssueResolution();
            var issueResolutionTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, issueResolutionTemplate);
            result = await notificationMessagesClient.SendAsync(issueResolutionTemplateContent);
            PrintResponse(result);

            // Send sample template sample_purchase_feedback
            MessageTemplate purchaseFeedbackTemplate = AssembleSamplePurchaseFeedback();
            var purchaseFeedbackTemplateContent = new TemplateNotificationContent(channelRegistrationId, recipientList, purchaseFeedbackTemplate);
            result = await notificationMessagesClient.SendAsync(purchaseFeedbackTemplateContent);
            PrintResponse(result);

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey(true);
        }

        public static MessageTemplate AssembleSampleTemplate()
        {
            string templateName = "sample_template";
            string templateLanguage = "en_us";

            return new MessageTemplate(templateName, templateLanguage);
        }

        public static MessageTemplate AssembleSampleShippingConfirmation()
        {
            string templateName = "sample_shipping_confirmation";
            string templateLanguage = "en_us";

            var threeDays = new MessageTemplateText("threeDays", "3");

            WhatsAppMessageTemplateBindings bindings = new();
            bindings.Body.Add(new(threeDays.Name));

            MessageTemplate shippingConfirmationTemplate = new(templateName, templateLanguage);
            shippingConfirmationTemplate.Bindings = bindings;
            shippingConfirmationTemplate.Values.Add(threeDays);

            return shippingConfirmationTemplate;
        }

        public static MessageTemplate AssembleSampleMovieTicketConfirmation()
        {
            string templateName = "sample_movie_ticket_confirmation"; 
            string templateLanguage = "en_us"; 
            var imageUrl = new Uri("https://aka.ms/acsicon1");

            var image = new MessageTemplateImage("image", imageUrl);
            var title = new MessageTemplateText("title", "Contoso");
            var time = new MessageTemplateText("time", "July 1st, 2023 12:30PM");
            var venue = new MessageTemplateText("venue", "Southridge Video");
            var seats = new MessageTemplateText("seats", "Seat 1A");

            WhatsAppMessageTemplateBindings bindings = new();
            bindings.Header.Add(new(image.Name));
            bindings.Body.Add(new(title.Name));
            bindings.Body.Add(new(time.Name));
            bindings.Body.Add(new(venue.Name));
            bindings.Body.Add(new(seats.Name));

            MessageTemplate movieTicketConfirmationTemplate = new(templateName, templateLanguage);
            movieTicketConfirmationTemplate.Values.Add(image);
            movieTicketConfirmationTemplate.Values.Add(title);
            movieTicketConfirmationTemplate.Values.Add(time);
            movieTicketConfirmationTemplate.Values.Add(venue);
            movieTicketConfirmationTemplate.Values.Add(seats);
            movieTicketConfirmationTemplate.Bindings = bindings;

            return movieTicketConfirmationTemplate;
        }

        public static MessageTemplate AssembleSampleHappyHourAnnouncement()
        {
            string templateName = "sample_happy_hour_announcement";
            string templateLanguage = "en_us";
            var videoUrl = new Uri("< Your .mp4 Video URL >");

            var video = new MessageTemplateVideo("video", videoUrl);
            var venue = new MessageTemplateText("venue", "Fourth Coffee");
            var time = new MessageTemplateText("time", "Today 2-4PM");
            WhatsAppMessageTemplateBindings bindings = new();
            bindings.Header.Add(new(video.Name));
            bindings.Body.Add(new(venue.Name));
            bindings.Body.Add(new(time.Name));

            MessageTemplate happyHourAnnouncementTemplate = new(templateName, templateLanguage);
            happyHourAnnouncementTemplate.Values.Add(venue);
            happyHourAnnouncementTemplate.Values.Add(time);
            happyHourAnnouncementTemplate.Values.Add(video);
            happyHourAnnouncementTemplate.Bindings = bindings;

            return happyHourAnnouncementTemplate;
        }

        public static MessageTemplate AssembleSampleFlightConfirmation()
        {
            string templateName = "sample_flight_confirmation";
            string templateLanguage = "en_us";
            var documentUrl = new Uri("< Your .pdf document URL >");

            var document = new MessageTemplateDocument("document", documentUrl);
            var firstName = new MessageTemplateText("firstName", "Kat");
            var lastName = new MessageTemplateText("lastName", "Larssen");
            var date = new MessageTemplateText("date", "July 1st, 2023");

            WhatsAppMessageTemplateBindings bindings = new();
            bindings.Header.Add(new(document.Name));
            bindings.Body.Add(new(firstName.Name));
            bindings.Body.Add(new(lastName.Name));
            bindings.Body.Add(new(date.Name));

            MessageTemplate flightConfirmationTemplate = new(templateName, templateLanguage);
            flightConfirmationTemplate.Values.Add(document);
            flightConfirmationTemplate.Values.Add(firstName);
            flightConfirmationTemplate.Values.Add(lastName);
            flightConfirmationTemplate.Values.Add(date);
            flightConfirmationTemplate.Bindings = bindings;

            return flightConfirmationTemplate;
        }

        public static MessageTemplate AssembleSampleIssueResolution()
        {
            string templateName = "sample_issue_resolution";
            string templateLanguage = "en_us";

            var name = new MessageTemplateText(name: "name", text: "Kat");
            var yes = new MessageTemplateQuickAction(name: "Yes"){ Payload =  "Kat said yes" };
            var no = new MessageTemplateQuickAction(name: "No") { Payload = "Kat said no" };

            WhatsAppMessageTemplateBindings bindings = new();
            bindings.Body.Add(new(name.Name));
            bindings.Buttons.Add(new(WhatsAppMessageButtonSubType.QuickReply.ToString(), yes.Name));
            bindings.Buttons.Add(new(WhatsAppMessageButtonSubType.QuickReply.ToString(), no.Name));

            MessageTemplate issueResolutionTemplate = new(templateName, templateLanguage);
            issueResolutionTemplate.Values.Add(name);
            issueResolutionTemplate.Values.Add(yes);
            issueResolutionTemplate.Values.Add(no);
            issueResolutionTemplate.Bindings = bindings;

            return issueResolutionTemplate;
        }

        public static MessageTemplate AssembleSamplePurchaseFeedback()
        {
            
            string templateName = "sample_purchase_feedback";
            string templateLanguage = "en_us";
            var imageUrl = new Uri("https://aka.ms/acsicon1");

            var image = new MessageTemplateImage(name: "image", uri: imageUrl);
            var product = new MessageTemplateText(name: "product", text: "coffee");
            var urlSuffix = new MessageTemplateQuickAction(name: "text") { Text = "survey-code"};
            
            WhatsAppMessageTemplateBindings bindings = new();
            bindings.Header.Add(new(image.Name));
            bindings.Body.Add(new(product.Name));
            bindings.Buttons.Add(new(WhatsAppMessageButtonSubType.Url.ToString(), urlSuffix.Name));

            MessageTemplate purchaseFeedbackTemplate = new(templateName, templateLanguage);
            purchaseFeedbackTemplate.Values.Add(image);
            purchaseFeedbackTemplate.Values.Add(product);
            purchaseFeedbackTemplate.Values.Add(urlSuffix);
            purchaseFeedbackTemplate.Bindings = bindings;

            return purchaseFeedbackTemplate;
        }

        public static void PrintResponse(Response<SendMessageResult> response)
        {
            Console.WriteLine($"Response: {response.GetRawResponse().Status} " +
                $"({response.GetRawResponse().ReasonPhrase})");
            Console.WriteLine($"Date: " +
                $"{response.GetRawResponse().Headers.First(header => header.Name == "Date").Value}");
            Console.WriteLine($"ClientRequestId: {response.GetRawResponse().ClientRequestId}");
            Console.WriteLine($"MS-CV: " +
                $"{response.GetRawResponse().Headers.First(header => header.Name == "MS-CV").Value}");
            foreach (var receipts in response.Value.Receipts)
            {
                Console.WriteLine($"MessageId: {receipts.MessageId}");
            }
            Console.WriteLine($"\n");
        }
    }
}

Next steps