Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

twilio/flows



Overview

overview page anchor

With WhatsApp Flows, you create an in-app, multi-screen experience that a user receives and submits all within WhatsApp.

A business sends a Flow as part of an approved Content Template. The templated message contains a button to open the attached Flow in the WhatsApp UI. Within the Flow, you can include text, images, and several input components. End users respond with single-choice, multi-choice, toggle, short-text, long-text, and date-picker inputs. You can organize these components across up to 10 screens.

twilio/flows versus whatsapp/flows

twilioflows-versus-whatsappflows page anchor

The twilio/flows Content Template type works well for Flows that don't need complex inputs across multiple screens or endpoint features. You can create twilio/flows in the Content Template Builder or the Content API. Compare with whatsapp/flows that require creating the Flow in the WhatsApp Business Account before sending with the Twilio Content API.

(warning)

Flows limitations

Flows aren't designed to transmit HIPAA Eligible Service or PCI data. Don't use them in workflows that require HIPAA or PCI compliance.

If you need to transmit sensitive information, use Message Redaction. Message Redaction isn't yet compatible with Studio, Proxy Service, or Functions. Don't send Flows that contain sensitive information through these products or services.

Supported options for end users

supported-options-for-end-users page anchor
  • Send a multi-screen form that includes several questions.
  • Collect text input, selections, and picker answers.
  • Include images, links, and clarifying text on each screen.

WhatsApp


Twilio Demo chat showing a response with a helpful link and notification.
Survey form with questions on finding method and favorite number, includes options and a complete button.

To create a Flow in the Content Template Builder:

  1. Create a twilio/flows Content Template.
  2. Submit the content template for approval. Choose the appropriate category (UTILITY or MARKETING).
  3. When you submit the twilio/flows Content Template, Meta publishes the Flow in your WhatsApp Business Account. You can view the publishing status in the Content Template approvals list. You can't use Flows without an approved content template.

ParameterTypeRequiredVariable supportDescription
bodystringYesYesText of the templated message that delivers the Flow. Maximum length: 1,024 characters
subtitlestringNoNoFooter of the message. Maximum length: 1,024 characters
media_urlstringNoYesMedia on the initial Flow message. Supports .png, .jpeg, .mp4, and .pdf. The domain must be static; the path can be variable.
typeenumYesNoFlow category. Valid values: SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY, OTHER
button_textstringYesNoText displayed on the button that starts the Flow.
pagesarrayYesNoDefinitions of each page's components. Maximum: 10 pages.
PropertyTypeRequiredVariable supportDescription
idstringYesNoIdentifier returned in the webhook. Maximum length: 20 characters
titlestringNoNoTitle text that appears above the Flow page.
subtitlestringNoNoSubtitle text that appears at the top of the Flow page.
layoutarrayYesNoComponents shown on the page. Each component must be one of the following: SHORT_TEXT,LONG_TEXT,SINGLE_SELECT,MULTI_SELECT,DATE_PICKER,LIST,TEXT_HEADING,TEXT_SUBHEADING,TEXT_CAPTION,TEXT_BODY,RICH_TEXT,MEDIA,FOOTER

SHORT_TEXT object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be SHORT_TEXT.
textYesstringYes (entire string must be variable or static)Helper text.
labelYesstringYes (entire string must be variable or static)Question displayed to the user.
requiredNoBooleanNoDefaults to false. Whether the user must answer the question.
input_typeNoenumNoDefaults to TEXT. Valid values: TEXT, NUMBER, EMAIL, PASSWORD, PASSCODE, PHONE.

LONG_TEXT object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be LONG_TEXT.
textYesstringYes (entire string must be variable or static)Helper text.
labelYesstringYes (entire string must be variable or static)Question displayed to the user.
requiredNoBooleanNoDefaults to false. Whether the user must answer the question.

SINGLE_SELECT object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be SINGLE_SELECT.
textYesstringYes (entire string must be variable or static)Helper text.
labelYesstringYes (entire string must be variable or static)Question displayed to the user.
optionsYesstringYes (entire string must be variable or static)Stringified array that contains title and id pairs. If you use a variable, the variable must replace the entire string. Example: "[{\"id\":\"ff\",\"title\":\"Friends and family\"}]"
options.titleYesstringYesDisplay title for the option. Can be a variable.
options.idYesstringYesOption identifier returned in the webhook. Can be a variable.

