# WhatsApp Flows

WhatsApp Flows is a way to build **structured interactions** for business messaging. With Flows, businesses can define, configure, and customize messages with rich interactions that give customers more structure in the way they communicate.

You can use Flows to **book appointments**, **browse products**, **collect customer feedback**, get new **sales leads**, or anything else where *structured communication* is more natural or comfortable for your customers.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2F8JuHWTllvHYWhgpLb4oC%2F386096957_853106666483066_9214900856885274042_n.png?alt=media&#x26;token=e197e4fe-9644-4ada-9933-5762f82f6c08" alt=""><figcaption></figcaption></figure>

With Flows, you can:

* Present simple input forms (in order to schedule an appointment, for example)
* Create workflows that guide users through multiple screens (for ordering products, for example)
* Create endpoints that exchange data across screens to enable more complex interactions (such as guiding a user through a process with multiple potential outcomes)

## How does it work?

Flows is a feature of the WhatsApp Business Platform that allows you to swiftly develop and deploy native, task-centric workflows on WhatsApp. This results in enhanced interactions between customers and businesses.

With WhatsApp Flows businesses can design, build and customize their own journeys, which can make chatbot and AI agent solutions better, as well as offer end-to-end experiences.

For users, Flows can improve interactions with businesses on WhatsApp, leading to better task completion and fewer drop offs than alternative channels.

For businesses, Flows can improve engagement and completion rates, resulting in improved business outcomes.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FM9bTCRji8YJkCvU4URrb%2Fimage.png?alt=media&#x26;token=877d8d3e-ef52-453f-b06f-a4c7183d3afd" alt=""><figcaption></figcaption></figure>

### Leveraging Flows

Flows is built for form-based use cases. You can create Flows to achieve a range of tasks with your customers, including:

* **Lead generation**
* **Appointment booking**
* **Registration, Sign up, and Sign in**
* **Customer support and feedback**
* **And many more**

{% hint style="info" %}
Meta will continue to expand Flows capabilities to unlock additional use cases in the future. We will keep you updated.&#x20;
{% endhint %}

**Sign Up**

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FukIjPrv6eUMSYulHuSsg%2Fsingup%20flow.png?alt=media&#x26;token=06a2baf1-bf8a-45db-9e18-2b3722887f39" alt=""><figcaption></figcaption></figure>

**Appointment Booking**

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2F5abTnw2q7F2Eiifu6zak%2Fappointmentbooking.png?alt=media&#x26;token=26c431a8-239c-40f0-98ba-2432a4d3adb2" alt=""><figcaption></figcaption></figure>

### How are Flows configured and used? <a href="#how-are-flows-configured-and-used" id="how-are-flows-configured-and-used"></a>

Flows are linked from a CTA in a message. Flows are composed of:

1. **Screens**: When tapping on the Flows CTA in a message, the user will access the initial screen of the Flow. The user can then interact with the Flow to move through multiple screens until completion.
2. **Layouts**: These define how components are presented within a Flow, providing a structured look and feel.
3. **Components**: You can use components to display information, and to create input fields for your users. You can display information with Text, Images, and Embedded links. You can create input fields for your users to complete using Text Inputs, Dropdowns, Checkboxes, Radio Buttons, Opt-in, and Date Pickers.

