> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Duplicate journey

> Copy an existing journey into a new draft. You can apply overrides to the copy in the same request.

<Info>
  **Beta.** The Journeys API is in beta. Endpoints and response fields can still change.
</Info>

## Overview

Copy the [Journey](/docs/en/journeys-overview) named in the path. The copy is a new journey in the `draft` state. The source does not change.

<Note>
  The copy is always a draft, whatever state the source is in. If you duplicate an active or archived journey, the copy has `started_at` and `archived_at` set to `null`. To activate the copy, use the [Update journey](/reference/update-journey) API or the [OneSignal dashboard](/docs/en/managing-journeys).
</Note>

***

## How to use this API

Authenticate with your [App API Key](/docs/en/keys-and-ids). The key must have permission to create journeys. To find the `id` of the source journey, use the [View journeys](/reference/view-journeys) API. You can also open the journey in the dashboard and read the `id` from the URL.

```http theme={null}
POST /apps/{app_id}/journeys/{id}/duplicate
```

The body is optional. If you send no body, the copy matches the source. The copy then takes a derived name, which is the name of the source plus a suffix.

### What the copy inherits

The copy carries the `description`, `audience`, `nodes`, `early_exit`, and `reentry_rules` of the source.

* `name`: the copy takes the name of the source plus ` (Copy)`. If the result is longer than the 300 character limit, the source part is truncated to fit. If you duplicate a copy, the suffix is added again rather than counted.
* `nodes`: nodes and branches get new `id` values from the server. A `client_node_id` is a value that you assign, so the copy keeps it unchanged. An `on_notification_action` condition points at the matching node in the copy.
* `schedule`: the copy does not inherit it, because a copied `start_at` is almost always in the past. To schedule the copy, send a `schedule` under `overrides`.
* `state` is `draft`, `started_at` and `archived_at` are `null`, and `created_source` is `public_api`. The copy gets its own `concurrency_key`.

Stats do not carry over. The copy starts with no entries, and the source keeps its own [journey stats](/reference/view-journey-stats).

### Apply overrides