MULTI_SELECT object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be MULTI_SELECT.
textYesstringYes (entire string must be variable or static)Helper text.
labelYesstringYes (entire string must be variable or static)Question displayed to the user.
optionsYesstringYes (entire string must be variable or static)Stringified array that contains title and id pairs. If you use a variable, the variable must replace the entire string. Example: "[{\"id\":\"ff\",\"title\":\"Friends and family\"}]"
options.titleYesstringYesDisplay title for the option. Can be a variable.
options.idYesstringYesOption identifier returned in the webhook. Can be a variable.

DATE_PICKER object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be DATE_PICKER.
labelYesstringYes (entire string must be variable or static)Question displayed to the user.
min_dateYesstringYes (entire string must be variable or static)Start date in YYYY-MM-DD format.
max_dateYesstringYes (entire string must be variable or static)End date in YYYY-MM-DD format.
unavailable_datesYesstringYes (entire string must be variable or static)Stringified array of unavailable dates in YYYY-MM-DD format.
nameNostringYes (entire string must be variable or static)Name of the date picker object.

LIST object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be LIST.
labelYesstringYes (entire string must be variable or static)Question displayed to the user.
optionsYesstringYes (entire string must be variable or static)Stringified array that contains title and id pairs. If you use a variable, the variable must replace the entire string. Example: "[{\"id\":\"ff\",\"title\":\"Friends and family\"}]"
options.titleYesstringYesDisplay title for the option. Can be a variable.
options.idYesstringYesOption identifier returned in the webhook. Can be a variable.

TEXT_HEADING object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be TEXT_HEADING.
textYesstringYes (entire string must be variable or static)Markdown-formatted text. Supports the syntax described in the WhatsApp Components syntax cheat sheet(link takes you to an external page).

TEXT_SUBHEADING object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be TEXT_SUBHEADING.
textYesstringYes (entire string must be variable or static)Markdown-formatted text. Supports the syntax described in the WhatsApp Components syntax cheat sheet(link takes you to an external page).

TEXT_BODY object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be TEXT_BODY.
textYesstringYes (entire string must be variable or static)Markdown-formatted text. Supports the syntax described in the WhatsApp Components syntax cheat sheet(link takes you to an external page).

TEXT_CAPTION object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be TEXT_CAPTION.
textYesstringYes (entire string must be variable or static)Markdown-formatted text. Supports the syntax described in the WhatsApp Components syntax cheat sheet(link takes you to an external page).

RICH_TEXT object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be RICH_TEXT.
text_listYesarrayYes (entire string must be variable or static)Array of Markdown-formatted strings. Supports the syntax described in the WhatsApp Components syntax cheat sheet(link takes you to an external page).

MEDIA object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be MEDIA.
urlYesstringYesImage URL. Supports .jpeg and .png formats.

FOOTER object

PropertyRequiredTypeVariable supportDescription
typeYesenumNoMust be FOOTER.
labelYesstringYesText displayed in the button used to continue the Flow.

Create a twilio/flows Content Template and check its approval status

