Flow JSON Specification & Validation Engine
Flow JSON is the declarative schema developed by Meta to programmatically define screen layouts, interactive components, dynamic data bindings, and screen transition rules for WhatsApp Flows.
SMSPort embeds an automated, real-time validation engine (flow-validator.ts) that enforces Meta Flow v7.3 standards, preventing invalid configurations from breaking at runtime or failing Meta Graph API asset uploads.
1. Top-Level Flow JSON Structure
A valid Flow JSON payload must adhere to the following top-level format:
{
"version": "7.3",
"data_api_version": "3.0",
"routing_model": {
"SCREEN_A": ["SCREEN_B"],
"SCREEN_B": []
},
"screens": [
{
"id": "SCREEN_A",
"title": "Welcome",
"data": {},
"layout": {
"type": "SingleColumnLayout",
"children": []
}
},
{
"id": "SCREEN_B",
"title": "Confirmation",
"terminal": true,
"layout": {
"type": "SingleColumnLayout",
"children": [
{
"type": "Footer",
"label": "Complete Flow",
"on-click-action": { "name": "complete" }
}
]
}
}
]
}Top-Level Property Specifications
| Property | Type | Requirement | Description |
|---|---|---|---|
version |
string | Required | The Flow JSON compiler version. Always specify "7.3" for modern flows. Versions < 6.0 are deprecated. |
data_api_version |
string | Optional | Must be "3.0" when communicating with dynamic Flow endpoints. |
routing_model |
object | Required for Endpoints | A map defining all permissible forward state transitions between screens. |
screens |
array | Required | Array containing between 1 and 50 screen definitions. |
data_channel_uri |
string | Deprecated | Deprecated as of Flow v3.0. Endpoints must be configured via API metadata (endpointUri), not in JSON. |
2. Screen Specifications & Constraints
Each object in the screens array represents an independent view within the Flow:
{
"id": "APPOINTMENT_DETAILS",
"title": "Select Time",
"terminal": false,
"refresh_on_back": false,
"data": {
"slots": {
"type": "array",
"__example__": [
{ "id": "10am", "title": "10:00 AM" },
{ "id": "2pm", "title": "02:00 PM" }
]
}
},
"layout": {
"type": "SingleColumnLayout",
"children": []
}
}Critical Screen Constraints:
- Screen ID Identifier:
- Must be uppercase alphanumeric with underscores:
^[A-Z0-9_]+$. - Must be globally unique across the Flow.
- Reserved Identifier:
SUCCESSis reserved for client-side termination. Using"id": "SUCCESS"is strictly forbidden by Meta.
- Must be uppercase alphanumeric with underscores:
- Mandatory Terminal Screen:
- Every Flow must define at least one terminal exit point (
terminal: true,success: true, or an action with"name": "complete"). - Footer Requirement: Meta mandates that terminal screens must contain a
Footercomponent to allow users to exit cleanly.
- Every Flow must define at least one terminal exit point (
- Component Limits:
- Maximum of 50 components per screen.
- Layout container
typemust strictly be"SingleColumnLayout".
3. Routing Model & Directed Graph Integrity
The routing_model acts as a security and integrity whitelist governing screen transitions:
"routing_model": {
"STEP_1": ["STEP_2"],
"STEP_2": ["SUMMARY"],
"SUMMARY": []
}Routing Rules Enforced by SMSPort:
- No Self-Referencing: Screens cannot route to themselves (
STEP_1: ["STEP_1"]triggersROUTING_SELF_REFERENCE). - Target Verification: Every destination screen listed in an array must exist in
screens(ROUTING_DESTINATION_NOT_FOUND). - Action Parity: Any navigation button with
"action": "navigate"must target a screen declared in the current screen's routing list. - Forward-Only: Backwards navigation is handled automatically by the native WhatsApp client header back button; do not add backwards edges to the routing model.
4. Field Uniqueness & Variable Binding
To avoid data collisions when form responses are sent back to your server:
- Unique Field Names: Every interactive input (
TextInput,TextArea,Dropdown,RadioButtonsGroup,CheckboxGroup,ChipsSelector,DatePicker,CalendarPicker,OptIn) must have a uniquenameattribute within its screen. - Dynamic Variable References:
${data.<key>}: Binds to server-provided or mockdatadeclared on the screen.${form.<field_name>}: References user-entered values from active form fields.- SMSPort's validator automatically checks if
${data.xyz}references exist in the screen'sdatadictionary, alerting you to undefined references before runtime.