openapi: 3.0.0
info:
title: Flows
version: "5.0"
description: |
Use the Flows endpoints to list your flows, view the details of a single flow (including its
versions and stages), and change a flow's status. These
endpoints read and control existing flows; they do not create them.
The Flows endpoints are in early access. MoEngage enhances these endpoints based on feedback during this period, but does not make breaking changes.
The API exposes the following endpoints:
- `POST /v5/flows/search` — paginated listing with filters (status, delivery type, tags,
teams, name, creator, creation-date range).
- `GET /v5/flows/{flow_id}` — single flow detail. Use the optional `version_no` query
parameter to view a specific version; the default is the last published version, or
the draft if none is published.
- `GET /v5/flows/{flow_id}/versions/{version_id}` — the details of a flow as it was in a
specific version, identified by its ID.
- `PATCH /v5/flows/{flow_id}/status` — lifecycle transition (`pause`, `resume`, `stop`,
`retire`) or the flow-level `archive` / `unarchive` toggle.
**Conventions**
- IDs are 24-character identifiers. `flow_id` identifies the flow; `version_id` identifies one
of its versions.
- Every successful response uses the format `{response_id, type, data}`. The `response_id`
echoes the `request_id` you send; if you omit it, the server uses the first 12 characters
of a system-generated UUID.
- Dates and times are in ISO 8601 UTC format (`YYYY-MM-DDThh:mm:ssZ`).
- The search endpoint returns results one page at a time. To fetch the next page, send the
`next_cursor` from the previous response back as the `cursor` value.
**Permissions**
Flows reuse the `campaigns` permission for scope checks. Read endpoints require the
`campaigns:view` permission; the status endpoint requires `campaigns:create_manage`.
**Status Model**
Public flow statuses: `DRAFT`, `ACTIVE`, `SCHEDULED`, `PAUSED`, `STOPPED`, `COMPLETED`,
`RETIRED`, `UNDER_REVIEW`, `REJECTED`. `archived` is a separate boolean flag
(it spans every version of the flow), not a status.
**Rate Limits**: The rate limits are at the workspace level. A maximum of 10 requests per second,
100 requests per minute, and 6,000 requests per hour are allowed per workspace for the search,
get, and status endpoints.
Breaching any limit rejects the request with a `429` response.
servers:
- url: https://api-{dc}.moengage.com
variables:
dc:
default: "01"
description: >
MoEngage data center identifier. Replace it with the number assigned to your account,
such as 01 (US), 02 (EU), 03 (India), 04 (US), 05 (Singapore), or 06 (Indonesia).
For example, https://api-01.moengage.com. Data center 101 is not supported.
enum: ["01", "02", "03", "04", "05", "06"]
security:
- basicAuth: []
paths:
/v5/flows/search:
post:
operationId: searchFlows
summary: Search Flows
description: |
This API returns a paginated list of flows matching your filters. Send filters in the
request body — all are optional and combine with AND. Multi-valued filters (`status`,
`delivery_type`, `tags`) match ANY of the supplied values, and archived flows are excluded
unless `include_archived` is `true`.
Each response includes a `next_cursor`. To get the next page, send that value as the
`cursor` in your next request. Sorting is not supported in this version; results are
returned most recent first. Your API key must have the `campaigns:view` permission (see
[Authentication](/api/flows/flows-overview#authentication)).
x-mint:
content: |
#### Rate Limits
The rate limits are at the workspace level. A maximum of 10 requests per second, 100 requests per minute, and 6,000 requests per hour are allowed per workspace.
tags:
- Flows
security:
- basicAuth: []
parameters:
- $ref: '#/components/parameters/XMoeTenantId'
- $ref: '#/components/parameters/XMoeRequestIdHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FlowSearchRequest'
examples:
defaultPage:
summary: First page, default filters
value:
limit: 20
byStatus:
summary: Filter by status
value:
status: [ACTIVE, PAUSED]
limit: 20
byDeliveryType:
summary: Filter by delivery type
value:
delivery_type: [EVENT_TRIGGERED, PERIODIC]
limit: 20
byName:
summary: Name substring match
value:
name: test
limit: 20
byCreationDateRange:
summary: Creation-date range
value:
creation_start_time: "2025-01-01T00:00:00Z"
creation_end_time: "2026-12-31T23:59:59Z"
limit: 20
nextPage:
summary: Fetch the next page with a cursor
value:
limit: 20
cursor: eyJpZCI6ICI2OWYxZGU4NGY5ZTQwMWEyZDdkOWE5MzEifQ==
responses:
'200':
description: Flows matching the filters.
headers:
X-MOE-Request-Id:
$ref: '#/components/headers/XMoeRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/FlowSearchResponse'
example:
response_id: abc-701
type: flow
data:
flows:
- flow_id: 69f1de84f9e401a2d7d9a931
name: Welcome journey
status: ACTIVE
archived: false
delivery_type: EVENT_TRIGGERED
active_version_name: Version 2
tags: [onboarding]
created_at: "2026-01-05T10:00:00Z"
updated_at: "2026-02-01T09:30:00Z"
published_at: "2026-01-06T08:00:00Z"
created_by: agent@example.com
has_more: true
next_cursor: eyJpZCI6ICI2OWYxZGU4NGY5ZTQwMWEyZDdkOWE5MzEifQ==
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalServerError'
/v5/flows/{flow_id}:
get:
operationId: getFlow
summary: Get a Single Flow
description: |
This API returns everything about one flow — its settings, targeting, conversion
goal, and full stage-by-stage structure — typically after you find its `flow_id` with Search
Flows. Use the optional `version_no` query parameter to view a specific version; by default,
you get the last published version, or the draft if the flow was never published. Your API
key must have the `campaigns:view` permission (see the
[Authentication](/api/flows/flows-overview#authentication) section).
x-mint:
content: |
#### Rate Limits
The rate limits are at the workspace level. A maximum of 10 requests per second, 100 requests per minute, and 6,000 requests per hour are allowed per workspace.
tags:
- Flows
security:
- basicAuth: []
parameters:
- $ref: '#/components/parameters/FlowId'
- name: version_no
in: query
required: false
description: >
View a specific version of the flow by its version number (the trailing integer of
the version name, for example `Version 3` becomes `3`). When omitted, the last
published version is returned, or the draft if none is published. A non-integer value
returns `400`; a number that does not exist for this flow returns `404`.
schema:
type: integer
minimum: 1
- $ref: '#/components/parameters/XMoeTenantId'
- $ref: '#/components/parameters/XMoeRequestIdHeader'
responses:
'200':
description: Flow found.
headers:
X-MOE-Request-Id:
$ref: '#/components/headers/XMoeRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/FlowDetailResponse'
example:
response_id: abc-100
type: flow
data:
flow_id: 69f1de84f9e401a2d7d9a931
name: Welcome journey
status: ACTIVE
archived: false
delivery_type: EVENT_TRIGGERED
tags: [onboarding]
created_at: "2026-01-05T10:00:00Z"
updated_at: "2026-02-01T09:30:00Z"
published_at: "2026-01-06T08:00:00Z"
created_by: agent@example.com
published_by: agent@example.com
global_control_group_enabled: false
active_version_name: Version 2
versions:
- version_id: 69f1de84f9e401a2d7d9a931
version_name: Version 1
version_no: 1
status: RETIRED
- version_id: 7a02ef95f9e401a2d7d9aa42
version_name: Version 2
version_no: 2
status: ACTIVE
settings:
control_group:
enabled: false
frequency_capping:
ignore: false
ignore_and_count: false
bypass_dnd: false
attribution:
click_track_hours: 24
impression_track_hours: 24
conversion_goal_details:
primary_goal:
event: Purchase
goal_name: Made a purchase
secondary_goals: []
revenue_tracking: true
revenue_attribute: amount
revenue_currency: USD
exit_on_conversion: false
structure:
nodes:
- stage_id: n1
type: TRIGGER
sub_type: EVENT
parent_stage_id: null
child_stage_ids: [n2]
label: App Opened
config:
schedule:
delivery: one_time
start_time: "2026-01-06T08:00:00Z"
timezone: Asia/Kolkata
segmentation:
audience_type: all_users
- stage_id: n2
type: ACTION
sub_type: EMAIL
parent_stage_id: n1
child_stage_ids: []
label: Welcome email
config:
campaign_id: 69f1de84f9e401a2d7d9a999
channel: EMAIL
campaign_name: Welcome email
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalServerError'
/v5/flows/{flow_id}/versions/{version_id}:
get:
operationId: getFlowVersion
summary: Get a Specific Version of a Flow
description: |
This API returns a flow exactly as it was in a past version — for example,
to audit what was live before a recent change. If you already have the version number
rather than its ID, use `version_no` on Get a Single Flow instead. The `version_id` must
belong to `flow_id`, otherwise the API returns `404`. Your API key must have the
`campaigns:view` permission (see the
[Authentication](/api/flows/flows-overview#authentication) section).
x-mint:
content: |
#### Rate Limits
The rate limits are at the workspace level. A maximum of 10 requests per second, 100 requests per minute, and 6,000 requests per hour are allowed per workspace.
tags:
- Flows
security:
- basicAuth: []
parameters:
- $ref: '#/components/parameters/FlowId'
- name: version_id
in: path
required: true
description: >
The 24-character ID of a specific version of the flow. Must belong to `flow_id`.
schema:
type: string
pattern: '^[a-f0-9]{24}$'
- $ref: '#/components/parameters/XMoeTenantId'
- $ref: '#/components/parameters/XMoeRequestIdHeader'
responses:
'200':
description: Flow version found.
headers:
X-MOE-Request-Id:
$ref: '#/components/headers/XMoeRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/FlowDetailResponse'
example:
response_id: abc-102
type: flow
data:
flow_id: 69f1de84f9e401a2d7d9a931
name: Welcome journey
status: RETIRED
archived: false
delivery_type: EVENT_TRIGGERED
tags: [onboarding]
created_at: "2026-01-05T10:00:00Z"
updated_at: "2026-01-20T09:30:00Z"
published_at: "2026-01-06T08:00:00Z"
created_by: agent@example.com
published_by: agent@example.com
global_control_group_enabled: false
active_version_name: Version 1
versions:
- version_id: 7a02ef95f9e401a2d7d9aa42
version_name: Version 1
version_no: 1
status: RETIRED
settings:
control_group:
enabled: false
frequency_capping:
ignore: false
ignore_and_count: false
bypass_dnd: false
attribution:
click_track_hours: 24
impression_track_hours: 24
conversion_goal_details:
primary_goal:
event: Purchase
goal_name: Made a purchase
secondary_goals: []
revenue_tracking: true
revenue_attribute: amount
revenue_currency: USD
exit_on_conversion: false
structure:
nodes:
- stage_id: n1
type: TRIGGER
sub_type: EVENT
parent_stage_id: null
child_stage_ids: [n2]
label: App Opened
config:
schedule:
delivery: one_time
start_time: "2026-01-06T08:00:00Z"
timezone: Asia/Kolkata
segmentation:
audience_type: all_users
- stage_id: n2
type: ACTION
sub_type: EMAIL
parent_stage_id: n1
child_stage_ids: []
label: Welcome email
config:
campaign_id: 69f1de84f9e401a2d7d9a999
channel: EMAIL
campaign_name: Welcome email
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalServerError'
/v5/flows/{flow_id}/status:
patch:
operationId: updateFlowStatus
summary: Update Flow Status
description: |
This API changes a flow's lifecycle state. It validates the requested transition against the flow's
current state before applying it; an invalid transition returns `409`. Your API key must have the
`campaigns:create_manage` permission (see the [Authentication](/api/flows/flows-overview#authentication) section).
x-mint:
content: |
Lifecycle actions (`pause`, `resume`, `stop`, `retire`) accept an optional `version_no` and act on that
version (default: the active version). `archive` / `unarchive` apply to the whole flow and reject a `version_no`.
| Action | Allowed from | Result |
| --- | --- | --- |
| `pause` | `ACTIVE`, `SCHEDULED` | `PAUSED` |
| `resume` | `PAUSED` | `ACTIVE` |
| `stop` | `ACTIVE`, `SCHEDULED`, `PAUSED`, `RETIRED` | `STOPPED` |
| `retire` | `ACTIVE`, `PAUSED` | `RETIRED` |
| `archive` | `PAUSED`, `STOPPED`, `COMPLETED` (and not already archived) | sets `archived=true` |
| `unarchive` | any archived flow | sets `archived=false` |
#### Rate Limits
The rate limits are at the workspace level. A maximum of 10 requests per second, 100 requests per minute, and 6,000 requests per hour are allowed per workspace.
tags:
- Flows
security:
- basicAuth: []
parameters:
- $ref: '#/components/parameters/FlowId'
- name: Idempotency-Key
in: header
required: true
description: Client-generated UUID v4. Reusing the same key replays the original response instead of re-applying the transition.
schema:
type: string
format: uuid
- $ref: '#/components/parameters/XMoeTenantId'
- $ref: '#/components/parameters/XMoeRequestIdHeader'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/FlowStatusRequest'
examples:
pause:
summary: Pause an active flow
value:
action: pause
updated_by: agent@example.com
archive:
summary: Archive a flow
value:
action: archive
updated_by: agent@example.com
responses:
'200':
description: Flow status updated.
headers:
X-MOE-Request-Id:
$ref: '#/components/headers/XMoeRequestId'
content:
application/json:
schema:
$ref: '#/components/schemas/FlowStatusResponse'
example:
response_id: abc-200
type: flow
data:
flow_id: 69f1de84f9e401a2d7d9a931
status: PAUSED
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/ForbiddenStatusWrite'
'404':
$ref: '#/components/responses/NotFound'
'409':
description: The requested action is not a valid transition from the flow's current status.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-409
error:
code: BAD_REQUEST
target: action
message: "Cannot resume a flow that is not paused."
details: []
'429':
$ref: '#/components/responses/RateLimited'
'500':
$ref: '#/components/responses/InternalServerError'
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
description: |
Authentication is done via Basic Auth. This requires a base64-encoded string of your credentials in the format 'username:password'.
- **Username**: Use your MoEngage workspace ID (also known as the App ID). You can find it in the MoEngage dashboard at **Settings** > **Account** > **APIs** > **Workspace ID (earlier app id)**.
- **Password**: On your MoEngage workspace, navigate to **Settings** → **Account** → **API keys** and click **Create new key**. The tab lists every API surface (Data, Segmentation, Push, Email, Campaigns, Templates, and more) and exposes per-resource actions. Flows reuse the Campaigns permissions — ensure the **View** checkbox (for the read endpoints) and the **Create & Manage** checkbox (for Update Flow Status) are selected.
For more information on authentication and getting your credentials, refer to [Getting your credentials](/api/introduction#getting-your-credentials).
Send the value in the `Authorization` header as `Basic` followed by Base64-encoding of `appkey:apisecret` (workspace ID and API key).
headers:
XMoeRequestId:
description: Echoed request ID. If you do not provide one, the server generates it.
schema:
type: string
XMoeRequestIdEchoed:
description: Echoes the X-MOE-Request-Id that you supplied.
schema:
type: string
parameters:
FlowId:
name: flow_id
in: path
required: true
description: >
The 24-character ID of the flow. This must be the flow's own ID, not a version ID;
passing a version ID returns `400`.
schema:
type: string
pattern: '^[a-f0-9]{24}$'
example: "6a3b09c938da57c8f5838880"
XMoeRequestIdHeader:
name: X-MOE-Request-Id
in: header
required: false
description: >
Client-supplied trace ID. The server echoes it in the `X-MOE-Request-Id` response header
and in `response_id`. If you omit it, the server generates one.
schema:
type: string
XMoeTenantId:
name: X-MOE-Tenant-ID
in: header
required: false
description: >
Identifies the tenant/workspace making the request. Optional — when omitted, the
workspace is resolved from the Basic Auth credentials in the `Authorization` header.
schema:
type: string
XMoeRequestIdRequired:
name: X-MOE-Request-Id
in: header
required: true
description: >
Request ID that you supply. It is echoed in the `X-MOE-Request-Id` response header and in
`response_id`.
schema:
type: string
VersionName:
name: version_name
in: query
required: false
description: Flow version to query. Defaults to the active version.
schema:
type: string
enum:
- "Version 1"
- "Version 2"
- "All Versions"
example: "Version 2"
schemas:
FlowStatusEnum:
type: string
description: >
Public lifecycle status of a flow (or of a specific version), independent of the
`archived` flag.
enum:
- DRAFT
- ACTIVE
- SCHEDULED
- PAUSED
- STOPPED
- COMPLETED
- RETIRED
- UNDER_REVIEW
- REJECTED
DeliveryTypeEnum:
type: string
description: Indicates how users enter the flow.
enum:
- ONE_TIME
- PERIODIC
- ON_FLOW_EXIT
- EVENT_TRIGGERED
- BUSINESS_EVENT_TRIGGERED
FlowSearchRequest:
type: object
description: >
Filters for listing flows. All filters are optional and combine with AND. Enum filters
(`status`, `delivery_type`) are case-insensitive.
properties:
request_id:
type: string
description: Optional if supplied via the `X-MOE-Request-Id` header; echoed in `response_id`.
status:
type: array
description: Keeps only flows whose status is in this set.
items:
$ref: '#/components/schemas/FlowStatusEnum'
delivery_type:
type: array
description: Keeps only flows that have one of these delivery types.
items:
$ref: '#/components/schemas/DeliveryTypeEnum'
tags:
type: array
description: The tag names to match; flows that carry any of them are kept.
items:
type: string
teams:
type: array
description: >
Team names. Required when the Flows-teams feature is enabled for the workspace —
omitting it or sending an empty list returns `400 VALIDATION_FAILED`
("teams is required when the team feature is enabled"). When the feature is off,
sending `teams` is rejected with `400`.
items:
type: string
name:
type: string
description: Matches flows whose name contains this text, case-insensitively.
created_by:
type: array
description: The email addresses of the flow creators to filter by.
items:
type: string
format: email
creation_start_time:
type: string
description: The inclusive lower bound on the creation time, in ISO 8601 UTC format.
example: "2025-01-01T00:00:00Z"
creation_end_time:
type: string
description: The inclusive upper bound on the creation time, in ISO 8601 UTC format. It must be on or after `creation_start_time`.
example: "2026-12-31T23:59:59Z"
include_archived:
type: boolean
default: false
description: '`false` (default) excludes archived flows; `true` returns both archived and non-archived.'
limit:
type: integer
minimum: 1
maximum: 100
default: 20
description: The number of results returned per page.
cursor:
type: string
description: The cursor from a previous page's `next_cursor`. Omit for the first page.
FlowSummary:
type: object
description: One flow as it appears in a search or list result.
required: [flow_id]
properties:
flow_id:
type: string
pattern: '^[a-f0-9]{24}$'
description: The ID of the flow.
name:
type: string
description: Display name of the flow.
status:
allOf:
- $ref: '#/components/schemas/FlowStatusEnum'
description: Lifecycle status of the flow's active version.
archived:
type: boolean
default: false
description: Whether the flow is archived (spans all versions). Independent of `status`.
delivery_type:
$ref: '#/components/schemas/DeliveryTypeEnum'
active_version_name:
type: string
nullable: true
description: Display name of the active version, such as `Version 3`.
tags:
type: array
description: Tag names attached to the flow.
items:
type: string
created_at:
type: string
nullable: true
description: ISO 8601 UTC creation time.
updated_at:
type: string
nullable: true
description: ISO 8601 UTC last-update time of the active version.
published_at:
type: string
nullable: true
description: ISO 8601 UTC publish time of the active version; null if never published.
created_by:
type: string
nullable: true
description: Email of the flow's creator.
FlowSearchResponse:
type: object
required: [response_id, type, data]
properties:
response_id:
type: string
description: Echo of the `request_id` that you supplied, or a generated ID when absent.
type:
type: string
enum: [flow]
data:
type: object
required: [flows, has_more]
properties:
flows:
type: array
items:
$ref: '#/components/schemas/FlowSummary'
has_more:
type: boolean
description: Whether another page exists after this one.
next_cursor:
type: string
nullable: true
description: Cursor to pass as `cursor` for the next page. Null on the last page.
FlowVersion:
type: object
description: One version of a flow, as listed in a detail response's `versions`.
properties:
version_id:
type: string
pattern: '^[a-f0-9]{24}$'
version_name:
type: string
description: Display name, such as `Version 2`.
version_no:
type: integer
nullable: true
description: The numeric version, parsed from the trailing integer of `version_name`.
status:
allOf:
- $ref: '#/components/schemas/FlowStatusEnum'
description: This version's own lifecycle status.
FlowNode:
type: object
description: One stage of the flow, such as a trigger, an action, a wait, a condition, or a split.
required: [stage_id]
properties:
stage_id:
type: string
description: Unique ID of this node within the flow.
type:
type: string
description: The category of this node.
enum: [TRIGGER, ACTION, CONTROL, CONDITION, SPLIT, BRANCH]
sub_type:
type: string
description: >
Public sub-type within `type`:
`TRIGGER` — `EVENT`, `BUSINESS_EVENT`, `ONE_TIME`, or `PERIODIC`;
`ACTION` — a channel (`EMAIL`, `SMS`, `PUSH`, `WHATSAPP`, `IN_APP`, `ONSITE`,
`CONNECTOR`, `CARDS`, `FB_AUDIENCE`, `GOOGLE_ADS`, `CONNECTED_APPS`) or `NBA`;
`CONTROL` — `EXIT`, `WAIT_FOR_TIMER`, or `GO_TO`;
`SPLIT` — `AB_SPLIT`, `IPO`, or `CONDITIONAL_SPLIT`;
`CONDITION` — `HAS_DONE_EVENT`, `ON_EMAIL_CLICK`, `ON_EMAIL_OPEN`, or `CHECK_USER_ATTRIBUTE`;
`BRANCH` mirrors its parent split or condition.
parent_stage_id:
type: string
nullable: true
description: ID of the parent node, or null for the entry (`TRIGGER`) node.
child_stage_ids:
type: array
description: IDs of the immediate downstream nodes.
items:
type: string
label:
type: string
nullable: true
description: Human-readable label shown in the flow builder.
config:
type: object
additionalProperties: true
description: >
Type-specific configuration. The shape depends on `type` and `sub_type`; null-valued
fields are omitted. The example below shows a `CONDITION` node's config. For the config
shape of every node type (`CONDITION`, `BRANCH`, `SPLIT`, `ACTION`/`NBA`, and `CONTROL`),
see [Flow structure and nodes](/api/flows/flows-overview#flow-structure-and-nodes).
example:
condition:
filter_operator: and
filters:
- action_name: MOE_EMAIL_CLICK
executed: true
filter_type: actions
execution:
count: 1
type: atleast
attributes:
filter_operator: and
filters: []
wait:
duration: 5
unit: mins
evaluation_timing: SINCE_PREVIOUS_STAGE
FlowDetailData:
allOf:
- $ref: '#/components/schemas/FlowSummary'
- type: object
description: >
Full single-flow detail. Carries every `FlowSummary` field plus the version list,
publish metadata, settings, attribution, conversion goal, and its stages.
properties:
active_version_name:
type: string
nullable: true
description: Display name of the flow's active version.
versions:
type: array
nullable: true
description: All versions of the flow, sorted by `version_no`. Null for a single-version flow.
items:
$ref: '#/components/schemas/FlowVersion'
published_by:
type: string
nullable: true
description: Email of the user who published this version.
approvers:
type: array
nullable: true
description: Approver emails (CAF), when set.
items:
type: string
global_control_group_enabled:
type: boolean
default: false
description: Whether the global control group is enabled for this flow.
settings:
$ref: '#/components/schemas/FlowSettings'
attribution:
$ref: '#/components/schemas/FlowAttribution'
conversion_goal_details:
$ref: '#/components/schemas/ConversionGoalDetails'
structure:
type: object
description: The stages of the flow.
properties:
nodes:
type: array
items:
$ref: '#/components/schemas/FlowNode'
FlowSettings:
type: object
description: Flow-level settings. Null-valued fields may be omitted.
properties:
control_group:
type: object
properties:
enabled:
type: boolean
nullable: true
description: Whether a control group (holdout) is enabled for this flow.
percentage:
type: number
nullable: true
description: The percentage of users held out as a control group.
stickiness:
type: boolean
nullable: true
description: Keeps a user in the same control or treatment assignment across re-entry.
frequency_capping:
type: object
properties:
ignore:
type: boolean
nullable: true
description: Ignores frequency capping for this flow.
ignore_and_count:
type: boolean
nullable: true
description: Ignores capping but still counts sends toward it.
inactive_eviction_days:
type: integer
nullable: true
description: The number of days of user inactivity after which a user is evicted from the flow.
on_failure:
type: string
nullable: true
description: Defines the behavior when a stage fails.
bypass_dnd:
type: boolean
nullable: true
description: Sends messages even during the workspace Do-Not-Disturb window.
FlowAttribution:
type: object
nullable: true
description: >
Click and impression attribution windows for the flow, derived from its channel action
nodes. Null when no channel action declares them.
properties:
click_track_hours:
type: integer
nullable: true
impression_track_hours:
type: integer
nullable: true
ConversionGoalDetails:
type: object
nullable: true
description: Conversion-goal configuration from the entry node. Null when the flow has no conversion goal.
properties:
primary_goal:
type: object
properties:
event:
type: string
nullable: true
description: The name of the conversion-goal event.
goal_name:
type: string
nullable: true
secondary_goals:
type: array
items:
type: object
properties:
event:
type: string
nullable: true
goal_name:
type: string
nullable: true
revenue_tracking:
type: boolean
description: Whether revenue is attributed for the primary goal.
revenue_attribute:
type: string
nullable: true
description: Event attribute carrying the revenue amount. Present only when `revenue_tracking` is true.
revenue_currency:
type: string
nullable: true
description: Currency of the revenue attribute. Present only when `revenue_tracking` is true.
exit_on_conversion:
type: boolean
nullable: true
description: Whether a user exits the flow once they convert.
FlowDetailResponse:
type: object
required: [response_id, type, data]
properties:
response_id:
type: string
type:
type: string
enum: [flow]
data:
$ref: '#/components/schemas/FlowDetailData'
FlowStatusRequest:
type: object
required: [action, updated_by]
properties:
action:
type: string
description: The lifecycle operation to apply. `publish` is not available in this phase.
enum: [pause, resume, stop, retire, archive, unarchive]
version_no:
type: integer
minimum: 1
description: >
Optional. For lifecycle actions (`pause`, `resume`, `stop`, `retire`), acts on this
version (default: the active version). Rejected for `archive` / `unarchive`.
updated_by:
type: string
format: email
description: Email of the user performing the action. Recorded in the audit log.
request_id:
type: string
description: Optional if supplied via the `X-MOE-Request-Id` header; echoed in `response_id`.
FlowStatusResponse:
type: object
required: [response_id, type, data]
properties:
response_id:
type: string
type:
type: string
enum: [flow]
data:
type: object
required: [flow_id, status]
properties:
flow_id:
type: string
description: The flow acted on.
status:
$ref: '#/components/schemas/FlowStatusEnum'
ErrorResponse:
type: object
required: [error, response_id]
properties:
response_id:
type: string
error:
type: object
required: [code, message]
properties:
code:
type: string
enum:
- VALIDATION_FAILED
- BAD_REQUEST
- NOT_FOUND
- UNAUTHORIZED
- FORBIDDEN
- RATE_LIMITED
- INTERNAL_ERROR
message:
type: string
target:
type: string
description: The component or field the error relates to.
details:
type: array
description: One entry per failing check.
items:
type: object
properties:
target:
type: string
message:
type: string
responses:
BadRequest:
description: >
The request failed validation — for example, a bad filter value, a malformed cursor, a
non-integer `version_no`, an invalid date range, or a `flow_id` that is actually a version
ID.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-101
error:
code: VALIDATION_FAILED
target: request
message: One or more request parameters failed validation.
details:
- target: request
message: Check the request parameters and try again.
Unauthorized:
description: Authentication failed (missing or invalid credentials).
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-101
error:
code: UNAUTHORIZED
message: Invalid or missing credentials.
details: []
Forbidden:
description: You do not have the required permission for this operation.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-450
error:
code: FORBIDDEN
target: permission
message: You do not have the required permission for this operation.
details:
- target: permission
message: "Required permission: campaigns:view"
ForbiddenStatusWrite:
description: You do not have the required permission for this operation.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-450
error:
code: FORBIDDEN
target: permission
message: You do not have the required permission for this operation.
details:
- target: permission
message: "Required permission: campaigns:create_manage"
NotFound:
description: The flow (or the requested version) does not exist in this workspace.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-100
error:
code: NOT_FOUND
target: flow
message: Flow not found.
details:
- target: flow_id
message: Flow not found.
RateLimited:
description: Per-app rate limit exceeded. Retry after the interval indicated in the `Retry-After` header.
headers:
Retry-After:
schema:
type: integer
description: Seconds until the rate-limit window resets.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-101
error:
code: RATE_LIMITED
message: Rate limit exceeded for app key.
details: []
InternalServerError:
description: Unhandled server-side failure.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
response_id: abc-101
error:
code: INTERNAL_ERROR
message: Internal server error.
details: []