create-a-twilioflows-content-template-and-check-its-approval-status page anchor
Content Templates API - Create a Flow TemplateLink to code sample: Content Templates API - Create a Flow Template
1
curl -X POST 'https://content.twilio.com/v1/Content' \
2
-H 'Content-Type: application/json' \
3
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN \
4
-d '{
5
"friendly_name": "info_flow",
6
"language": "en",
7
"types": {
8
"twilio/flows": {
9
"body": "Wow do we have something super cool for you! Thanks for your interest. we have a helpful link there too.",
10
"button_text": "See flow",
11
"subtitle": "Finish flow",
12
"pages": [
13
{
14
"id": "id_one",
15
"next_page_id": "id_two",
16
"title": "Page 1",
17
"layout": [
18
{
19
"label": "Name",
20
"type": "SHORT_TEXT",
21
"text": "Question 1",
22
"required": true
23
},
24
{
25
"label": "Email",
26
"type": "SHORT_TEXT",
27
"text": "Question 2",
28
"input_type": "EMAIL"
29
},
30
{
31
"label": "Address",
32
"type": "LONG_TEXT",
33
"text": "Question 3"
34
}
35
]
36
},
37
{
38
"id": "id_two",
39
"next_page_id": null,
40
"title": "Page 2",
41
"subtitle": "Subtitle of Page 2",
42
"layout": [
43
{
44
"label": "How did you find us?",
45
"type": "SINGLE_SELECT",
46
"options": "[{\"id\":\"ff\",\"title\":\"Friends and family\"},{\"id\":\"oo\",\"title\":\"Online\"},{\"id\":\"ip\",\"title\":\"In person\"}]"
47
},
48
{
49
"label": "What is your favorite number?",
50
"type": "MULTIPLE_SELECT",
51
"options": "[{\"id\":\"one\",\"title\":\"one one\"},{\"id\":\"two\",\"title\":\"two two\"},{\"id\":\"three\",\"title\":\"three three\"}]"
52
},
53
{
54
"type": "TEXT_BODY",
55
"text": "Go to [Google](https://www.google.com/) if you have any questions"
56
},
57
{
58
"type": "TEXT_CAPTION",
59
"text": "No seriously, go to [Google](https://www.google.com/) if you have any questions"
60
},
61
{
62
"label": "If other, tell us where",
63
"type": "SHORT_TEXT",
64
"text": "Question 6"
65
}
66
]
67
}
68
],
69
"type": "OTHER"
70
}
71
}
72
}'

Output

1
{
2
"account_sid": "ACXXXXXXXXXXXXX",
3
"date_created": "2025-01-22T22:35:25Z",
4
"date_updated": "2025-01-22T22:35:25Z",
5
"friendly_name": "info_flow",
6
"language": "en",
7
"links": {
8
"approval_create": "https://content.twilio.com/v1/Content/HXXXXXXXXXXXX/ApprovalRequests/whatsapp",
9
"approval_fetch": "https://content.twilio.com/v1/Content/HXXXXXXXXXXXX/ApprovalRequests"
10
},
11
"sid": "HXXXXXXXXXXXX",
12
"types": {
13
"twilio/flows": {
14
"body": "Wow do we have something super cool for you! Thanks for your interest. we have a helpful link there too.",
15
"button_text": "See flow",
16
"media_url": null,
17
"pages": [
18
{
19
"id": "id_one",
20
"layout": [
21
{
22
"input_type": "TEXT",
23
"label": "Name",
24
"name": null,
25
"required": true,
26
"text": "Question 1",
27
"type": "SHORT_TEXT"
28
},
29
{
30
"input_type": "EMAIL",
31
"label": "Email",
32
"name": null,
33
"required": null,
34
"text": "Question 2",
35
"type": "SHORT_TEXT"
36
},
37
{
38
"input_type": null,
39
"label": "Address",
40
"name": null,
41
"required": null,
42
"text": "Question 3",
43
"type": "LONG_TEXT"
44
}
45
],
46
"next_page_id": "id_two",
47
"subtitle": null,
48
"title": "Page 1"
49
},
50
{
51
"id": "id_two",
52
"layout": [
53
{
54
"label": "How did you find us?",
55
"name": null,
56
"options": "[{\"id\":\"ff\",\"title\":\"Friends and family\"},{\"id\":\"oo\",\"title\":\"Online\"},{\"id\":\"ip\",\"title\":\"In person\"}]",
57
"required": null,
58
"type": "SINGLE_SELECT"
59
},
60
{
61
"label": "What's your favorite number?",
62
"name": null,
63
"options": "[{\"id\":\"one\",\"title\":\"one one\"},{\"id\":\"two\",\"title\":\"two two\"},{\"id\":\"three\",\"title\":\"three three\"}]",
64
"required": null,
65
"type": "MULTIPLE_SELECT"
66
},
67
{
68
"text": "Go to [Google](https://www.google.com/) if you have any questions",
69
"type": "TEXT_BODY"
70
},
71
{
72
"text": "No seriously, go to [Google](https://www.google.com/) if you have any questions",
73
"type": "TEXT_CAPTION"
74
},
75
{
76
"input_type": "TEXT",
77
"label": "If other, tell us where",
78
"name": null,
79
"required": null,
80
"text": "Question 6",
81
"type": "SHORT_TEXT"
82
}
83
],
84
"next_page_id": null,
85
"subtitle": "Subtitle of Page 2",
86
"title": "Page 2"
87
}
88
],
89
"subtitle": "Finish flow",
90
"type": "OTHER"
91
}
92
},
93
"url": "https://content.twilio.com/v1/Content/HXXXXXXXXXXXX",
94
"variables": {}
95
}

