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: []