Dialogflow (Google Cloud) can act as the intelligence layer behind your WhatsApp Flows — processing submitted data, deciding the next action, and sending a tailored follow-up message. This article walks through two integration modes and provides working code examples.
Integration architecture overview #
Customer submits Flow
↓
WhatsApp Cloud API
↓
Baat webhook receiver
↓
[ two paths ]
Path A — Post-submit (async):
Baat stores data → Journey Builder triggers → calls Dialogflow webhook → sends reply
Path B — data_exchange (sync, during Flow):
Flow calls your endpoint directly → your server calls Dialogflow → returns dynamic screen data
Path A — Post-submit async integration #
This is the simpler and more common path. The Flow completes, Baat receives the submission via webhook, and Journey Builder triggers a follow-up step that calls your Dialogflow agent.
1. Set up a Dialogflow webhook endpoint #
Create an HTTPS endpoint that accepts a POST request from Baat’s Journey Builder. Here is a minimal Node.js (Express) example:
const express = require('express');
const { SessionsClient } = require('@google-cloud/dialogflow');
const app = express();
app.use(express.json());
const client = new SessionsClient();
const projectId = 'your-dialogflow-project-id';
app.post('/dialogflow-webhook', async (req, res) => {
const { contact_phone, flow_response } = req.body;
// flow_response contains the submitted Flow fields as key-value pairs
const sessionPath = client.projectAgentSessionPath(
projectId,
contact_phone.replace('+', '')
);
const request = {
session: sessionPath,
queryInput: {
text: {
text: JSON.stringify(flow_response),
languageCode: 'en-IN',
},
},
};
const [response] = await client.detectIntent(request);
const fulfillmentText = response.queryResult.fulfillmentText;
// Return the reply Baat should send back to the customer
res.json({ reply: fulfillmentText });
});
app.listen(3000);
2. Configure the Journey Builder step #
- In Baat, open your Journey and add a Webhook step after the Flow trigger
- Set the URL to your endpoint (e.g.
https://your-server.com/dialogflow-webhook) - Map Flow response fields to the payload:
contact_phone→{{contact.phone}},flow_response→{{flow.response}} - Add a Send Message step after the webhook using
{{webhook.reply}}as the message body
Path B — data_exchange sync integration #
Use this when you need to return dynamic data to the Flow while the customer is still in it — for example, fetching available appointment slots based on the selected date.
Flow JSON with data_exchange #
{
"type": "Footer",
"label": "Check slots",
"on-click-action": {
"name": "data_exchange",
"payload": {
"selected_date": "${form.appointment_date}",
"service": "${form.service_type}"
}
}
}
Endpoint that handles the data_exchange call #
Meta calls your endpoint directly (not via Baat) with the payload the customer submitted. Your server must respond within 10 seconds with updated screen data.
app.post('/flow-exchange', async (req, res) => {
const { screen, data, flow_token, version } = req.body;
if (screen === 'SCREEN_1') {
const { selected_date, service } = data;
// Fetch available slots from your booking system
const slots = await getAvailableSlots(selected_date, service);
res.json({
screen: 'SCREEN_2',
data: {
available_slots: slots.map(s => ({
id: s.id,
title: s.label // e.g. "10:00 AM", "2:00 PM"
}))
}
});
}
});
data_exchange requests using your Flow’s private_key and the payload is AES-encrypted. You must decrypt the payload and verify the signature before processing. See Meta’s Flows documentation for the decryption helper code.
Dialogflow intent for Flow data #
Create a Dialogflow intent that handles the JSON text you send as the query. Use a fulfillment webhook on the intent to process the structured data and return a personalised response.
// Fulfillment webhook response format (Dialogflow v2)
{
"fulfillmentMessages": [
{
"text": {
"text": [
"Thanks Priya! Your appointment for Spa Treatment on 15 June at 10:00 AM is confirmed. We'll send you a reminder the day before."
]
}
}
],
"outputContexts": [
{
"name": "projects/your-project/agent/sessions/SESSION_ID/contexts/booking-confirmed",
"lifespanCount": 2,
"parameters": {
"service": "spa",
"date": "2024-06-15",
"slot": "10:00"
}
}
]
}
End-to-end flow example #
- Customer receives template message: “Book your appointment — tap below”
- Customer taps the Flow button → sees booking form → selects Spa, 15 June
- Customer taps “Check slots” →
data_exchangefires → your server returns available times - Customer selects 10:00 AM and submits → Flow closes
- Baat receives the webhook with
response_jsoncontaining all submitted fields - Journey Builder fires → calls your Dialogflow webhook endpoint with the data
- Dialogflow returns a confirmation message
- Baat sends the message to the customer: “Your Spa appointment on 15 June at 10:00 AM is confirmed ✅”