Fetch an approval status for a twilio/flows Content Template

fetch-an-approval-status-for-a-twilioflows-content-template page anchor

You can check the status of a Content Template submitted for WhatsApp approval:

1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID and Auth Token at twilio.com/console
5
// and set the environment variables. See http://twil.io/secure
6
const accountSid = process.env.TWILIO_ACCOUNT_SID;
7
const authToken = process.env.TWILIO_AUTH_TOKEN;
8
const client = twilio(accountSid, authToken);
9
10
async function listContentAndApprovals() {
11
const contentAndApprovals = await client.content.v1.contentAndApprovals.list({
12
limit: 20,
13
});
14
15
contentAndApprovals.forEach((c) => console.log(c.dateCreated));
16
}
17
18
listContentAndApprovals();

Response

Note about this response
1
{
2
"contents": [],
3
"meta": {
4
"page": 0,
5
"page_size": 10,
6
"first_page_url": "https://content.twilio.com/v1/ContentAndApprovals?PageSize=10&Page=0",
7
"previous_page_url": null,
8
"next_page_url": null,
9
"url": "https://content.twilio.com/v1/ContentAndApprovals?PageSize=10&Page=0",
10
"key": "contents"
11
}
12
}

Send your twilio/flows template

send-your-twilioflows-template page anchor

Sending a twilio/flows Content Template is the same process as sending other Content Templates using the Programmable Messaging APIs. For detailed steps, see Send templates created with the Content Template Builder.

Send a WhatsApp Flow Content Template messageLink to code sample: Send a WhatsApp Flow Content Template message
1
// Download the helper library from https://www.twilio.com/docs/node/install
2
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";
3
4
// Find your Account SID and Auth Token at twilio.com/console
5
// and set the environment variables. See http://twil.io/secure
6
const accountSid = process.env.TWILIO_ACCOUNT_SID;
7
const authToken = process.env.TWILIO_AUTH_TOKEN;
8
const client = twilio(accountSid, authToken);
9
10
async function createMessage() {
11
const message = await client.messages.create({
12
contentSid: "HXaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
13
from: "whatsapp:+14155238886",
14
to: "whatsapp:+15017122661",
15
});
16
17
console.log(message.sid);
18
}
19
20
createMessage();

Response

Note about this response
1
{
2
"account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
3
"api_version": "2010-04-01",
4
"body": "Hello! 👍",
5
"date_created": "Thu, 24 Aug 2023 05:01:45 +0000",
6
"date_sent": "Thu, 24 Aug 2023 05:01:45 +0000",
7
"date_updated": "Thu, 24 Aug 2023 05:01:45 +0000",
8
"direction": "outbound-api",
9
"error_code": null,
10
"error_message": null,
11
"from": "whatsapp:+14155238886",
12
"num_media": "0",
13
"num_segments": "1",
14
"price": null,
15
"price_unit": null,
16
"messaging_service_sid": "MGaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
17
"sid": "SMaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
18
"status": "queued",
19
"subresource_uris": {
20
"media": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages/SMaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Media.json"
21
},
22
"to": "whatsapp:+15017122661",
23
"uri": "/2010-04-01/Accounts/ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Messages/SMaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json"
24
}

Receive a Flow submission

receive-a-flow-submission page anchor

When a user submits a Flow in WhatsApp, Twilio sends a webhook request to the messaging endpoint that you've configured on your WhatsApp sender. The InteractiveData field contains the names and user-submitted values for the Flow's structured data components.

You can also prepare a follow-up experience for the user, such as a message to indicate that you have received the completed flow.

Flow-specific webhook fields

flow-specific-webhook-fields page anchor
FieldDescription
FlowDataRaw data string from the channel provider.
InteractiveDataUser-provided information in JSON format.