Flows can be attached and sent as Business Initiated Messages, as well as standard messages. [See Best Practices](#best-practices).

## Getting Started

### Manage Flows through the WhatsApp Manager

Clients can set up Flows directly from the WhatsApp Business Manager UI. To access it, the user must have admin rights to manage the account. The Flows editor can be found under the "Account tools" section under the main menu in Meta's WhatsApp Manager.

{% hint style="info" %}
Find in [Form Builder section](#form-flows) below payload examples with code snippets and explanations of how different Flows come together to create immersive experiences for users.
{% endhint %}

### Manage Flows through the Partner API

Flows can be crafted through our Partner API. We have enabled various endpoints to perform different operations to Flows. Alternatively, your clients can access a Flow builder user interface through the "Account tools" section in Meta's WhatsApp Manager.

Meta has introduced a new flow JSON template **“Book an Appointment”** which you can use as reference when creating a flow in Builder.[ The flow template can be found here.](https://developers.facebook.com/docs/whatsapp/flows/examples/templates#book-an-appointment)

{% hint style="warning" %}
To use the endpoints below, retrieve the `{waba_account_id}` suffix using the[ Partner API](https://docs.360dialog.com/partner/partner-hub/broken-reference). (eg. WABA ID "`120000000000000`" corresponds to the ID "`XxXxxXX`". If the correct ID is not parsed, the API will return an error.
{% endhint %}

## Creating a Flow

To create the flow, please use this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#post-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows). New Flows are created as drafts.

## Updating a Flow

Existing Flows can be updated using the update [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#patch-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id) by providing the Flow ID.

## Updating a Flow's Flow JSON

The individual screens of a Flow are defined through a "Flow JSON", that can be updated through this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#post-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id-assets). To learn more about the Flow JSON definition, follow [this documentation link](https://developers.facebook.com/docs/whatsapp/flows/reference/flowjson).

## Preview a Flow

Flows can be previewed through a public link generated with this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#get-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id-preview). The preview will show what the screens will look like, but will not be interactive. The final screens might render slightly differently for some users.

## Deleting a Flow

While a Flow is in draft status, it can be deleted using this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#delete-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id). Once published, the flow can only be deprecated (see endpoint documentation further down).

## Retrieving a List of Flows

This [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#get-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows) can be used to retrieve a list of flows under a WhatsApp Business Account (WABA).

## Retrieve Flow Details

This [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#get-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id) will return a specified flow's details such as: `id`, `name`, `status`, and validation errors if they exist.&#x20;

## Retrieving a Flow's List of Assets

This [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#get-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id-assets) will return all assets attached to a specified flow.

## Publishing a Flow

Using this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#post-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id-publish), the flow can be published once it meets the design principles of WhatsApp Flows, complies with the [WhatsApp Terms of Service](https://www.whatsapp.com/legal/terms-of-service/?lang=en\&fbclid=IwAR01WJJSzGACTlWO0RapBsbvGaetqSYUjuGvqQruMOdiQC9oYSWpzL2D6Us), the [WhatsApp Business Messaging Policy](https://faq.whatsapp.com/933578044281252?fbclid=IwAR3y5mLksPUePQ-_zwQQjpbb5CWgcdIkt2K1GwoeWx3h-HYeopFO-Y_G5pE), and, if applicable, the [WhatsApp Commerce Policy](https://www.whatsapp.com/legal/commerce-policy/?lang=en\&fbclid=IwAR0EcbGkhz38Fx_b0WdJ05u9x_dUFMSFwlMoasPDkzDyGjx2TiNnpL3ZLVs).

Once published, a flow cannot be modified. Changes to a flow can be done by cloning it and modifying the cloned copy of the Flow.

## Deprecating a Flow

Once a flow is published, it cannot be modified or deleted, but can be marked as deprecated. It is necessary to use this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#post-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-flow_external_id-deprecate).&#x20;

## Migrating Flows <a href="#migrate" id="migrate"></a>

Migrate Flows from one WhatsApp Business Account (WABA) to another. Migration doesn't move the source Flows, it creates copies of them with the same names in the destination WABA.

Please use this [endpoint](https://docs.360dialog.com/partner/partner-api/api-reference/whatsapp-flows#post-api-v2-partners-partner_id-waba_accounts-waba_account_id-flows-migrate_flows) to migrate the flows.&#x20;

**Notes:**

* You can specify specific Flow names to migrate, or choose to migrate all Flows in the source WABA.
* Flows can only be migrated between WABAs owned by the same Meta business.
* If a Flow exists with the same name in the destination WABA, it will be skipped, and the API will return an error message for that Flow. Other Flows in the same request will be copied.
* The migrated Flow will be published if the original Flow is published, otherwise it will be in draft state.
* New Flows under destination WABA will have new Flow IDs.

## Webhooks

If you're subscribed to our Partner API webhooks, you will receive events regarding the statuses and performance of your business's Flows.

Currently, there are webhooks to monitor:

* [Flows status changes](https://docs.360dialog.com/partner/onboarding/webhook-events-and-setup/webhook-events-partner-and-messaging-api#flow-status-change-event)
* [Client error rates](https://docs.360dialog.com/partner/onboarding/webhook-events-and-setup/webhook-events-partner-and-messaging-api#flow-client-error-rate-event)
* [Endpoint error rates](https://docs.360dialog.com/partner/onboarding/webhook-events-and-setup/webhook-events-partner-and-messaging-api#flow-endpoint-error-rate-event)
* [Endpoint channel latencies](https://docs.360dialog.com/partner/onboarding/webhook-events-and-setup/webhook-events-partner-and-messaging-api#flow-endpoint-latency-event)
* [Endpoint channel availability](https://docs.360dialog.com/partner/onboarding/webhook-events-and-setup/webhook-events-partner-and-messaging-api#flow-endpoint-availability-event)

Additional information on the webhook events' payloads can be found in [Meta's developer documentation here](https://developers.facebook.com/docs/whatsapp/flows/reference/qualmgmtwebhook#statuschange).

## Setup Data Channel

In order to later de- and encrypt data passed through WhatsApp Flows, every WhatsApp Business Account (WABA) requires a key pair, which needs to be signed for every phone number sending Flows within the WABA.

### Generating a Key Pair

Generate a public and private RSA key pair by typing in the following command in the terminal/console within your operating system (Note: [OpenSSL](https://www.openssl.org/) needs to be installed):

```bash
openssl genrsa -des3 -out private.pem 2048
```

The generates 2048-bit RSA key pair encrypted with a password you provided. Next, you need to export the RSA public key to a file, which can be accessed within your file system:

```bash
openssl rsa -in private.pem -outform PEM -pubout -out public.pem
```

### Signing the Public Key

For every phone number sending Flows the public key needs to be signed.&#x20;

{% hint style="info" %}
In Postman, when inputting the business public key as a parameter in the Body, select `x-www-form-urlencoded.` Additionally, the  public key needs to be copied in full to work (from `----BEGIN PUBLIC KEY----` and ending with `----END PUBLIC KEY----`).
{% endhint %}

## Set Business Public Key

Use this [endpoint](https://app.gitbook.com/s/-M4sMxKjL6eJRvZn6jeG-887967055/messaging-api/api-reference/encryption#post-whatsapp_business_encryption) to set the business public key.

### Verifying the Public Key

You can verify the public key by retrieving it through the following endpoints.

## Get Business Public Key&#x20;

Use this [endpoint](https://app.gitbook.com/s/-M4sMxKjL6eJRvZn6jeG-887967055/messaging-api/api-reference/encryption#get-whatsapp_business_encryption).&#x20;

### Set up Data Channel Endpoint

When the Flow needs to exchange data with your backend systems, it will make an HTTP request to an endpoint, that you provide. This endpoint needs to be set up so that it can receive and process `POST` requests.&#x20;

With this endpoint you will receive data passed into the Flow by the end user, which you can process e.g. storing it in your database.

Once set up you will share the data channel endpoint URL with the Flow through the Flow's Flow JSON.

Meta has introduced an endpoint example in NodeJS that works with the[ “Book an Appointment” flow JSON end to end,](https://developers.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#-book-an-appointment--endpoint-example) with app secret validation, endpoint error codes, and script to create public/private key. The endpoint code is available on [Github](https://github.com/WhatsApp/WhatsApp-Flows-Tools/tree/main/examples/endpoint/nodejs/book-appointment?fbclid=IwAR1BoPhcUu3EtocdjtbaCxwu3qFMbmK7rsy0nxbas3JTd9E_cFtTcDtrXk8) and [Glitch](https://glitch.com/~whatsapp-flows-appointment).

{% hint style="danger" %}
Since you're the owner of the endpoint you will not be able to validate the payload and verify the origin of the incoming webhook event.
{% endhint %}

#### Implement Encryption/Decryption

The body of each request passed to your endpoint will be encrypted and will have the following format:

```json
{
    encrypted_flow_data: "<ENCRYPTED FLOW DATA>",
    encrypted_aes_key: "<ENCRYPTED_AES_KEY>",
    initial_vector: "<INITIAL VECTOR>"
 }
```

<table><thead><tr><th width="263">Parameter</th><th>Description</th></tr></thead><tbody><tr><td><code>encrypted_flow_data</code></td><td>The encrypted request payload.</td></tr><tr><td><code>encrypted_aes_key</code></td><td>The encrypted 128-bit AES key.</td></tr><tr><td><code>initial_vector</code></td><td>The 128-bit initialization vector.</td></tr></tbody></table>

You can then proceed to decrypt this data using the `encrypted_aes_key`. You can find a detailed example with sample code on this [page of Meta's developer documentation](https://developers.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#request-decryption-and-encryption).

After encryption, the data will have the following format:&#x20;

```json
{
    version: "<VERSION>",
    user_locale: "<LOCALE>",
    action: "<ACTION_NAME>",         // init | back | data_exchange | ping
    screen: "<SCREEN_NAME>",
    data: {                         // JSON of values from screen
        prop_1: "value_1",
        ...
        prop_n: "value_n"
    },
    flow_token: "<FLOW-TOKEN>”
}
```

After processing the decrypted request, you can process the data and craft a response object, which will be encrypted and returned to the Flow. A sample response payload before encryption would follow the format:&#x20;

```json
{
    eg_textfield_variable_1: "sample_Value_1",
    eg_textfield_variable_2: "sample_Value_2"
}
```

The response payload needs to be encrypted using the AES key received in the request and can afterwards be send back as Base64 string. An example on how to encrypt the data can be found in Meta's developer documentation [via this link](https://developers.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#request-decryption-and-encryption).

#### Implement Endpoint Logic

Your endpoint will receive requests in the following cases:

1. User opens the Flow
2. User submits the screen
3. User presses the back button on the screen
4. Error notification request (in case your endpoint returned with invalid content on the previous request)
5. [Periodical health check from WhatsApp](https://developers.facebook.com/docs/whatsapp/flows/guides/healthmonitoring)

For a detailed explanation of all cases and how to process the individual requests, [please refer to Meta's developer documentation for implementing endpoint logic. ](https://developers.facebook.com/docs/whatsapp/flows/guides/implementingyourflowendpoint#implement-endpoint-logic)

#### Webhook Response

Once the Flow closes you will receive a message payload through your messages webhook URL, which will look like the followig example:

```json
{
  "messages": [{
    "context": {
      "from": "16315558151",
      "id": "gBGGEiRVVgBPAgm7FUgc73noXjo"
    },
    "from": "<USER_ACCOUNT_NUMBER>",
    "id": "<MESSAGE_ID>",
    "type": "interactive",
    "interactive": {
      "type": "nfm_reply",
      "nfm_reply": {
        "name": "galaxy_message",
        "response_json": {
            "flow_token": "<FLOW_TOKEN>", 
            "optional_param1": "<value1>",
            "optional_param2": "<value2>"
        }
      }
    },
    "timestamp": "<MESSAGE_SEND_TIMESTAMP>"
  }]
}
```

| Parameter                                                                       | Description                                                                                                                      |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| <p><code>context</code></p><p><em>object</em></p>                               | Context of the message that the user replied to. Context object contains message\_id of flows request message and sender number. |
| <p><code>context.from</code></p><p><em>string</em></p>                          | User's WhatsApp account number                                                                                                   |
| <p><code>context.id</code></p><p><em>string</em></p>                            | Message ID                                                                                                                       |
| <p><code>context.type</code></p><p><em>string</em></p>                          | Always `interactive`                                                                                                             |
| <p><code>interactive.type</code></p><p><em>string</em></p>                      | Always `nfm_reply`                                                                                                               |
| <p><code>interactive.nfm\_reply.name</code></p><p><em>string</em></p>           | `galaxy_message`                                                                                                                 |
| <p><code>interactive.nfm\_reply.response\_json</code></p><p><em>string</em></p> | String that can be parsed to JSON that contains the params business sent like `flow_token`                                       |
| <p><code>timestamp</code></p><p><em>string</em></p>                             | Time of flow response message                                                                                                    |

## Send Flow as Message

#### Via WhatsApp Manager

Admin users can use the Flows Builder, which allows Flows to be sent directly via WhatsApp Manager. The functionality works only with phone numbers registered to Cloud API.&#x20;

#### Via API

You can send a Message with a Flow in a user-initiated conversation using a Message with a Call To Action (CTA). The Flow is triggered when the user taps the CTA button.

To send a message with a Flow, you can use the new type of the Interactive Object named `flow` with the following properties:

#### Interactive message parameters <a href="#interactive-message-parameters" id="interactive-message-parameters"></a>

| Parameter                     | Description                                                                               |
| ----------------------------- | ----------------------------------------------------------------------------------------- |
| `interactive`object           | The interactive message configuration                                                     |
| ↳`type`(required) string      | Value must be `"flow"`.                                                                   |
| ↳`action`(required) object    | 3ff433f692a640a0b6def6ef46ccd515                                                          |
| Parameter                     | Description                                                                               |
| `name`(required) string       | Value must be `"flow"`.                                                                   |
| `parameters`object            |                                                                                           |
| ↳`mode`string                 | The Flow can be in either `draft` or `published` mode.(Default value: `published`)        |
| ↳`flow_message_version`string | Value must be `"3"`.                                                                      |
| ↳`flow_token`string           | Flow token that is generated by the business to serve as an identifier.                   |
| ↳`flow_id`string              | Unique ID of the Flow provided by WhatsApp.                                               |
| ↳`flow_cta`string             | Text on the CTA button. For example: "Signup" Character limit - 20 characters (no emoji). |
| ↳`flow_action`string          | `navigate` or `data_exchange`.(Default value: `navigate`)                                 |
| ↳`flow_action_payload`string  | Required if `flow_action` is `navigate`. Should be omitted otherwise.                     |

Send a message using this [endpoint](https://app.gitbook.com/s/-M4sMxKjL6eJRvZn6jeG-887967055/messaging-api/api-reference/messages#post-messages).

**Sample Request for Cloud API**

```json
{
  "recipient_type": "individual",
  "messaging_product": "whatsapp",
  "to": "whatsapp-id",
  "type": "interactive",
  "interactive": {
    "type": "flow",
    "header": {
      "type": "text",
      "text": "Flow message header"
    },
    "body": {
      "text": "Flow message body"
    },
    "footer": {
      "text": "Flow message footer"
    },
    "action": {
      "name": "flow",
      "parameters": {
        "flow_message_version": "3",
        "flow_token": "AQAAAAACS5FpgQ_cAAAAAD0QI3s.",
        "flow_id": "1",
        "flow_cta": "Book!",
        "flow_action": "navigate",
        "flow_action_payload": {
          "screen": "<SCREEN_NAME>",
          "data": { 
            "product_name": "name",
            "product_description": "description",
            "product_price": 100
          }
        }
      }
    }
  }
}
```

**Sample Response**

```json
{
  "contacts": [
    {
      "Input": "+447385946746",
      "wa_id": "47385946746"
    }
  ],
  "messages": [
    {
      "id": "gHTRETHRTHTRTH-av4Y"
    }
  ],
  "meta": {
    "api_status": "stable",
    "version": "2.44.0.27"
  }
}
```

### Send Flow Template Message <a href="#templatemessages" id="templatemessages"></a>

You can send a [template message](#templatemessages) with a WhatsApp Flow. Only published Flows can be sent this way. [Use the new button type called `FLOW`](https://docs.360dialog.com/partner/messaging/template-messages/template-elements#flows-buttons). Use this type to specify the Flow to be sent with the template message.

First you need[ to create a template](https://docs.360dialog.com/partner/messaging/template-messages#create-new-waba-template). Here is an example request:

```json
{
  "name": "example_template_name",
  "language": "en_US",
  "category": "MARKETING",
  "components": [
    {
      "type": "body",
      "text": "This is a flows as template demo"
    },
    {
      "type": "BUTTONS",
      "buttons": [
        {
          "type": "FLOW",
          "text": "Open flow!",
          "flow_id": "<flow-id>",
          "navigate_screen":  "Flows Json screen name",
          "flow_action": "navigate"
        }
      ]
    }
  ]
}'
```

| Parameter                | Description                                                                       |
| ------------------------ | --------------------------------------------------------------------------------- |
| `buttons`                |                                                                                   |
| ↳`flow_id`string         | The unique ID of a Flow.                                                          |
| ↳`nagivate_screen`string | Required if `flow_action` is `navigate`. The unique ID of the Screen in the Flow. |
| ↳`flow_action`string     | Either `navigate` or `data_exchange`.(Default value: `navigate`)                  |

**Sample Response**

```json
{
  "id": "<template-id>",
  "status": "PENDING",
  "category": "MARKETING"
}
```

{% hint style="success" %}
Ensure that your template passes all required reviews so that `status` is `APPROVED` instead of `PENDING.` See[ Template Statuses](https://docs.360dialog.com/partner/messaging/template-messages#template-statuses).
{% endhint %}

Now you can send a template message with a Flow using the following request:

**Sample Request for Cloud API**

```json
{
  "messaging_product": "whatsapp",
  "recipient_type": "individual",
  "to": "PHONE_NUMBER",
  "type": "template",
  "template": {
    "name": "TEMPLATE_NAME",
    "language": {
      "code": "LANGUAGE_AND_LOCALE_CODE"
    },
    "components": [
      {
        "type": "button",
        "sub_type": "flow",
        "index": "0",
        "parameters": [
          {
            "type": "action",
            "action": {
              "flow_token": "FLOW_TOKEN",   //optional, default is "unused"
              "flow_action_data": {
                 ...
              }   // optional, json object with the data payload for the first screen
            }
          }
        ]
      }
    ]
  }
}
```

**Sample Response**

```json
{
  "messaging_product": "whatsapp",
  "contacts": [
    {
      "input": "<phone-number>",
      "wa_id": "<phone-number>"
    }
  ],
  "messages": [
    {
      "id": "<message-id>"
    }
  ]
}
```

### Receiving Flow Response <a href="#receiving-flow-response" id="receiving-flow-response"></a>

Upon flow completion a response message will be sent to the WhatsApp chat. You will receive it in the same way as you receive all other messages from the user - via message webhook. `response_json` field will contain flow-specific data. See [Webhook Notifications ](https://docs.360dialog.com/partner/onboarding/webhook-events-and-setup/webhook-events-partner-and-messaging-api#flows)for more details.

#### Sending a WhatsApp Flow as user initiated message

```json
{
    "recipient_type": "individual",
    "to": "whatsapp-id",
    "type": "interactive",
    "interactive": {
        "type": "galaxy_message",
        "header": {
            "type": "text",
            "text": "Flow message header"
        },
        "body": {
            "text": "Flow message body"
        },
        "footer": {
            "text": "Flow message footer"
        },
        "action": {
            "name": "",
            "parameters": {
                "flow_message_version": "3",
                "flow_token": "AQAAAAACS5FpgQ_cAAAAAD0QI3s.",
                "flow_id": "1",
                "flow_cta": "Book!",
                "mode": "draft"
            }
        }
    }
}
```

## Best Practices

Here are some guidelines to optimize both the WhatsApp Flows user and developer experience.

### Form Flows&#x20;

#### Feedback Form Flow <a href="#feedback-form-flow" id="feedback-form-flow"></a>

The Feedback Form Flow can be used to collect customer feedback for an experience that includes purchase and delivery of a product. It can also easily be modified to collect other kinds of customer feedback as well.

This example tutorial breaks out the wrapper scaffolding code from the screen code. However, you should combine all the code in these examples using the [Form Builder](https://developers.facebook.com/apps/).

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2Fbm91uOXsdWdEXwBMHufZ%2FScreenshot%202023-11-10%20at%2017.48.33.png?alt=media&#x26;token=eecd174b-ce32-432a-9885-0f5bbf49cb67" alt=""><figcaption></figcaption></figure>

**Wrapper Code**

Include the following code to "wrap" the 2 screens of the Feedback Form (the General Satisfaction Questions screen, and the Rating Questions screen):

```json
{
    "version": "2.1",
    "screens": [
  /* screens we'll define in the next sections */
    ]
}
```

**General Satisfaction Questions Screen:**

```json
{
    "id": "screen_feedback_one",
    "title": "Feedback 1 of 2",
    "layout": {
        "type": "SingleColumnLayout",
        "children": [
            {
                "type": "Form",
                "name": "form_feedback_one",
                "children": [
                    {
                        "type": "TextSubheading",
                        "text": "Would you recommend us to a friend?"
                    },
                    {
                        "type": "RadioButtonsGroup",
                        "label": "Choose one:",
                        "name": "would_recommend",
                        "data-source": [
                            {
                                "id": "1",
                                "title": "Yes"
                            },
                            {
                                "id": "0",
                                "title": "No"
                            }
                        ],
                        "required": true
                    },
                    {
                        "type": "TextSubheading",
                        "text": "How could we do better?"
                    },
                    {
                        "type": "TextArea",
                        "label": "Leave a comment",
                        "required": false,
                        "name": "how_to_do_better_comment"
                    },
                    {
                        "type": "Footer",
                        "label": "Continue",
                        "on-click-action": {
                            "name": "navigate",
                            "next": {
                                "type": "screen",
                                "name": "screen_feedback_two"
                            },
                            "payload": {
                                "would_recommend": "${form.would_recommend}",
                                "how_to_do_better": "${form.how_to_do_better_comment}"
                            }
                        }
                    }
                ]
            }
        ]
    }
}
```

The **Form** component organizes all the input fields on the page and sets the footer CTA to be disabled until all required fields have been completed.

**RadioButtonsGroup** and **TextArea** components are used to get input from the user.

{% hint style="info" %}
You can decide for each input field whether it is required or not using the boolean “required” field.
{% endhint %}

Additional items to note here are the `navigate` action which is designed to navigate to the chosen screen. This example also passes a payload to the next screen - the form collects the `would_recommend` and `how_to_do_better` payload so it can be received as part of the user’s response.

#### Rating Questions Screen <a href="#rating-questions-screen" id="rating-questions-screen"></a>

Once you have the first screen in the Builder and modified as needed, the following can be pasted below it:

```json
{
    "id": "screen_feedback_two",
    "title": "Feedback 2 of 2",
    "data": {
        "would_recommend": {
            "type": "string",
            "__example__": "1"
        },
        "how_to_do_better": {
            "type": "string",
            "__example__": "Have more color options"
        }
    },
    "terminal": true,
    "layout": {
        "type": "SingleColumnLayout",
        "children": [
            {
                "type": "Form",
                "name": "form_feedback_two",
                "children": [
                    {
                        "type": "TextSubheading",
                        "text": "Rate the following: "
                    },
                    {
                        "type": "Dropdown",
                        "label": "Purchase experience",
                        "required": true,
                        "name": "purchase_experience_dropdown",
                        "data-source": [
                            {
                                "id": "5",
                                "title": "★★★★★• Excellent (5/5)"
                            },
                            {
                                "id": "4",
                                "title": "★★★★☆• Good (4/5)"
                            },
                            {
                                "id": "3",
                                "title": "★★★☆☆• Average (3/5)"
                            },
                            {
                                "id": "2",
                                "title": "★★☆☆☆• Poor (2/5)"
                            },
                            {
                                "id": "1",
                                "title": "★☆☆☆☆• Very Poor (1/5)"
                            }
                        ]
                    },
                    {
                        "type": "Dropdown",
                        "label": "Delivery and setup",
                        "required": true,
                        "name": "delivery_dropdown",
                        "data-source": [
                            {
                                "id": "5",
                                "title": "★★★★★• Excellent (5/5)"
                            },
                            {
                                "id": "4",
                                "title": "★★★★☆• Good (4/5)"
                            },
                            {
                                "id": "3",
                                "title": "★★★☆☆• Average (3/5)"
                            },
                            {
                                "id": "2",
                                "title": "★★☆☆☆• Poor (2/5)"
                            },
                            {
                                "id": "1",
                                "title": "★☆☆☆☆• Very Poor (1/5)"
                            }
                        ]
                    },
                    {
                        "type": "Dropdown",
                        "label": "Customer service",
                        "required": true,
                        "name": "customer_service_dropdown",
                        "data-source": [
                            {
                                "id": "5",
                                "title": "★★★★★• Excellent (5/5)"
                            },
                            {
                                "id": "4",
                                "title": "★★★★☆• Good (4/5)"
                            },
                            {
                                "id": "3",
                                "title": "★★★☆☆• Average (3/5)"
                            },
                            {
                                "id": "2",
                                "title": "★★☆☆☆• Poor (2/5)"
                            },
                            {
                                "id": "1",
                                "title": "★☆☆☆☆• Very Poor (1/5)"
                            }
                        ]
                    },
                    {
                        "type": "Footer",
                        "label": "Done",
                        "on-click-action": {
                            "name": "complete",
                            "payload": {
                                "purchase_experience_rating": "${form.purchase_experience_dropdown}",
                                "delivery_rating": "${form.delivery_dropdown}",
                                "customer_service_rating": "${form.customer_service_dropdown}",
                                "would_recommend": "${data.would_recommend}",
                                "how_to_do_better": "${data.how_to_do_better}"
                            }
                        }
                    }
                ]
            }
        ]
    }
}
```

The input data for the screen matches the payload of the `navigate` action from the previous screen, and the `complete` action terminates the flow (the screen is defined as `terminal`).

For each dropdown, the `id` of the option that the user selects is sent as part of the `complete` action payload. In addition, the inputs from the first screen, propagated through the second screen’s data, is also sent as part of the `complete` action payload. This way, the business will receive the entire feedback response from the user on the webhook.

### Testing <a href="#testing" id="testing"></a>

Now that Flow development is complete, you should test it prior to publishing.

To test the Flow before publishing you can:

* Use the interactive preview in the Meta Builder UI

Or

* Send the Flow as a draft message using the Partner API

Once everything has been tested successfully, you can [publish the Flow ](#publishing-a-flow)(via the Builder UI or the API) and start sending [Feedback Form Flows to users.](#feedback-form-flow)

### Designing your Flow

#### Call-to-Actions (CTAs) <a href="#call-to-actions-ctas" id="call-to-actions-ctas"></a>

The CTA should always tell the user what will happen next or what task is being completed on each screen, for example **Confirm booking.**

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FEroF55UCpAjs9Ef4HCES%2Fimage.png?alt=media&#x26;token=203adc40-5338-4b46-acbc-63a5d3c92565" alt=""><figcaption></figcaption></figure>

#### Capitalization <a href="#capitalization" id="capitalization"></a>

Use sentence case on screen titles, headings, and CTAs. Use consistent capitalization throughout each flow.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FUsVQ8LMKYxkcyQsn8B8D%2Fimage.png?alt=media&#x26;token=318a3a2f-71e7-4e76-a757-2addb496629c" alt=""><figcaption></figcaption></figure>

#### Emojis <a href="#emojis" id="emojis"></a>

Always consider the context of the content when using emojis, such as:

* Are they appropriate to use?
* Will they add to the content?
* Do they reflect the business brand?

#### Error Handling <a href="#error-handling" id="error-handling"></a>

* Errors should be clearly communicated to the user, including what has happened and how to resolve it.
* Make sure validation rules are clearly communicated, such as if a user tries to enter a password that is not long enough.
* If the flow is exchanging data with your endpoint and a screen becomes invalid (eg. appointment booking), take the user back to the previous screen rather than ending the flow.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FPDbQRzz43WSxzW5EAMwj%2Fimage.png?alt=media&#x26;token=829d9bb0-672f-4c83-9b6d-115a574ebe1a" alt=""><figcaption></figcaption></figure>

#### Diverging Flows <a href="#diverging-flows" id="diverging-flows"></a>

If you need to create a sub-flow for certain use cases (eg. a forgot password flow), try to keep it to a maximum of 3 screens and always take the user back to the main flow and task at hand.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FKzRNVpZsbDmfhARlQget%2Fimage.png?alt=media&#x26;token=a9e34a18-7a53-4bbe-9d5e-01dc061d6828" alt=""><figcaption></figcaption></figure>

#### Flow Simplicity <a href="#flow-simplicity" id="flow-simplicity"></a>

**Flows shouldn’t be long:** Users should enter flows aiming to complete a task as quickly as possible, with tasks taking no longer than 5 minutes to complete.

**Don’t have more than one task per screen:** Screens with too many tasks may look messy and overwhelm the user. If the flow needs the user to complete multiple tasks, try splitting them up over several screens.

**Don’t use too many components per screen:** Too many components will make your screens look messy and may overwhelm users. It will also take longer to load.'

**Build for caching:** Once a user has completed a screen and moves onto the next, their information will be cached. If there are too many components on a single screen and the user exits the flow, they will lose all of this information, which could be frustrating for users.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FAflNdot55Mdppq99haYk%2Fimage.png?alt=media&#x26;token=29f23ffe-9c5a-42eb-a5b3-d61f7856347c" alt=""><figcaption></figcaption></figure>

#### Form Quality <a href="#form-quality" id="form-quality"></a>

* Always use the right components for specific actions, for example, use the date picker to capture *Date of Booking*.
* If an input requires a lot of text, use the text area component and not the text input.
* Questions and form labels must provide full clarity on what it is asking the user.
* Forms or questions should be logically ordered, for example, first name, last name, etc.
* Forms that are not critical to completing a task should be made optional to the user.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2Ft1DAVwn0LCyTX77lny4U%2Fimage.png?alt=media&#x26;token=ca814a8e-a5e0-4ed5-8377-970512b70aad" alt=""><figcaption></figcaption></figure>

#### Formatting <a href="#formatting" id="formatting"></a>

Ensure that any information is correctly formatted for context, for example, currency symbols, phone numbers, and dates.

#### Grammar and Spelling <a href="#grammar-and-spelling" id="grammar-and-spelling"></a>

* Always check the content in your flows before publishing.
* Ensure you use consistent spelling and capitalization for certain terms.
* Check your grammar such as ensuring sentences use full-stops.

#### Helper Text <a href="#helper-text" id="helper-text"></a>

Helper text should provide clarity for users, eg. the correct format for a phone number, date input, or email address.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2Ffux4xaI7BEtl7D4antEo%2Fimage.png?alt=media&#x26;token=a8e8c9e0-be10-4688-afb4-b078e41f6cd9" alt=""><figcaption></figcaption></figure>

#### Initiation Flow <a href="#initiation-flow" id="initiation-flow"></a>

**The chat should provide clarity**

Users will choose to open a flow based on the clarity of the initiation messages. The exchange should feel conversational, providing context and clear task-focused actions for the user.

**Users want to complete a task**

The CTA should go hand-in-hand with the message content. It should be short and concise, telling the user what task they can expect to complete by opening the flow.

**There should be no surprises**

The first screen of the flow should mirror the action of the CTA. Any deviations from the task at hand will result in a bad experience for the user, resulting in them closing the flow.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FhtgMjxf85n3n8dwGURV3%2Fimage.png?alt=media&#x26;token=fe02b5c2-6472-4173-ac34-f87dea6f917d" alt=""><figcaption></figcaption></figure>

#### Login Screens <a href="#login-screens" id="login-screens"></a>

Some flows may need login screens to complete tasks. However, there are factors to consider when including them in your flows.

**Use only when necessary**

Including a login screen may be off putting for some users, so try to only use them when absolutely necessary. If you do need one, set the expectations for users so it doesn’t come as a surprise.

**Sense of place within flow**

Research has shown that login screens may confuse users within flows. Some people thought screens would take them to an external page, outside of WhatsApp. This may result in users losing their sense of place within the flow.

**Users need to see the benefit of logging in**

The placement of login screens is key. If they are too early in the flow, users will not be motivated to continue. Showing the benefits upfront will make users want to complete the flow. Aim to make the login screen one of the last steps before completion.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FvMZF9J6NeBnWGn99peFu%2Fimage.png?alt=media&#x26;token=da952520-4b12-4906-95b0-08df62d05142" alt=""><figcaption></figcaption></figure>

#### Navigation <a href="#navigation" id="navigation"></a>

* Always set expectations for how long it will take to complete a task, eg. "It should only take a few minutes to complete."
* Help the user know where they are in the flow by using short, concise action-oriented screen titles, such as "Book appointment."
* Use screen titles to show progress where possible, eg. "Question 1 of 3."
* End the flow with a summary screen, especially if there have been multiple steps, so users can review and complete the task with clarity.

#### Opt-in <a href="#opt-in" id="opt-in"></a>

* It should be clear what the user is consenting to.
* You should try to include a "Read more" CTA which links to the relevant information, eg. Terms and Conditions.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FPGOfO2cq6WN658lFrcDV%2Fimage.png?alt=media&#x26;token=57793bb6-fb95-444d-8d63-3eb8334917a0" alt=""><figcaption></figcaption></figure>

#### Options and lists <a href="#options-and-lists" id="options-and-lists"></a>

* Keep it simple, try not to use more than 10 options per screen.
* Only use dropdown options when there are 8 or more options.
* Use a radio button if there is only one selection to make.
* Use checkboxes if the user can select multiple options.
* Always make the option at the top of the list the default selection.

#### Termination Flow <a href="#termination-flow" id="termination-flow"></a>

**Set expectations**

The last screen should clearly tell the user what will happen when they end the flow. They will also want confirmation of their actions. Sending a summary message should make the user feel reassured.

**Bookend your flows**

The termination messages should provide the user with clarity and a sense of completion. They should know what they have done, what the next steps are, and who they can get in touch with if they have any questions or if they want to edit or cancel a task.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2FpuRvBxzx6PUAC5bXCv5i%2Fimage.png?alt=media&#x26;token=87907e5f-c3fb-42fa-8ca5-4cd152cc6c82" alt=""><figcaption></figcaption></figure>

#### Trust and Support <a href="#trust-and-support" id="trust-and-support"></a>

* The business logo (profile photo) should be simple and identifiable in the footer so the user knows and trusts the flow.
* Add a CTA within your flow that enables your users to get in touch when needed. This can also be done in follow-up messages once the user has completed the flow.

<figure><img src="https://2248475362-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuyAl2S0lSHJaNDXJHo7A%2Fuploads%2Fe0ZjFd7B8UhlJgQUEIny%2Fimage.png?alt=media&#x26;token=5ba0a67b-3dbd-465c-89be-111ade4745e8" alt=""><figcaption></figcaption></figure>

#### Writing Content <a href="#writing-content" id="writing-content"></a>

* Make sure your content follows a simple, clear hierarchy using a heading, body and captions
* Do not repeat content unnecessarily, for example:
  * “Complete registration"
  * "Complete registration below"
