Getting Started
WhatsApp Flow Endpoint is an HTTPS endpoint that receives requests from our service when users interact with Flows. Our service will make requests to Flows with Endpoints to achieve dynamic Flow loading or to obtain user operation data.
Basic Requirements
- HTTPS Endpoint: Must be a publicly accessible HTTPS URL
- POST Method: Endpoint must support POST requests
- Response Time: Must respond within 15 seconds
- JSON Processing: Handle plain JSON request and response payloads
- Security: HTTPS ensures secure communication
Request Flow Overview
- User interacts with WhatsApp Flow
- Our service makes request to your endpoint
- Your endpoint processes the business logic
- Your endpoint returns JSON response
- Flow continues based on your response
Implement Endpoint Logic
Your endpoint needs to handle three main types of requests, distinguished by the action
field:
Health Check Request
Health check requests are used to verify that your endpoint is working properly.
Request Payload Structure
{
"action": "ping"
}
Processing Logic
- When receiving
action: "ping"
, simply return status confirmation - No complex business logic processing required
- Mainly used by Meta platform to verify endpoint availability
Response
{
"data": {
"status": "active"
}
}
Response Description:
status
: Always return"active"
to indicate the endpoint is working properly
Error Notification Request
When errors occur during Flow execution, our service sends error notification requests.
Request Payload Structure
{
"version": "<VERSION>",
"flow_token": "<FLOW-TOKEN>",
"action": "data_exchange | INIT",
"data": {
"error": "<ERROR-KEY>",
"error_message": "<ERROR-MESSAGE>"
}
}
Processing Logic
- Log error information for debugging and monitoring
- Perform appropriate cleanup operations based on error type
- Acknowledge receipt of error notification
Response
{
"data": {
"acknowledged": true
}
}
Response Description:
acknowledged
: Always returntrue
to indicate error notification has been acknowledged- This is a confirmation response that you have processed the error notification
Data Exchange Request
Data exchange requests are the most important request type, containing user interaction data within the Flow.
Request Payload Structure
{
"version": "3.0",
"screen": "SCREEN_ID",
"action": "INIT|data_exchange|BACK",
"data": {
// Screen data, structure depends on specific Flow design
"field1": "value1",
"field2": "value2",
// ... other fields
},
"flow_token": "FLOW_TOKEN_STRING"
}
Field Description:
Field | Required | Type | Description |
---|---|---|---|
version | Yes | string | Must be set to "3.0" |
screen | Yes | string | Current screen ID. If action is set to INIT or BACK, this field may not be populated. Note: "SUCCESS" is a reserved name and cannot be used by any screens. |
action | Yes | string | Operation type: • INIT : If the request is triggered when opening the Flow• data_exchange : If the request is triggered when submitting the screen• BACK : If the request is triggered when pressing "back" |
data | Yes | object | Screen form data or user input as JSON object. If action is set to INIT or BACK, this field may not be populated. |
flow_token | Yes | string | Flow session token generated by you as part of the Flow message |
Processing Logic
Handle different action
types accordingly:
INIT Operation:
if ("INIT".equals(action)) {
// Initialize Flow, return initial screen data
return initializeFlow(screen, data, flowToken);
}
data_exchange Operation:
if ("data_exchange".equals(action)) {
// Process user submitted data, return next step operation
return processDataExchange(screen, data, flowToken);
}
BACK Operation:
if ("BACK".equals(action)) {
// Handle user going back to previous screen
return handleBackNavigation(screen, data, flowToken);
}
Response
The response structure for data exchange requests should follow this format:
Standard Response Structure:
{
"screen": "SCREEN_NAME",
"data": {
"key1": "value1",
"key2": "value2"
}
}
Example Response for Navigation:
{
"screen": "NEXT_SCREEN",
"data": {
"user_name": "John Doe",
"selected_option": "premium_plan",
"total_amount": 99.99
}
}
Response for Validation Errors:
{
"screen": "CURRENT_SCREEN",
"data": {
"error_message": "Please check your input and try again"
}
}
Flow Completion Response:
To trigger flow completion, send the following response:
{
"screen": "SUCCESS",
"data": {
"extension_message_response": {
"params": {
"flow_token": "<FLOW_TOKEN>",
"optional_param1": "<value1>",
"optional_param2": "<value2>"
}
}
}
}
Flow Completion Parameters:
Parameter | Required | Type | Description |
---|---|---|---|
screen | Yes | string | Must be set to "SUCCESS" to trigger flow completion |
data.extension_message_response.params | Yes | object | A JSON object with data included in the flow completion message |
data.extension_message_response.params.flow_token | Yes | string | Flow token generated by business signifying a session or user flow |
Additional optional parameters | No | any | Can be included and will be forwarded to the response message webhook |
As a result, the flow will be closed and a flow response message will be sent to the chat.
Implementation Example
Here's a general example of how to handle different request types in your endpoint:
@PostMapping("/flow-endpoint")
public ResponseEntity<Map<String, Object>> handleFlowRequest(
@RequestBody Map<String, Object> request) {
String action = (String) request.get("action");
String screen = (String) request.get("screen");
Map<String, Object> data = (Map<String, Object>) request.get("data");
String flowToken = (String) request.get("flow_token");
Map<String, Object> response = new HashMap<>();
switch (action) {
case "ping":
response.put("data", Map.of("status", "active"));
break;
case "INIT":
response = handleFlowInitialization(screen, data, flowToken);
break;
case "data_exchange":
response = handleDataExchange(screen, data, flowToken);
break;
case "BACK":
response = handleBackNavigation(screen, data, flowToken);
break;
default:
response.put("screen", screen);
response.put("data", Map.of("error_message", "Unknown action: " + action));
}
return ResponseEntity.ok(response);
}
private Map<String, Object> handleFlowInitialization(String screen, Map<String, Object> data, String flowToken) {
// Initialize flow with default data
Map<String, Object> response = new HashMap<>();
response.put("screen", "WELCOME_SCREEN");
response.put("data", Map.of("welcome_message", "Welcome to our service!"));
return response;
}
private Map<String, Object> handleDataExchange(String screen, Map<String, Object> data, String flowToken) {
// Process user input and determine next screen
Map<String, Object> response = new HashMap<>();
// Example: validate user input
if (data.containsKey("email") && isValidEmail((String) data.get("email"))) {
response.put("screen", "CONFIRMATION_SCREEN");
response.put("data", Map.of("user_email", data.get("email")));
} else {
response.put("screen", screen); // Stay on current screen
response.put("data", Map.of("error_message", "Please enter a valid email address"));
}
return response;
}
private Map<String, Object> handleBackNavigation(String screen, Map<String, Object> data, String flowToken) {
// Handle back navigation
Map<String, Object> response = new HashMap<>();
response.put("screen", "PREVIOUS_SCREEN");
response.put("data", new HashMap<>());
return response;
}
Important Notes
- HTTPS Security: Ensure your endpoint uses HTTPS for secure communication
- Error Handling: Properly handle various exception scenarios
- Response Time: Ensure response within 15 seconds
- Logging: Log key operations for debugging and monitoring
- Data Validation: Validate received data format and content
- JSON Processing: Handle JSON parsing and serialization correctly
By correctly implementing these logics, your endpoint will be able to successfully handle various WhatsApp Flow requests and provide users with a smooth interactive experience.