The Flows endpoints are in early access. MoEngage enhances these endpoints based on feedback during this period, but does not make breaking changes.
Endpoints
The Flows API is a collection of the following endpoints:- Search Flows: Lists flows with filters and keyset pagination.
- Get a Single Flow: Returns a single flow, and optionally a specific version with
version_no. - Get a Specific Version of a Flow: Returns a flow as it was in a specific version, addressed by its version ID.
- Update Flow Status: Pauses, resumes, stops, retires, archives, or unarchives a flow.
Authentication
Authenticate with Basic Auth using your MoEngage Workspace ID (App ID) as the username and your API Key as the password. You can find these in the MoEngage dashboard at Settings > Account > APIs. Flows reuse the Campaigns permissions. Enable the matching checkboxes on your API key:- View (
campaigns:view) for the read endpoints — Search Flows, Get a Single Flow, and Get a Specific Version of a Flow. - Create & Manage (
campaigns:create_manage) for Update Flow Status.
X-MOE-Tenant-ID header (your Workspace ID) is optional — when omitted, the workspace is resolved from the Basic Auth credentials in the Authorization header. You can also send an optional X-MOE-Request-Id.
For more information on authentication and getting your credentials, refer to Getting your credentials.
Requests go to your data center’s host, https://api-{dc}.moengage.com. For the full list of data centers and their identifiers, refer to Data Centers.
Conventions
- IDs are raw 24-character ObjectIds.
flow_idaddresses the flow;version_idaddresses one version. - Every successful response uses the envelope
{response_id, type, data}. - Datetimes are ISO 8601 UTC (
YYYY-MM-DDThh:mm:ssZ). - Search results are paginated. Each response includes a
next_cursor. To get the next page, send that value as thecursorparameter in your next request.
Flow Structure and Nodes
Get a single flow and Get a specific version of a flow return the flow’s stages indata.structure.nodes[]. Each entry is a node (one stage of the flow). Nodes share a common envelope and carry a config object whose shape depends on the node’s type and sub_type.
Every node includes these fields:
The sections below describe the
config shape for each node type. Field sets are documented from real flows; a node may include additional keys not shown here.
Condition Nodes
ACONDITION node evaluates a condition and routes users down one of two paths. child_stage_ids always has exactly two entries: index 0 is the path taken when the condition matches, and index 1 is the path when it does not.
config fields:
condition— the rule to evaluate. It reuses the same filter grammar as a trigger’s event filter (filter_operator,filters[], and per-filteraction_name,executed,execution.type/execution.count, and nestedattributes).wait— how long to wait before evaluating, as{ duration, unit }.unitismins,hours, ordays.evaluation_timing— when the condition is evaluated:ON_ENTRYorSINCE_PREVIOUS_STAGE.
sub_type values: HAS_DONE_EVENT, ON_EMAIL_CLICK, ON_EMAIL_OPEN.
Two-way CONDITION node
Branch Nodes
ABRANCH node represents a single arm of a parent CONDITION or SPLIT. Its sub_type mirrors the parent’s sub_type, and its single child is the next real stage on that path. Its config depends on the parent:
- Arm of a
CONDITION(explicit YES/NO pattern):configis{ "outcome": "YES" }or{ "outcome": "NO" }. - Arm of a
CONDITIONAL_SPLIT:configcarriesbranch_index(0-based) and, for a conditioned arm,branch_type: "main"with aconditionobject. The catch-all arm usesbranch_type: "default"and has nocondition. - Arm of an
AB_SPLITorIPO:configcarriesnameandpercentage.
BRANCH arms of a CONDITIONAL_SPLIT
Split Nodes
ASPLIT node splits users into more than two paths (or two paths for IPO). Its child_stage_ids map one-to-one to BRANCH children. config fields depend on the sub_type:
CONDITIONAL_SPLITroutes each user down a branch based on a condition. Itsconfigcarriesbranch_order(the ordered list of childstage_ids),evaluation_timing, andwait.AB_SPLITdivides users randomly by percentage. Itsconfig.branches[]lists each arm as{ stage_id, name, percentage }.IPO(Intelligent Path Optimizer) uses the sameconfig.branches[]asAB_SPLIT, plus anoptimization_metric(observed value:ENGAGEMENT). The ordering comes frombranches[], so there is nobranch_order.
Multi-way CONDITIONAL_SPLIT
AB_SPLIT
Action Nodes
AnACTION node sends a campaign or selects a channel. For a channel send (EMAIL, PUSH, SMS, WHATSAPP, and so on), config carries campaign_id, channel, and campaign_name.
The NBA (Next Best Action) sub_type is an ACTION node — it occupies the same slot as channel sends, not a separate node type. Its config fields:
channels[]— one entry per eligible channel, each{ channel, stage_id, campaign_id }.stage_idreferences a siblingACTIONnode (of that channel) that owns the actual send; the NBA node itself holds no campaign content.fallback_channel— the channel used when the best channel can’t be determined (observed value:PUSH).best_time_to_send— the send-time strategy (observed shape:{ "default_time": "SEND_IMMEDIATELY" }).
ACTION node with NBA sub_type
Control Nodes
ACONTROL node manages flow control and path convergence. Observed sub_type values:
EXIT— exits the user from the flow.WAIT_FOR_TIMER— holds the user for a set duration.GO_TO— routes the user to a shared downstream stage (config.target_stage_id), used to re-converge parallel branches.
FAQs
Can I create or edit flows with these endpoints?
Can I create or edit flows with these endpoints?
No, this isn’t supported. You can search, read, and change the status of existing flows.
How do I enroll users into a flow through the API?
How do I enroll users into a flow through the API?
You do not enroll users directly. For event-triggered flows, use the Track Event API — a user enters the flow when a tracked event matches the flow’s entry condition. For business-event-triggered flows, use the Trigger Business Event API. Periodic flows are audience-driven and do not support API enrollment.
What is the difference between flow_id and version_id?
What is the difference between flow_id and version_id?
flow_id identifies the flow. version_id identifies one of its versions. To read a specific version, either pass version_no on Get a single flow, or call Get a specific version of a flow with the version_id.Which status changes can I make?
Which status changes can I make?
You can
pause, resume, stop, retire, archive, and unarchive a flow. Each change is validated against the flow’s current status; an invalid change returns a 409. Publish isn’t available.What permissions do I need?
What permissions do I need?
The read endpoints (search, get flow, get version) require the
campaigns:view permission. The status endpoint requires the campaigns:create_manage permission.