Skip to main content

Troubleshooting: WhatsApp Flow submissions missing, empty, or stuck in the funnel

A WhatsApp Flow problem shows up one of four ways: a submitted Flow never appears on the contact’s profile, the funnel shows completions but the submissions list stays empty, recipients receive a Flow they cannot open, or the dashboard submissions panel and the API list disagree. This page covers the Flow-submissions layer only. If the problem is the Flow’s runtime itself — the screen render fails, the encrypted exchange aborts mid-Flow — the Flow execution failures page is the right playbook; if the WABA or template is down, work Troubleshoot a WhatsApp connection first.
Publish state, phone-number quality, and CDP routing are Meta’s or your own tenant’s levers — Orbit relays the submission from Meta’s webhook and writes the row. The CDP event contract and the contact write-back rules are in WhatsApp channels — Flow Submissions.

Symptom map

Work the table top-down — it covers the failure modes that account for nearly every Flow-submission incident.

Check contact resolution first

landed_in_cdp only flips true when the submission resolves to a contact. The CDP event lives on the contact record, so a submission arrives as a row with contact_id: null only when the submitter’s phone number did not match any contact in your tenant. To confirm which side of that branch you are on, fetch one row:
Read contact_id and landed_in_cdp on each row:
  • contact_id is null. The submitter’s phone number did not match any contact. Create the contact (or add the phone number to an existing contact), then the next submission from that sender resolves and lands in the CDP.
  • contact_id set, landed_in_cdp false. The CDP event emission has not finished for that submission yet. Allow for ingestion lag (seconds to a few minutes behind live), then re-read the row. If the lag clears and landed_in_cdp still shows false, the write failed — the escalation payload at the bottom of this page includes the submission id for that row.
Verify on the contact page: open the contact in the dashboard and find the whatsapp_flow_submitted event in their event feed. The event carries the raw answers payload, so a Journeys trigger on whatsapp_flow_submitted fires the same as any other behavioral event.
Rows recorded before the CDP wiring shipped show landed_in_cdp: false regardless of resolution. A false on an old row does not mean the event write failed.

Funnel shows completions but the list is empty

The funnel and the submissions list measure different things:
  • Funnel — counts screen-to-screen transitions. A recipient who reaches the final screen appears in the funnel even if they never tapped Submit on the completion screen.
  • Submissions list — a row appears only when a recipient completes the final screen of the Flow.
To match the two, compare the funnel’s “final screen completions” step count with the submissions list on the same window. A funnel spike on a specific screen with no submissions points to that screen blocking completion (a validation error, a missing Next action, or a dropped encrypted exchange — the Flow execution failures page covers those).

Recipients can’t open the Flow

Three reasons account for most open failures:
  1. Publish state. A Flow saved as DRAFT cannot be opened by recipients — the WhatsApp client refuses it. Publish the Flow in Meta Business Manager. The Flow status is visible on the Flow’s record alongside the template list.
  2. Phone-number quality. Meta blocks sends from phone numbers with a RED quality rating. If your send returned success but the recipient cannot open the message, the WABA phone is usually the blocker — the WABA’s phone-quality rating is on the channel page (Settings → Channels → WhatsApp → Phone number), and the recovery path is in Troubleshoot a WhatsApp connection.
  3. Category restrictions. Flows in the restricted categories (regulated goods, health, adult themes) require explicit Meta allow-listing. Without it the send succeeds but the client refuses to open. The category rules are in WhatsApp content policy.
If the send failed outright with WHATSAPP_* error code, the fix is the earlier-level playbooks, not this page.

Dashboard panel vs the API

The dashboard submissions panel on the Flow’s detail page reads the same list endpoint as the API. Divergence is a client-side effect, not two different queries:
  • Pagination. The panel requests a page size smaller than the API’s limit=200 max; a raw call with a larger limit returns older rows the panel has not rendered. Page the API with offset to mirror the panel.
  • Window defaults. The API defaults to the trailing 90 days for since/until; if you pass an explicit since, that window overrides the default. A call against a window the panel is not showing will disagree with the panel either way. Match the windows first, then compare counts.
The API /api/v1/whatsapp/flows/{flowId}/submissions list endpoint is the source of truth for what persisted. If the API and the dashboard disagree even after the windows and pagination are matched, escalate with the request id from the response header.

What not to do

  • Do not treat a null contact_id as a bug to retry. The contact resolution is not a blocking step; the row persists either way. Fix the contact record so the next submission resolves.
  • Do not page past limit=200. The API caps limit at 200. Loop over offset for longer windows; large values are rejected rather than silently truncated.
  • Do not send a DRAFT Flow to recipients. Until the Flow is published in Meta Business Manager, recipients receive a message they cannot open. Check the publish state before a campaign.
  • Do not test a Flow on a phone-quality RED number. Sends fail silently; work the phone-quality recovery first.

Escalation payload

If you have worked the page and a completed submission still does not land in the CDP, email whatsapp-support@devotel.io with these three items so we can trace the ingestion without a back-and-forth:
  1. The Flow id (Meta’s flow id, or the dashboard URL id).
  2. The submission id of one row stuck at landed_in_cdp: false.
  3. The contact resolution branchcontact_id null vs set — so we skip the resolution-angle probe and start on the event ingestion path.

See also