`overrides` holds a journey document that is applied over the copy. It uses JSON Merge Patch ([RFC 7396](https://datatracker.ietf.org/doc/html/rfc7396)), which merges one document into another. `overrides` accepts the same writable fields as [Create journey](/reference/create-journey), and none of them are required. Use it to create the copy in its final state, instead of creating the copy and then patching it.

```json theme={null}
{
  "overrides": {
    "name": "Welcome series v2",
    "description": null,
    "schedule": { "start_at": "2026-07-01T14:00:00Z" },
    "early_exit": { "rules": { "on_session": true } }
  }
}
```

Merge patch works field by field:

* An object merges into the copied object key by key. The `early_exit` above adds a rule and leaves the other rules of the source in place.
* `null` clears the copied value. The `"description": null` above gives the copy no description.
* An array replaces the copied array as a unit. A `nodes` array replaces the whole graph of the source and does not merge into it. Send the complete graph that you want.
* If an `audience` override changes `kind`, the copy drops the fields of the previous kind. It does not keep them beside the new fields.

<Warning>
  Do not send server-controlled fields. Sending them is rejected with a `400` validation error, exactly as on [Create journey](/reference/create-journey). This covers the journey `id` and `state`, the lifecycle timestamps, and the `id` fields on nodes and branches.
</Warning>

A `nodes` override replaces the graph, so an `id` inside it addresses nothing. To reference a node from elsewhere in the same request, use `client_node_id`.

Only `overrides` is read from the body. A journey field sent at the top level is ignored rather than rejected. For example, `{"name": "Renamed"}` leaves the copy with the derived name.

## Response

A successful request returns `201 Created` and the full copy in the `draft` state. The response contains the `id` fields from the server and the `concurrency_key`. On a later [Update journey](/reference/update-journey) request, pass that `concurrency_key` unchanged. It stops your request from overwriting a concurrent change.

### Error responses

| Status | Code                   | Description                                                                                                                                                                                               |
| ------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | `invalid-payload`      | `overrides` failed validation. This covers an `overrides` value that is not an object, schema failures such as a server-controlled field or an unknown property, and business-logic failures on the copy. |
| 403    | `journey-not-entitled` | Journeys are not enabled for this app.                                                                                                                                                                    |
| 404    | `journey-not-found`    | No journey with that `id` exists for this app.                                                                                                                                                            |
| 429    |                        | Rate limit exceeded. Wait the number of seconds in the `Retry-After` header before retrying. See [Rate limits](/reference/rate-limits).                                                                   |

Entitlements are measured against the copy, not the source. An app cannot use this endpoint to create a journey that it has no entitlement to create.

Coded errors use the shape `{ "errors": [{ "code", "title", "meta" }] }`. Branch on `code` and `meta`, not on `title`, whose wording comes from the schema validator and can change between releases.

A schema failure reports `base` in `meta.attribute` and a JSON Pointer ([RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901)) in `meta.path`. The pointer names the object that holds the offending property, not the property itself, and the same pointer appears in `title`. Both are relative to the `overrides` document rather than to the request body. A rejected `state` at the top of `overrides` therefore reports `#/`, and `meta.path` is omitted because the pointer is the root. A business-logic failure on the copy names the field in `meta.attribute` instead.


## OpenAPI

````yaml POST /apps/{app_id}/journeys/{id}/duplicate
openapi: 3.1.0
info:
  title: api.onesignal.com
  version: '11.6'
servers:
  - url: https://api.onesignal.com
security:
  - {}
paths:
  /apps/{app_id}/journeys/{id}/duplicate:
    post:
      summary: Duplicate journey
      description: >-
        Copy an existing journey. The copy is always in the `draft` state,
        whatever state the source is in, and the source does not change. To
        shape the copy in the same request, send `overrides`. It is a journey
        document that is applied over the copy as a JSON Merge Patch ([RFC
        7396](https://datatracker.ietf.org/doc/html/rfc7396)). Use it to create
        the copy in its final state, instead of creating the copy and then
        patching it.
      operationId: duplicate-journey
      parameters:
        - name: app_id
          in: path
          description: >-
            Your OneSignal App ID in UUID v4 format. See [Keys &
            IDs](/docs/en/keys-and-ids).
          schema:
            type: string
            default: YOUR_APP_ID
          required: true
        - name: id
          in: path
          description: UUID of the journey to copy.
          required: true
          schema:
            type: string
            default: YOUR_JOURNEY_ID
        - name: Authorization
          in: header
          description: >-
            Your App API key with prefix `Key `. See [Keys &
            IDs](/docs/en/keys-and-ids).
          required: true
          schema:
            type: string
            default: Key YOUR_APP_API_KEY
        - name: Content-Type
          in: header
          required: true
          schema:
            type: string
            default: application/json; charset=utf-8
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                overrides:
                  type: object
                  description: >-
                    Journey fields to apply to the copy. Accepts the same
                    writable fields as [Create
                    journey](/reference/create-journey), and none of them are
                    required. Fields sent outside `overrides` are ignored.
                  properties:
                    name:
                      type: string
                      description: >-
                        Name for the copy. If you omit it, the copy takes the
                        name of the source plus ` (Copy)`.
                    description:
                      type:
                        - string
                        - 'null'
                      description: >-
                        Optional journey description. If you omit it, the copy
                        takes the description of the source.
                    audience:
                      $ref: '#/components/schemas/JourneyAudience'
                    early_exit:
                      $ref: '#/components/schemas/JourneyEarlyExit'
                    reentry_rules:
                      $ref: '#/components/schemas/JourneyReentryRules'
                    schedule:
                      $ref: '#/components/schemas/JourneySchedule'
                    nodes:
                      type: array
                      items:
                        $ref: '#/components/schemas/JourneyNode'
                      description: >-
                        Replaces the copied graph as a unit and does not merge
                        into it. Server-assigned `id` fields are rejected with a
                        `400` validation error, exactly as on create.
            examples:
              Request:
                value:
                  overrides:
                    name: Welcome series v2
      responses:
        '201':
          description: '201'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JourneyDetail'
              examples:
                Result:
                  value:
                    id: 7b6a5948-3726-1504-f3e2-d1c0b9a8f7e6
                    app_id: 1a2b3c4d-5e6f-7081-92a3-b4c5d6e7f809
                    name: Welcome series v2
                    description: Onboard new users over their first week.
                    state: draft
                    created_at: '2026-06-02T09:30:00Z'
                    updated_at: '2026-06-02T09:30:00Z'
                    started_at: null
                    archived_at: null
                    created_source: public_api
                    audience:
                      kind: segment
                      included_segment_ids:
                        - 3f7c1e90-0000-0000-0000-000000000001
                      excluded_segment_ids: []
                      future_additions_only: false
                    early_exit: null
                    reentry_rules: null
                    schedule: null
                    nodes:
                      - id: 22222222-0000-0000-0000-000000000001
                        kind: send_push
                        template_id: 9a8b7c6d-0000-0000-0000-000000000001
                      - id: 22222222-0000-0000-0000-000000000002
                        kind: wait
                        duration_seconds: 86400
                      - id: 22222222-0000-0000-0000-000000000003
                        kind: send_email
                        template_id: 9a8b7c6d-0000-0000-0000-000000000002
                    concurrency_key: >-
                      5b1f0c1d9a3e47a2b8c6d0e4f7a913b5c2d8e6f40a7b9c1d3e5f70829a4b6c8d
        '400':
          description: '400'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JourneyValidationErrorResponse'
              example:
                errors:
                  - code: invalid-payload
                    title: >-
                      The property '#/nodes/1' contains additional properties
                      ["id"] outside of the schema when none are allowed
                    meta:
                      attribute: base
                      path: nodes/1
        '403':
          description: '403'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JourneyCodedErrorResponse'
              example:
                errors:
                  - code: journey-not-entitled
                    title: Journeys are not enabled for this app
                    meta: {}
        '404':
          description: '404'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JourneyCodedErrorResponse'
              example:
                errors:
                  - code: journey-not-found
                    title: Journey not found
                    meta: {}
        '429':
          description: '429'
          headers:
            Retry-After:
              description: >-
                Number of seconds to wait before retrying the request. Always
                emitted on 429 responses.
              schema:
                type: integer
                minimum: 0
components:
  schemas:
    JourneyAudience:
      oneOf:
        - type: object
          title: segment
          required:
            - kind
          properties:
            kind:
              type: string
              const: segment
            included_segment_ids:
              type: array
              items:
                type: string
              description: Segment UUIDs whose users enter the journey.
            excluded_segment_ids:
              type: array
              items:
                type: string
              description: Segment UUIDs whose users are excluded.
            future_additions_only:
              type: boolean
              description: >-
                When true, only users who newly match the segment after
                activation enter the journey. Defaults to false.
        - type: object
          title: event_trigger
          required:
            - kind
          properties:
            kind:
              type: string
              const: event_trigger
            name:
              type: string
              description: Event name that triggers entry, up to 255 characters.
            attributes:
              $ref: '#/components/schemas/JourneyEventTriggerAttributes'
      description: >-
        The journey entry audience. Either a segment-based or event-triggered
        audience.
    JourneyEarlyExit:
      type:
        - object
        - 'null'
      description: >-
        Conditions that remove a user from the journey before it completes. At
        least one rule must be set under `rules`; an early_exit that configures
        no rule is rejected. Send `null` to remove early exit entirely, or
        `null` for an individual rule to drop just that rule.
      properties:
        rules:
          type: object
          properties:
            on_segment:
              type:
                - object
                - 'null'
              properties:
                included_segment_ids:
                  type: array
                  items:
                    type: string
                  description: Exit when the user enters any of these segments.
            when_not_in_audience:
              type:
                - boolean
                - 'null'
              description: >-
                Exit when the user no longer matches the journey audience.
                Defaults to false.
            on_session:
              type:
                - boolean
                - 'null'
              description: Exit on a new session start. Defaults to false.
            on_event:
              type:
                - object
                - 'null'
              required:
                - name
              properties:
                name:
                  type: string
                  description: Exit when this event occurs. Up to 255 characters.
        tag_on_early_exit:
          type: object
          additionalProperties:
            type: string
          description: Tag key-value pairs applied when a user exits early.
    JourneyReentryRules:
      type:
        - object
        - 'null'
      description: >-
        Controls whether and how soon a user can re-enter the journey. `null`
        means re-entry is not allowed.
      properties:
        duration_seconds:
          type: integer
          minimum: 600
          description: >-
            Minimum seconds before a user can re-enter. Must be at least `600`
            (10 minutes).
    JourneySchedule:
      type:
        - object
        - 'null'
      description: >-
        Optional future start and/or stop time. `null` means no scheduled
        activation.
      properties:
        start_at:
          type:
            - string
            - 'null'
          description: >-
            ISO 8601 start time. Use UTC (`Z` or `+00:00`). Must be at least 5
            minutes in the future.
        stop_at:
          type:
            - string
            - 'null'
          description: >-
            ISO 8601 stop time. Use UTC (`Z` or `+00:00`). Must be in the future
            and later than `start_at`.
        error:
          type:
            - string
            - 'null'
          description: Read-only. Present when a scheduling error occurred.
    JourneyNode:
      oneOf:
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: wait
              description: Holds the user for a fixed duration before continuing.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            duration_seconds:
              type: integer
              description: >-
                Seconds to hold the user. Minimum `60`, maximum `31556952` (1
                year).
              minimum: 60
              maximum: 31556952
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: time_window
              description: Holds the user until the next configured time window opens.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            relative_to:
              type: string
              enum:
                - schedule_in_timezone
                - last_active_time
              description: >-
                `schedule_in_timezone` uses the configured windows;
                `last_active_time` holds relative to the user's last active
                time.
            windows:
              type: array
              items:
                $ref: '#/components/schemas/JourneyTimeWindow'
              description: >-
                One or more time windows. A window with no `day_of_week` applies
                to every day, and is returned in that same day-agnostic form.
                Required when `relative_to` is `schedule_in_timezone`; must be
                omitted when it is `last_active_time`, and is absent from
                responses for those nodes.
            time_zone:
              type: string
              description: >-
                IANA timezone identifier used when the user's timezone is
                unavailable.
            use_user_time_zone:
              type: boolean
              description: When true, uses the user's timezone if available.
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              enum:
                - send_push
                - send_email
                - send_sms
              description: Sends a message on the given channel using a template.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            template_id:
              type: string
              description: UUID of the template to send.
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: send_iam
              description: Sends an in-app message.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            iam_id:
              type: string
              description: UUID of the in-app message to send.
            user_ttl_seconds:
              type: integer
              minimum: 1
              description: Optional time-to-live for the in-app message, in seconds.
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: send_webhook
              description: Sends a webhook.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            webhook_id:
              type: string
              description: UUID of the webhook to send.
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: tag
              description: Assigns key-value tags to the user.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            assignments:
              type: object
              additionalProperties:
                type: string
              description: >-
                Tag key-value pairs to assign. An empty string value removes the
                tag. Keys are limited to 255 characters and values to 1024.
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: split_range
              description: >-
                Routes users into weighted branches that converge to the next
                sibling node.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            randomize_on_entry:
              type: boolean
              description: >-
                When true, assigns each user to a branch at random on entry.
                Defaults to false.
            branches:
              type: array
              items:
                $ref: '#/components/schemas/JourneyBranch'
              description: >-
                Weighted branches. Between 2 and 20. Weights must sum to 100.
                Order determines display order.
              minItems: 2
              maxItems: 20
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: yes_no
              description: Routes users into a yes or no branch based on a condition.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            branches:
              type: array
              minItems: 2
              maxItems: 2
              items:
                $ref: '#/components/schemas/JourneyBranch'
              description: >-
                Exactly two branches. The branch with a `condition` is the "yes"
                branch; the branch without one is the "no" branch.
        - type: object
          required:
            - kind
          properties:
            id:
              type: string
              description: >-
                Server-assigned node UUID. Read-only. Returned on reads; sending
                it on create is rejected with a `400` validation error.
            kind:
              type: string
              const: wait_until
              description: >-
                Holds the user until any branch condition is met, or an optional
                expiration timer fires.
            client_node_id:
              type: string
              description: >-
                Optional client-assigned identifier, unique within the journey.
                Use it to reference this node from elsewhere in the same request
                (for example as `client_node_id` on an `on_notification_action`
                condition). Persisted and returned on reads.
            annotation:
              type: string
              description: >-
                Optional free-text label, up to 255 characters. Stored and
                returned as-is with no effect on journey behavior.
            branches:
              type: array
              items:
                $ref: '#/components/schemas/JourneyBranch'
              description: >-
                Condition branches. At least one required, at most 10. Order
                determines priority.
            expiration:
              type:
                - object
                - 'null'
              properties:
                duration_seconds:
                  type: integer
                  minimum: 60
                  description: >-
                    Seconds to wait before the timer fires. Minimum `60`,
                    maximum `31556952` (1 year).
                  maximum: 31556952
                exits:
                  type: boolean
                  description: >-
                    When true, the user exits the journey when the timer fires;
                    when false, the user continues to convergence.
              description: Optional expiration timer. `null` waits indefinitely.
      description: >-
        A journey node. The `kind` field selects the shape. Branching nodes
        (`split_range`, `yes_no`, `wait_until`) nest their sub-graphs inline via
        `branches[].nodes`.
    JourneyDetail:
      type: object
      description: Full journey representation returned by the detail and create endpoints.
      properties:
        id:
          type: string
          description: Journey UUID. Read-only.
        app_id:
          type: string
          description: UUID of the app the journey belongs to. Read-only.
        name:
          type: string
          description: Journey name, up to 300 characters.
        description:
          type:
            - string
            - 'null'
          description: >-
            Journey description, up to 1024 characters. Defaults to an empty
            string.
        state:
          type: string
          enum:
            - draft
            - scheduled
            - processing
            - active
            - archived
          description: >-
            Journey state. Read-only. New journeys are created as `draft`.
            `processing` is a transient state while an activation is in
            progress, and `archived` is a journey that has been stopped. Change
            it through the `state` field on [Update
            journey](/reference/update-journey).
        created_at:
          type: string
          description: ISO 8601 creation time. Read-only.
        updated_at:
          type: string
          description: ISO 8601 last-update time. Read-only.
        started_at:
          type:
            - string
            - 'null'
          description: >-
            ISO 8601 time the journey was activated, or `null`. Read-only. May
            stay `null` briefly after you set `state` to `active`: activation is
            enqueued for processing, and `started_at` populates once the journey
            finishes processing and becomes active.
        archived_at:
          type:
            - string
            - 'null'
          description: ISO 8601 time the journey was archived, or `null`. Read-only.
        created_source:
          type:
            - string
            - 'null'
          description: >-
            Origin of the journey, for example `public_api` or `dashboard`.
            Read-only.
        audience:
          $ref: '#/components/schemas/JourneyAudience'
        early_exit:
          $ref: '#/components/schemas/JourneyEarlyExit'
        reentry_rules:
          $ref: '#/components/schemas/JourneyReentryRules'
        schedule:
          $ref: '#/components/schemas/JourneySchedule'
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/JourneyNode'
          description: Ordered list of journey nodes.
        concurrency_key:
          type: string
          description: >-
            Opaque optimistic-concurrency token. Read-only. Pass it back on
            update to guard against overwriting a concurrent change (`409
            journey-stale`). Send it back exactly as read from this response; do
            not construct or parse it.
    JourneyValidationErrorResponse:
      type: object
      description: >-
        Validation error response. Uses the same `code`/`title`/`meta` shape as
        every other error; the failing field and any positional detail travel in
        `meta`.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
                description: >-
                  Stable, kebab-case error identifier. Always `invalid-payload`
                  for validation failures.
              title:
                type: string
                description: Human-readable message. Wording may change between releases.
              meta:
                type: object
                description: >-
                  Structured context. Always includes `attribute` (the field, or
                  `base` for request-level errors); may also include `path`,
                  `node_id`, or `client_node_id`.
    JourneyCodedErrorResponse:
      type: object
      description: Error response with a stable machine-readable `code`.
      properties:
        errors:
          type: array
          items:
            type: object
            properties:
              code:
                type: string
                description: >-
                  Stable, kebab-case error identifier. Does not change once
                  shipped.
              title:
                type: string
                description: Human-readable message. Wording may change between releases.
              meta:
                type: object
                description: Optional structured context. Shape varies by error.
    JourneyEventTriggerAttributes:
      type: array
      description: >-
        Event attribute matchers, as a list of condition groups. Send a single
        group whose conditions are AND'd together. More than one group is
        rejected.
      items:
        type: array
        items:
          type: object
          required:
            - key
            - operator
          properties:
            key:
              type: string
              description: Event attribute key.
            operator:
              type: string
              enum:
                - equal
                - not_equal
                - less
                - less_or_equal
                - greater_or_equal
                - greater
                - is
                - is_not
                - exists
                - not_exists
                - before
                - after
              description: Comparison operator.
            value:
              type: string
              description: >-
                Value to compare against. Not required for `exists` and
                `not_exists`.
    JourneyTimeWindow:
      type: object
      properties:
        start:
          allOf:
            - $ref: '#/components/schemas/JourneyTimePoint'
          description: When the window opens.
        end:
          allOf:
            - $ref: '#/components/schemas/JourneyTimePoint'
          description: When the window closes.
        day_of_week:
          type: integer
          minimum: 1
          maximum: 7
          description: Day of week, 1 = Monday. Omit to apply the window to every day.
      description: A wall-clock window. Each window must span at least 15 minutes.
    JourneyBranch:
      type: object
      properties:
        id:
          type: string
          description: Server-assigned branch identifier. Read-only.
        condition:
          $ref: '#/components/schemas/JourneyCondition'
        weight:
          type: number
          description: >-
            Branch weight for `split_range` nodes. Weights across a node's
            branches must sum to 100.
        nodes:
          type: array
          items:
            $ref: '#/components/schemas/JourneyNode'
          description: >-
            Nodes run when this branch is taken, before flow converges to the
            next sibling node.
    JourneyTimePoint:
      type: object
      properties:
        hour:
          type: integer
          minimum: 0
          maximum: 23
          description: Hour of day, 0-23.
        minute:
          type: integer
          minimum: 0
          maximum: 59
          description: Minute of hour, 0-59. Defaults to 0.
    JourneyCondition:
      oneOf:
        - type: object
          title: segment_membership
          required:
            - kind
          properties:
            kind:
              type: string
              const: segment_membership
            included_segment_ids:
              type: array
              items:
                type: string
              description: Segment UUIDs the user must belong to.
            excluded_segment_ids:
              type: array
              items:
                type: string
              description: Segment UUIDs the user must not belong to.
        - type: object
          title: on_notification_action
          required:
            - kind
          properties:
            kind:
              type: string
              const: on_notification_action
            action:
              type: string
              enum:
                - received
                - clicked
                - opened
              description: >-
                The notification action to branch on. Which actions apply
                depends on the sending node's channel.
            sending_node_id:
              type: string
              description: >-
                `id` of the sending node this action refers to. Returned on
                reads; accepted on write.
            client_node_id:
              type: string
              description: >-
                Write-only alternative to `sending_node_id`. References the
                sending node by its `client_node_id`, which is resolved to that
                node's `id`.
        - type: object
          title: event_trigger
          required:
            - kind
          properties:
            kind:
              type: string
              const: event_trigger
            name:
              type: string
              description: Event name, up to 255 characters.
            attributes:
              $ref: '#/components/schemas/JourneyEventTriggerAttributes'
            entry_event_match_attributes:
              type:
                - array
                - 'null'
              items:
                type: object
              description: >-
                Match incoming event properties against the journey's entry
                event. Only valid on event-triggered journeys.
      description: A branch condition. The `kind` field selects the shape.

````