Skip to Content

WhatsApp Flows

WhatsApp Flows are multi-screen interactive forms Meta hosts on your behalf — appointment booking, lead capture, surveys, order confirmation. You define the screens as JSON, attach the flow to a MARKETING / UTILITY template (or send it directly as an interactive message), and Meta renders it in the WhatsApp client.

1. Create a flow

POST /api/v25.0/{WABA_ID}/flows Authorization: Bearer pk_live_<your-key> Content-Type: application/json

Request body

{ "name": "lead_capture_v1", "categories": ["LEAD_GENERATION"] }
FieldNotes
nameInternal name, ≤ 200 chars, unique per WABA
categoriesArray. One or more of SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY, OTHER

Response — 200

{ "id": "1234567890123456" }

The returned id is the flow-id used by every other endpoint below.

2. List flows

GET /api/v25.0/{WABA_ID}/flows Authorization: Bearer pk_live_<your-key>

Response — 200

{ "data": [ { "id": "1234567890123456", "name": "lead_capture_v1", "status": "DRAFT", "categories": ["LEAD_GENERATION"], "validation_errors": [] } ], "paging": { "cursors": { "before": "...", "after": "..." } } }

status is one of DRAFT, PUBLISHED, DEPRECATED, BLOCKED, THROTTLED.

3. Get one flow

GET /api/v25.0/{FLOW_ID}?fields=id,name,status,categories,validation_errors,preview Authorization: Bearer pk_live_<your-key>

The preview field returns a temporary preview URL you can open in a browser to walk through the flow without sending it.

4. Update flow metadata

POST /api/v25.0/{FLOW_ID} Authorization: Bearer pk_live_<your-key> Content-Type: application/json
{ "name": "lead_capture_v2", "categories": ["LEAD_GENERATION", "CONTACT_US"] }

5. Upload flow JSON (the screens)

POST /api/v25.0/{FLOW_ID}/assets Authorization: Bearer pk_live_<your-key> Content-Type: multipart/form-data

Form fields

FieldNotes
nameflow.json
asset_typeFLOW_JSON
fileThe flow definition. See Meta’s Flow JSON schema for shape

Response — 200

{ "success": true, "validation_errors": [] }

If validation_errors is non-empty, the JSON has schema problems (unknown component, missing route, invalid endpoint binding) and the flow stays in DRAFT with the errors attached.

6. Publish

POST /api/v25.0/{FLOW_ID}/publish Authorization: Bearer pk_live_<your-key>

Response — 200

{ "success": true }

Once published, you can send the flow via Send Messages using type: "interactive" + interactive.type: "flow":

{ "messaging_product": "whatsapp", "to": "+919999999999", "type": "interactive", "interactive": { "type": "flow", "body": { "text": "Tap to book" }, "action": { "name": "flow", "parameters": { "flow_message_version": "3", "flow_id": "1234567890123456", "flow_cta": "Book now", "flow_action": "navigate", "flow_action_payload": { "screen": "WELCOME_SCREEN", "data": { "user_name": "Aditya" } } } } } }

7. Deprecate / delete

POST /api/v25.0/{FLOW_ID}/deprecate DELETE /api/v25.0/{FLOW_ID} Authorization: Bearer pk_live_<your-key>

Deprecating keeps the flow visible to existing recipients but blocks new sends. Delete removes it entirely; only DRAFT flows can be deleted.

Webhook responses

When a user completes a flow, the response screen-data lands at your configured webhook URL as a normal message webhook with type: "interactive" and interactive.type: "nfm_reply". The response_json field is the user’s submitted data.

Errors

StatusExample
400Meta returns 400 for malformed flow JSON, unsupported component, etc.
401{ "success": false, "message": "unauthorized" }
403{ "success": false, "message": "id does not belong to your account" }
404{ "success": false, "message": "id not found" }

cURL — full lifecycle

# 1) Create FLOW_ID=$(curl -X POST \ "https://api.splashifypro.com/api/v25.0/$WABA_ID/flows" \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "lead_capture_v1", "categories": ["LEAD_GENERATION"] }' \ | jq -r .id) # 2) Upload JSON curl -X POST \ "https://api.splashifypro.com/api/v25.0/$FLOW_ID/assets" \ -H "Authorization: Bearer $SPLASHIFY_API_KEY" \ -F "name=flow.json" \ -F "asset_type=FLOW_JSON" \ -F "file=@/path/to/flow.json" # 3) Publish curl -X POST \ "https://api.splashifypro.com/api/v25.0/$FLOW_ID/publish" \ -H "Authorization: Bearer $SPLASHIFY_API_KEY"

Notes

  • Flow versioning is implicit — uploading new flow.json to an existing flow replaces the screens. To roll back, keep your old JSON in source control and re-upload.
  • Endpoint-bound flows require your own HTTPS endpoint that responds to navigation events. Configure the endpoint URL in flow.json’s routing_model. Meta’s request signing uses your business public key; rotate that key via POST /api/v25.0/{PHONE_NUMBER_ID}/whatsapp_business_encryption.
  • Preview URLs expire after ~10 minutes — fetch a fresh one each time you need to inspect.