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

# Update draft

> Replace a draft journey's whole graph. Journey-level metadata is merged, not replaced — keys the payload omits (e.g. the environment pin) keep their stored values. Only drafts can be edited; published versions are frozen (edit a live journey in the app to fork a new draft). Omit node positions and the server lays the graph out automatically.



## OpenAPI

````yaml /api-reference/openapi.json patch /api/v1/journeys/{journeyId}
openapi: 3.1.0
info:
  title: Boom API
  version: 1.0.0
  description: >-
    Boom's public REST API — one uniform surface over every platform capability.
    CDP: upsert people and custom objects, define object and relationship types,
    link and unlink relationships, and record behavioral events — one record per
    request or up to 1000 per request via the `/batch` endpoints. Segments: read
    (list, read, membership) and full authoring — discover the filterable
    catalog, validate a filter, create and update segments, preview match
    counts, and trigger evaluation. Initiatives: create and configure outreach
    initiatives, link WhatsApp templates, drive the lifecycle (launch, cancel,
    archive), and read collected-data summaries. Participants: enroll people
    into an active initiative, track their status, read conversation
    transcripts, and stop outreach. Journeys: read-only access to always-on
    message flows and their metrics. WhatsApp templates: list your WhatsApp
    numbers and list, read, and create message templates. The same capabilities
    are exposed as MCP tools with identical schemas.
servers:
  - url: https://www.useboom.ai
    description: Production
  - url: https://dev.useboom.ai
    description: Development (sandbox — use a development organization API key)
security:
  - bearerAuth: []
paths:
  /api/v1/journeys/{journeyId}:
    patch:
      tags:
        - Journeys
      summary: Update draft
      description: >-
        Replace a draft journey's whole graph. Journey-level metadata is merged,
        not replaced — keys the payload omits (e.g. the environment pin) keep
        their stored values. Only drafts can be edited; published versions are
        frozen (edit a live journey in the app to fork a new draft). Omit node
        positions and the server lays the graph out automatically.
      operationId: journeys_update_draft
      parameters:
        - name: journeyId
          in: path
          required: true
          schema:
            $schema: https://json-schema.org/draft/2020-12/schema
            type: string
            minLength: 1
            description: >-
              A draft journey id, or the initiative id (resolves to its current
              draft).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $schema: https://json-schema.org/draft/2020-12/schema
              type: object
              properties:
                definition:
                  type: object
                  properties:
                    id:
                      description: >-
                        Journey id; carried for round-trip ergonomics. Optional
                        on create.
                      type: string
                    name:
                      type: string
                      minLength: 1
                      description: Journey name.
                    metadata:
                      type: object
                      properties:
                        initiativeType:
                          type: string
                        version:
                          type: integer
                          minimum: -9007199254740991
                          maximum: 9007199254740991
                        cancelOnEvents:
                          description: >-
                            Cancel an in-flight run when any of these events
                            arrive.
                          type: object
                          properties:
                            eventNames:
                              type: array
                              items:
                                type: string
                            matchRunKey:
                              description: >-
                                Cancel only the run whose key equals this
                                event's `parallelRunsBy` property, instead of
                                every run the person has. Leave it unset on a
                                journey with several runs at once: that already
                                matches on the key, and setting it to false
                                there is refused at publish, because one
                                completed payment would stop the person's other
                                payments too.
                              type: boolean
                          required:
                            - eventNames
                        environmentId:
                          description: >-
                            Pinned environment whose non-secret {{env.*}} values
                            HTTP nodes resolve against. Frozen at publish. The
                            server preserves the stored value when a whole-graph
                            update omits it.
                          type: string
                      description: Optional journey-level metadata.
                    actions:
                      minItems: 1
                      type: array
                      items:
                        oneOf:
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: ENTRY
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  description:
                                    type: string
                                  triggerType:
                                    description: >-
                                      How people enter: manual (added by an
                                      operator or API call), segment (on
                                      entering a segment), cdp_event (when an
                                      event is received), or inbound (when a
                                      message arrives on one of the org's
                                      channels). Defaults to manual.
                                    type: string
                                    enum:
                                      - manual
                                      - segment
                                      - cdp_event
                                      - inbound
                                  segmentId:
                                    description: >-
                                      Segment id — required when triggerType is
                                      segment.
                                    type: string
                                  segmentName:
                                    description: Cached segment display name (optional).
                                    type: string
                                  eventName:
                                    description: >-
                                      CDP event name — required when triggerType
                                      is cdp_event.
                                    type: string
                                  inboundAction:
                                    description: >-
                                      Which arrival fires the trigger — required
                                      when triggerType is inbound.
                                      INSTAGRAM_COMMENT / FACEBOOK_COMMENT
                                      listen to public comments on the account's
                                      posts instead of DMs; they require
                                      Instagram or Messenger channels whose
                                      connection was granted comment permission,
                                      and enroll the commenter without opening a
                                      conversation.
                                    type: string
                                    enum:
                                      - WHATSAPP_MESSAGE
                                      - SMS_MESSAGE
                                      - INSTAGRAM_MESSAGE
                                      - MESSENGER_MESSAGE
                                      - INSTAGRAM_COMMENT
                                      - FACEBOOK_COMMENT
                                  inboundChannelIds:
                                    description: >-
                                      Channel ids to listen on — at least one
                                      required when triggerType is inbound. Must
                                      be NATIVE WhatsApp, SMS, Instagram or
                                      Messenger channels that are not deleted —
                                      WhatsApp and SMS additionally need an
                                      ONLINE sender, Instagram and Messenger
                                      have no sender row and need none (a
                                      Messenger Page still on the V1 bridge is
                                      withheld as NOT_NATIVE);
                                      journeys_set_trigger names the eligible
                                      ids if you pass an ineligible one. For a
                                      comment action, only Instagram and
                                      Messenger channels are valid. Several
                                      published journeys may share one channel
                                      as long as their keywords differ:
                                      publishing a rule whose keyword (or blank
                                      catch-all) is already taken on that
                                      channel is refused with
                                      INBOUND_CHANNEL_TAKEN. Each arriving
                                      message enrols exactly one of them, the
                                      most specific matching rule, ties going to
                                      the older initiative.
                                    type: array
                                    items:
                                      type: string
                                  inboundKeyword:
                                    description: >-
                                      The word the inbound message must match
                                      for this journey to enrol — e.g. 'PRECIO'.
                                      Blank or absent means the trigger is the
                                      catch-all and fires on ANY message
                                      arriving on the channel, which is almost
                                      never what you want beside other journeys
                                      on the same number. Several journeys may
                                      share one channel as long as their
                                      keywords differ — two rules with the same
                                      keyword on one channel, or two blank ones,
                                      are refused at publish with
                                      INBOUND_CHANNEL_TAKEN. The keyword is
                                      matched accent-, case- and
                                      punctuation-insensitively, and stored
                                      normalized.
                                    type: string
                                  inboundMatchMode:
                                    description: >-
                                      How inboundKeyword is matched: EXACT (the
                                      message is only-the-word), ALL_WORDS (the
                                      message contains all-the-words, in any
                                      order), or CONTAINS (the message
                                      contains-the-word, adjacent and in order).
                                      All three are word-based, so no mode ever
                                      matches inside a longer word ('precioso'
                                      does not match 'precio'). Defaults to
                                      EXACT. Ignored when inboundKeyword is
                                      blank.
                                    type: string
                                    enum:
                                      - EXACT
                                      - CONTAINS
                                      - ALL_WORDS
                                  maxEnrollments:
                                    description: >-
                                      Frequency cap: max enrollments per person
                                      within enrollmentWindow. Both-or-neither
                                      with enrollmentWindow.
                                    type: integer
                                    minimum: 1
                                    maximum: 9007199254740991
                                  enrollmentWindow:
                                    description: Rolling window for the frequency cap.
                                    type: string
                                  parallelRunsBy:
                                    description: >-
                                      Let one person have several runs of this
                                      journey at the same time, one per distinct
                                      value of this event property (e.g.
                                      "paymentLinkId"). Use it when a person can
                                      have several of the same thing in flight,
                                      two payment links or two orders, and each
                                      needs its own sequence. Three things to
                                      know. It works on cdp_event triggers only,
                                      because the run is identified by a
                                      property of the triggering event; an event
                                      that does not carry the property is
                                      refused rather than enrolled. The journey
                                      becomes SEND ONLY: no wait-for-reply,
                                      conversation or AI nodes, because an
                                      inbound message belongs to the person and
                                      not to one run, so a single reply would
                                      wake every run at once. And every stop
                                      event listed in cancelOnEvents matches on
                                      this same property, so a completed one
                                      stops only its own run and leaves the
                                      person's other runs alive. Publish is
                                      refused if any of that is violated.
                                    type: string
                                    minLength: 1
                                description: >-
                                  Trigger node config. Exactly one ENTRY node
                                  per journey.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: SEND_MESSAGE
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  mode:
                                    description: >-
                                      What this send carries: 'template' (an
                                      approved WhatsApp template, the default
                                      when omitted) or 'free_text' (prose you
                                      write, needing `body` instead of
                                      `templateId`). free_text emits SENT and
                                      WINDOW_CLOSED, both of which must be wired
                                      — Meta accepts free-form content only
                                      within 24 hours of the customer's last
                                      message, checked before sending. Prefer
                                      this over the deprecated
                                      SEND_WHATSAPP_TEXT node, which is the same
                                      send under an older name.
                                    type: string
                                    enum:
                                      - template
                                      - free_text
                                  templateId:
                                    description: >-
                                      Approved WhatsApp template id. Resolve ids
                                      from the catalog.
                                    type: string
                                  templateName:
                                    type: string
                                  body:
                                    description: >-
                                      The message text, for mode 'free_text'
                                      only. Placeholders are named, like
                                      {{customer.name}}, and EVERY one must have
                                      a matching entry in `bindings` or publish
                                      is refused: an unbound placeholder is sent
                                      literally, braces and all. Bind an
                                      upstream HTTP response with
                                      engagement.nodeOutputs.<nodeId>.body.<field>.
                                    type: string
                                  bindings:
                                    description: >-
                                      Map of {{placeholder}} name → variable
                                      reference, for `body`. Template mode uses
                                      `templateBindings` instead.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                  channel:
                                    description: >-
                                      Always whatsapp. Other channels have their
                                      own node kind — SEND_SMS for a text,
                                      SEND_INSTAGRAM for Instagram,
                                      SEND_MESSENGER for Facebook Messenger.
                                    type: string
                                    const: whatsapp
                                  templateBindings:
                                    description: >-
                                      Map of template placeholder → variable
                                      reference, or fixed text prefixed
                                      `literal:` (e.g. `{ "2":
                                      "literal:BIENVENIDA20" }`) for a value
                                      that is the same for every recipient.
                                      EVERY placeholder the template declares
                                      (body, header, footer, button URL) needs
                                      an entry or publish is refused, since an
                                      unbound one is sent literally. The only
                                      exception: a template whose sole
                                      placeholder is {{1}}, with no map at all,
                                      falls back to the customer name (not on a
                                      Transactional).
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                  channelId:
                                    description: >-
                                      Sending WhatsApp channel (WABA) id.
                                      Required before publishing.
                                    type: string
                                  sendImmediately:
                                    description: >-
                                      Deprecated business-hours gate; prefer a
                                      preceding DELAY.
                                    type: boolean
                                  delivery:
                                    description: >-
                                      'draft' holds the rendered send in the
                                      Drafts queue until an org member approves
                                      or rejects it; the run waits at this node.
                                      Approve sends it and continues on SENT;
                                      reject emits REJECTED (optional edge —
                                      unwired, the run ends). Omit for
                                      'immediate'. Refused on a Transactional
                                      initiative's journey
                                      (`transactional_draft_delivery`): a
                                      notification must go out. Refused
                                      (`drafts_disabled`) while drafts are
                                      turned off for the organization; a
                                      published drafted send reached while
                                      they're off is skipped (SKIPPED), never
                                      sent unreviewed.
                                    type: string
                                    enum:
                                      - immediate
                                      - draft
                                description: >-
                                  Sends WhatsApp: an approved template
                                  (default), or free-text prose with mode
                                  'free_text'.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: SEND_SMS
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  body:
                                    description: >-
                                      The message text. Free text — SMS has no
                                      approved-template concept. Placeholders
                                      are named, like {{customer.name}}, and
                                      EVERY one must have a matching entry in
                                      `bindings` or publish is refused: an
                                      unbound placeholder is sent literally,
                                      braces and all. The opt-out footer and the
                                      brand are added by the system; do not
                                      write them into the body.
                                    type: string
                                  channelId:
                                    description: >-
                                      Sending SMS channel id. Required before
                                      publishing.
                                    type: string
                                  bindings:
                                    description: >-
                                      Map of {{placeholder}} name → variable
                                      reference. The builder writes the path as
                                      its own name ({"customer.name":
                                      "customer.name"}); an alias is allowed as
                                      long as the body uses the alias.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                  optOutText:
                                    description: >-
                                      Opt-out line for this node, overriding the
                                      organization's. Must contain the STOP
                                      keyword. Omit to use the organization's.
                                    type: string
                                  allowEmoji:
                                    description: >-
                                      Keep emoji instead of stripping them.
                                      Defaults to false, because emoji force
                                      UCS-2 encoding, which cuts a message part
                                      from 160 characters to 70 and roughly
                                      doubles the cost.
                                    type: boolean
                                description: Sends a plain-text SMS.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: SEND_WHATSAPP_TEXT
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  body:
                                    description: >-
                                      The message text. Free text — no Meta
                                      template approval needed, which is the
                                      point of this node. Placeholders are
                                      named, like {{customer.name}}, and EVERY
                                      one must have a matching entry in
                                      `bindings` or publish is refused: an
                                      unbound placeholder is sent literally,
                                      braces and all. Bind an upstream HTTP
                                      response with
                                      engagement.nodeOutputs.<nodeId>.body.<field>.
                                    type: string
                                  channelId:
                                    description: >-
                                      Sending WhatsApp channel (WABA) id.
                                      Required before publishing; it is also the
                                      per-number send throttle key.
                                    type: string
                                  bindings:
                                    description: >-
                                      Map of {{placeholder}} name → variable
                                      reference. The builder writes the path as
                                      its own name ({"customer.name":
                                      "customer.name"}); an alias is allowed as
                                      long as the body uses the alias.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                description: >-
                                  Sends free-text WhatsApp — author-written
                                  prose instead of an approved template. Emits
                                  SENT or WINDOW_CLOSED, and BOTH must be wired.
                                  Meta accepts free-form content only within 24
                                  hours of the customer's last message; the node
                                  checks that BEFORE sending (Twilio would
                                  accept an out-of-window message and fail it
                                  asynchronously with 63016), so WINDOW_CLOSED
                                  means nothing was sent and is where you put an
                                  approved template. A node with no upstream
                                  WAIT_FOR_REPLY / MANAGE_CONVERSATION will
                                  usually take WINDOW_CLOSED — publish warns but
                                  does not block, because a customer who wrote
                                  recently on this number in ANY journey still
                                  has an open window.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: SEND_INSTAGRAM
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  body:
                                    description: >-
                                      The message text. Free text — Instagram
                                      has no approved-template concept.
                                      Placeholders are named, like
                                      {{customer.name}}, and EVERY one must have
                                      a matching entry in `bindings` or publish
                                      is refused: an unbound placeholder is sent
                                      literally, braces and all.
                                    type: string
                                  channelId:
                                    description: >-
                                      Sending native Instagram channel id.
                                      Required before publishing, with no
                                      org-primary fallback.
                                    type: string
                                  bindings:
                                    description: >-
                                      Map of {{placeholder}} name → variable
                                      reference. The builder writes the path as
                                      its own name ({"customer.name":
                                      "customer.name"}); an alias is allowed as
                                      long as the body uses the alias.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                description: >-
                                  Sends free-text Instagram from a chosen native
                                  account — no template concept, so every
                                  message is author-written prose. Emits SENT or
                                  WINDOW_CLOSED, and BOTH must be wired. Meta
                                  accepts free-form content only within 24 hours
                                  of the customer's last message; the node
                                  checks that BEFORE sending, so WINDOW_CLOSED
                                  means nothing was sent. Instagram has no
                                  template fallback, so WINDOW_CLOSED usually
                                  leads to EXIT — say so explicitly rather than
                                  leaving it dangling. Exception: in a run an
                                  INSTAGRAM_COMMENT trigger started, a shut
                                  window sends one private reply to that comment
                                  instead (same account, comment under 7 days
                                  old and not yet replied to); Meta decides
                                  whether it lands.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: SEND_EMAIL
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  templateId:
                                    description: >-
                                      A PUBLISHED email template id from
                                      journeys_email_templates. Required before
                                      publishing; a draft or archived template
                                      is refused at publish.
                                    type: string
                                  templateName:
                                    description: >-
                                      The template's name, cached so the canvas
                                      can label the node without a lookup. Copy
                                      it from journeys_email_templates.
                                    type: string
                                  bindings:
                                    description: >-
                                      Map of the template's variable key (its
                                      `variables[].key` in
                                      journeys_email_templates) → variable
                                      reference such as customer.name, or
                                      engagement.chatLink for the link that
                                      opens this run's web chat. Bind only what
                                      you want to reroute: a variable left out
                                      resolves its own `path`, as the template
                                      was authored.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                  fromSenderIdOverride:
                                    description: >-
                                      Sender id to send From for this node only,
                                      overriding the template's pick and the org
                                      default. Must be a sender with
                                      usableAsFrom: true in
                                      journeys_email_templates. Omit to inherit.
                                    type: string
                                  replyToSenderIdOverride:
                                    description: >-
                                      Sender id to use as Reply-To for this node
                                      only. Omit to inherit the template, then
                                      the org default.
                                    type: string
                                  delivery:
                                    description: >-
                                      'draft' holds the rendered send in the
                                      Drafts queue until an org member approves
                                      or rejects it; the run waits at this node.
                                      Approve sends it and continues on SENT;
                                      reject emits REJECTED (optional edge —
                                      unwired, the run ends). Omit for
                                      'immediate'. Refused on a Transactional
                                      initiative's journey
                                      (`transactional_draft_delivery`): a
                                      notification must go out. Refused
                                      (`drafts_disabled`) while drafts are
                                      turned off for the organization; a
                                      published drafted send reached while
                                      they're off is skipped (SKIPPED), never
                                      sent unreviewed.
                                    type: string
                                    enum:
                                      - immediate
                                      - draft
                                description: >-
                                  Sends a PUBLISHED email template to the
                                  customer.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: SEND_MESSENGER
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  body:
                                    description: >-
                                      The message text, at most 2000 characters.
                                      Free text — no approved-template concept.
                                      Placeholders are named, like
                                      {{customer.name}}, and EVERY one must have
                                      a matching entry in `bindings` or publish
                                      is refused: an unbound placeholder is sent
                                      literally, braces and all.
                                    type: string
                                  channelId:
                                    description: >-
                                      Sending native Messenger channel (Facebook
                                      Page) id, from journeys_message_channels
                                      (sendNodeKind SEND_MESSENGER). Required
                                      before publishing, with no org-primary
                                      fallback.
                                    type: string
                                  bindings:
                                    description: >-
                                      Map of {{placeholder}} name → variable
                                      reference. The builder writes the path as
                                      its own name ({"customer.name":
                                      "customer.name"}); an alias is allowed as
                                      long as the body uses the alias.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      type: string
                                description: >-
                                  Sends free-text Facebook Messenger from a
                                  chosen Page — every message is author-written
                                  prose. Emits SENT or WINDOW_CLOSED, and BOTH
                                  must be wired. Meta accepts it only within 24
                                  hours of the customer's last message; the node
                                  checks that BEFORE sending, so WINDOW_CLOSED
                                  means nothing was sent. There is no template
                                  fallback, so WINDOW_CLOSED usually leads to
                                  EXIT — say so explicitly rather than leaving
                                  it dangling. Exception: in a run an
                                  FACEBOOK_COMMENT trigger started, a shut
                                  window sends one private reply to that comment
                                  instead (same Page, comment under 7 days old
                                  and not yet replied to); Meta decides whether
                                  it lands.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: CONVERSATION_BLOCK
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  goal:
                                    type: string
                                  maxTimeout:
                                    description: >-
                                      How long to wait for a reply before timing
                                      out.
                                    type: string
                                  mode:
                                    type: string
                                    enum:
                                      - AGENT
                                      - ESCALATE
                                  outputs:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: string
                                        label:
                                          type: string
                                        type:
                                          type: string
                                          enum:
                                            - string
                                            - number
                                            - date
                                            - boolean
                                            - json
                                        description:
                                          type: string
                                        builtin:
                                          type: boolean
                                      required:
                                        - id
                                        - label
                                        - type
                                        - builtin
                                description: Legacy combined wait + AI conversation block.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: WAIT_FOR_REPLY
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  maxTimeout:
                                    description: >-
                                      How long to wait for the first reply
                                      before timing out.
                                    type: string
                                description: Waits for the person to reply.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: MANAGE_CONVERSATION
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  mode:
                                    description: >-
                                      AGENT (AI-led) or ESCALATE (human
                                      handoff). Defaults to AGENT.
                                    type: string
                                    enum:
                                      - AGENT
                                      - ESCALATE
                                  goal:
                                    description: >-
                                      Instructions for this conversation step
                                      only, on top of the initiative objective
                                      (e.g. 'Confirm the delivery address before
                                      anything else'). AGENT mode only; ignored
                                      in ESCALATE.
                                    type: string
                                  inactivityTimeout:
                                    description: >-
                                      Optional custom idle window (e.g. '2h',
                                      '30m') that overrides the global
                                      inactive-conversation close. Resets on
                                      each inbound message; after this much
                                      silence the node closes the conversation
                                      (routes CLOSED), unless the AI has
                                      escalated it to a human, in which case it
                                      stays open. Hard cap 24h; under 30m is
                                      allowed but flagged 'not recommended'.
                                      Requires the journey-inactivity-timeout
                                      flag.
                                    type: string
                                description: Runs the AI-led conversation.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: DISPATCH_EVENT
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  eventName:
                                    type: string
                                    minLength: 1
                                    description: >-
                                      CDP event name to record. Must match the
                                      CDP name pattern.
                                  properties:
                                    description: >-
                                      Literal string values, or { var: path }
                                      bindings resolved to typed values at
                                      dispatch time.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      anyOf:
                                        - type: string
                                        - type: object
                                          properties:
                                            var:
                                              type: string
                                          required:
                                            - var
                                  description:
                                    type: string
                                required:
                                  - eventName
                                description: Records a CDP event for the person.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: DELAY
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  mode:
                                    description: >-
                                      How the wait is measured. Defaults to
                                      duration.
                                    type: string
                                    enum:
                                      - duration
                                      - until_date
                                      - until_weekday
                                  duration:
                                    description: For mode duration.
                                    type: string
                                  targetAt:
                                    description: ISO 8601 instant, for mode until_date.
                                    type: string
                                  weekdays:
                                    description: >-
                                      ISO weekdays 1=Mon..7=Sun, for mode
                                      until_weekday.
                                    type: array
                                    items:
                                      type: integer
                                      minimum: 1
                                      maximum: 7
                                  windowStartMinutes:
                                    type: integer
                                    minimum: 0
                                    maximum: 1439
                                  windowEndMinutes:
                                    type: integer
                                    minimum: 0
                                    maximum: 1439
                                  timezone:
                                    description: >-
                                      IANA timezone. Load-bearing for
                                      until_weekday.
                                    type: string
                                  description:
                                    type: string
                                description: Pauses the run.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: DECISION
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  logic:
                                    type: string
                                    enum:
                                      - AND
                                      - OR
                                  conditions:
                                    type: array
                                    items:
                                      oneOf:
                                        - type: object
                                          properties:
                                            kind:
                                              type: string
                                              const: value
                                            selectionPath:
                                              type: string
                                              description: >-
                                                Dot-path into the run; must start with
                                                one of "engagement.workflowState.",
                                                "engagement.extracted.",
                                                "engagement.nodeOutputs.",
                                                "engagement.conversation." (e.g.
                                                engagement.workflowState.totalPrice).
                                                customer.*, person.*, attributes.* and
                                                engagement.context.* are NOT resolvable
                                                here. Unlike the other roots,
                                                "engagement.conversation." takes ONE OF
                                                a closed set of keys —
                                                hoursSinceLastInbound, lastInboundText,
                                                lastInboundKind, documentCount,
                                                newDocumentCount — and any other key is
                                                refused at publish rather than resolving
                                                blank. A single formatting helper may
                                                follow the path ("| currency:MXN", "|
                                                count"), including on
                                                engagement.conversation.*, whose key is
                                                checked with the helper stripped off.
                                            operator:
                                              type: string
                                              enum:
                                                - eq
                                                - neq
                                                - gt
                                                - lt
                                                - contains
                                                - matchesKeyword
                                                - isSet
                                              description: >-
                                                How to compare. `contains` is a plain
                                                substring test, so "precio" also matches
                                                "precioso". `matchesKeyword` is the
                                                ENTRY inbound-trigger matcher instead —
                                                accent- and case-folded, matched on word
                                                boundaries — so an author who writes the
                                                same word on a trigger and mid-journey
                                                gets the same answer. Use
                                                `matchesKeyword` to route by what the
                                                customer said; a value that folds to no
                                                letters or digits is refused at publish,
                                                because it would match every message.
                                                Must also suit the selected field: text
                                                tests (`contains`, `matchesKeyword`) are
                                                refused on a number, and ordering (`gt`,
                                                `lt`) on text — see
                                                DECISION_OPERATOR_TYPE_MISMATCH.
                                            value:
                                              type: string
                                          required:
                                            - kind
                                            - selectionPath
                                            - operator
                                            - value
                                        - type: object
                                          properties:
                                            kind:
                                              type: string
                                              const: event
                                            eventName:
                                              type: string
                                            subjectSelectionPath:
                                              type: string
                                              description: >-
                                                Dot-path into the run; must start with
                                                one of "engagement.workflowState.",
                                                "engagement.extracted.",
                                                "engagement.nodeOutputs.",
                                                "engagement.conversation." (e.g.
                                                engagement.workflowState.totalPrice).
                                                customer.*, person.*, attributes.* and
                                                engagement.context.* are NOT resolvable
                                                here. Unlike the other roots,
                                                "engagement.conversation." takes ONE OF
                                                a closed set of keys —
                                                hoursSinceLastInbound, lastInboundText,
                                                lastInboundKind, documentCount,
                                                newDocumentCount — and any other key is
                                                refused at publish rather than resolving
                                                blank. A single formatting helper may
                                                follow the path ("| currency:MXN", "|
                                                count"), including on
                                                engagement.conversation.*, whose key is
                                                checked with the helper stripped off.
                                            occurred:
                                              type: boolean
                                          required:
                                            - kind
                                            - eventName
                                            - subjectSelectionPath
                                            - occurred
                                        - type: object
                                          properties:
                                            kind:
                                              type: string
                                              const: cdp_predicate
                                            term:
                                              type: object
                                              properties:
                                                attr:
                                                  type: string
                                                  minLength: 1
                                                  description: >-
                                                    Typed person column, `attributes.<key>`,
                                                    or `computed.<key>`. See
                                                    journeys_condition_catalog for the
                                                    available attributes.
                                                type:
                                                  type: string
                                                  enum:
                                                    - STRING
                                                    - NUMBER
                                                    - BOOLEAN
                                                    - DATE
                                                    - JSON
                                                    - ARRAY
                                                  description: >-
                                                    CDP attribute type. Determines which
                                                    `op` values are legal — see
                                                    journeys_condition_catalog.
                                                op:
                                                  type: string
                                                  minLength: 1
                                                  description: >-
                                                    Segments OperatorEnum value (eq | neq |
                                                    gt | lt | in_last_n | ...). Must be
                                                    legal for `type` — see
                                                    journeys_condition_catalog.
                                                value:
                                                  description: >-
                                                    Shape depends on `op`: a plain scalar
                                                    for eq/neq/gt/lt/starts_with/…, an array
                                                    for in/not_in/contains/not_contains,
                                                    {from, to} for between, {amount, unit}
                                                    for
                                                    in_last_n/in_next_n/more_than_n_ago/more_than_n_from_now,
                                                    {minAmount, maxAmount, unit} for
                                                    between_n_and_m_ago, {daysOffset} for
                                                    exactly_n_from_today. Omit entirely for
                                                    is_null/is_not_null.
                                                  anyOf:
                                                    - type: string
                                                    - type: number
                                                    - type: boolean
                                                    - type: array
                                                      items:
                                                        anyOf:
                                                          - type: string
                                                          - type: number
                                                    - type: object
                                                      properties:
                                                        from:
                                                          type: string
                                                        to:
                                                          type: string
                                                      required:
                                                        - from
                                                        - to
                                                    - type: object
                                                      properties:
                                                        amount:
                                                          type: integer
                                                          minimum: 1
                                                          maximum: 9999
                                                        unit:
                                                          type: string
                                                          enum:
                                                            - days
                                                            - weeks
                                                            - months
                                                      required:
                                                        - amount
                                                        - unit
                                                    - type: object
                                                      properties:
                                                        minAmount:
                                                          type: integer
                                                          minimum: 0
                                                          maximum: 9999
                                                        maxAmount:
                                                          type: integer
                                                          minimum: 1
                                                          maximum: 9999
                                                        unit:
                                                          type: string
                                                          enum:
                                                            - days
                                                            - weeks
                                                            - months
                                                      required:
                                                        - minAmount
                                                        - maxAmount
                                                        - unit
                                                    - type: object
                                                      properties:
                                                        daysOffset:
                                                          type: integer
                                                          minimum: -9007199254740991
                                                          maximum: 9007199254740991
                                                        rollForward:
                                                          type: object
                                                          properties:
                                                            fromDow:
                                                              type: integer
                                                              minimum: 0
                                                              maximum: 6
                                                            includeDows:
                                                              minItems: 1
                                                              type: array
                                                              items:
                                                                type: integer
                                                                minimum: 0
                                                                maximum: 6
                                                          required:
                                                            - fromDow
                                                            - includeDows
                                                      required:
                                                        - daysOffset
                                              required:
                                                - attr
                                                - type
                                                - op
                                              description: >-
                                                A single live person/computed predicate
                                                term. See journeys_condition_catalog for
                                                its shape and the legal operator/value
                                                pairing.
                                          required:
                                            - kind
                                            - term
                                        - type: object
                                          properties:
                                            kind:
                                              type: string
                                              const: cdp_object
                                            objectType:
                                              type: string
                                            matchAttr:
                                              type: string
                                            matchSelectionPath:
                                              type: string
                                              description: >-
                                                Dot-path into the run; must start with
                                                one of "engagement.workflowState.",
                                                "engagement.extracted.",
                                                "engagement.nodeOutputs.",
                                                "engagement.conversation." (e.g.
                                                engagement.workflowState.totalPrice).
                                                customer.*, person.*, attributes.* and
                                                engagement.context.* are NOT resolvable
                                                here. Unlike the other roots,
                                                "engagement.conversation." takes ONE OF
                                                a closed set of keys —
                                                hoursSinceLastInbound, lastInboundText,
                                                lastInboundKind, documentCount,
                                                newDocumentCount — and any other key is
                                                refused at publish rather than resolving
                                                blank. A single formatting helper may
                                                follow the path ("| currency:MXN", "|
                                                count"), including on
                                                engagement.conversation.*, whose key is
                                                checked with the helper stripped off.
                                            exists:
                                              type: boolean
                                          required:
                                            - kind
                                            - objectType
                                            - matchAttr
                                            - matchSelectionPath
                                            - exists
                                        - type: object
                                          properties:
                                            kind:
                                              type: string
                                              const: matched_object
                                            objectType:
                                              type: string
                                              minLength: 1
                                              description: >-
                                                Custom-object type whose matched rows
                                                (the rows that put this person in the
                                                entry segment,
                                                `workflowState.__matched.<type>`) are
                                                re-read LIVE. Segment-triggered journeys
                                                only; must be one of the segment's
                                                matched types.
                                            term:
                                              type: object
                                              properties:
                                                attr:
                                                  type: string
                                                  minLength: 1
                                                  description: >-
                                                    The BARE attribute key of the matched
                                                    object type, exactly as in its attribute
                                                    catalog (e.g. `order_status`). No
                                                    `attributes.`, `object.` or `computed.`
                                                    prefix. `type` must equal the catalogued
                                                    type.
                                                type:
                                                  type: string
                                                  enum:
                                                    - STRING
                                                    - NUMBER
                                                    - BOOLEAN
                                                    - DATE
                                                    - JSON
                                                    - ARRAY
                                                  description: >-
                                                    CDP attribute type. Determines which
                                                    `op` values are legal — see
                                                    journeys_condition_catalog.
                                                op:
                                                  type: string
                                                  minLength: 1
                                                  description: >-
                                                    Segments OperatorEnum value (eq | neq |
                                                    gt | lt | in_last_n | ...). Must be
                                                    legal for `type` — see
                                                    journeys_condition_catalog.
                                                value:
                                                  description: >-
                                                    Shape depends on `op`: a plain scalar
                                                    for eq/neq/gt/lt/starts_with/…, an array
                                                    for in/not_in/contains/not_contains,
                                                    {from, to} for between, {amount, unit}
                                                    for
                                                    in_last_n/in_next_n/more_than_n_ago/more_than_n_from_now,
                                                    {minAmount, maxAmount, unit} for
                                                    between_n_and_m_ago, {daysOffset} for
                                                    exactly_n_from_today. Omit entirely for
                                                    is_null/is_not_null.
                                                  anyOf:
                                                    - type: string
                                                    - type: number
                                                    - type: boolean
                                                    - type: array
                                                      items:
                                                        anyOf:
                                                          - type: string
                                                          - type: number
                                                    - type: object
                                                      properties:
                                                        from:
                                                          type: string
                                                        to:
                                                          type: string
                                                      required:
                                                        - from
                                                        - to
                                                    - type: object
                                                      properties:
                                                        amount:
                                                          type: integer
                                                          minimum: 1
                                                          maximum: 9999
                                                        unit:
                                                          type: string
                                                          enum:
                                                            - days
                                                            - weeks
                                                            - months
                                                      required:
                                                        - amount
                                                        - unit
                                                    - type: object
                                                      properties:
                                                        minAmount:
                                                          type: integer
                                                          minimum: 0
                                                          maximum: 9999
                                                        maxAmount:
                                                          type: integer
                                                          minimum: 1
                                                          maximum: 9999
                                                        unit:
                                                          type: string
                                                          enum:
                                                            - days
                                                            - weeks
                                                            - months
                                                      required:
                                                        - minAmount
                                                        - maxAmount
                                                        - unit
                                                    - type: object
                                                      properties:
                                                        daysOffset:
                                                          type: integer
                                                          minimum: -9007199254740991
                                                          maximum: 9007199254740991
                                                        rollForward:
                                                          type: object
                                                          properties:
                                                            fromDow:
                                                              type: integer
                                                              minimum: 0
                                                              maximum: 6
                                                            includeDows:
                                                              minItems: 1
                                                              type: array
                                                              items:
                                                                type: integer
                                                                minimum: 0
                                                                maximum: 6
                                                          required:
                                                            - fromDow
                                                            - includeDows
                                                      required:
                                                        - daysOffset
                                              required:
                                                - attr
                                                - type
                                                - op
                                              description: >-
                                                Condition on the row's CURRENT
                                                attributes. `attr` is the bare object
                                                attribute key (e.g. `order_status`, not
                                                `object.attributes.order_status`);
                                                `type`/`op`/`value` follow the same
                                                rules as a cdp_predicate term.
                                            quantifier:
                                              type: string
                                              enum:
                                                - any
                                                - all
                                              description: >-
                                                `any`: YES when at least one matched row
                                                passes. `all`: YES only when every
                                                matched row still exists and passes. No
                                                matched rows on the run → false.
                                          required:
                                            - kind
                                            - objectType
                                            - term
                                            - quantifier
                                      description: One decision condition.
                                  description:
                                    type: string
                                required:
                                  - logic
                                  - conditions
                                description: Two-way branch. Emits YES / NO.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: CASE
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  selectionPath:
                                    type: string
                                    description: >-
                                      Value to switch on; must start with one of
                                      "attributes.", "engagement.extracted.",
                                      "engagement.nodeOutputs.", "matched."
                                      (e.g. attributes.plan_tier).
                                      "matched.<type>.<attr>" (e.g.
                                      matched.order.order_status) switches on
                                      the CURRENT value of an attribute of the
                                      row that put the person in the entry
                                      segment — the first matched row of that
                                      type, read live; segment-triggered
                                      journeys only, and the type must be in the
                                      segment's matched types. A formatting
                                      helper ("| currency:MXN", "| count") is
                                      REFUSED here, unlike on a DECISION
                                      condition: CASE reads this path raw, so a
                                      helper would resolve blank and route
                                      case:default on every run.
                                  branches:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: string
                                          description: >-
                                            Stable branch id; edge handle is
                                            case:<id>.
                                        value:
                                          type: string
                                          description: Value matched. Unique within the node.
                                        label:
                                          type: string
                                          minLength: 1
                                          description: >-
                                            Required. Names the variant in analytics
                                            and on canvas.
                                      required:
                                        - id
                                        - value
                                        - label
                                    description: >-
                                      Up to 10 branches. A case:default handle
                                      is always required.
                                  description:
                                    type: string
                                required:
                                  - selectionPath
                                  - branches
                                description: N-way switch on a person attribute.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: RANDOM_SPLIT
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  arms:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: string
                                          description: >-
                                            Stable arm id; edge handle is
                                            split:<id>.
                                        weight:
                                          type: integer
                                          minimum: 1
                                          maximum: 100
                                          description: >-
                                            Integer percentage. A node's arms must
                                            total 100.
                                        label:
                                          type: string
                                      required:
                                        - id
                                        - weight
                                    description: >-
                                      At least 2 and at most 10 arms whose
                                      weights total exactly 100. There is no
                                      default handle — every roll lands on a
                                      declared arm.
                                  description:
                                    type: string
                                required:
                                  - arms
                                description: >-
                                  Randomly routes each run down one of N
                                  weighted arms.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: HTTP_REQUEST
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  method:
                                    type: string
                                    enum:
                                      - GET
                                      - POST
                                      - PUT
                                      - PATCH
                                      - DELETE
                                    description: HTTP method.
                                  url:
                                    type: string
                                    minLength: 1
                                    description: >-
                                      Target URL. Supports {{variable}}
                                      placeholders. Resolvable roots here:
                                      customer.<field> (a single flat field of
                                      the customer record), person.<attribute>
                                      (CDP), env.<key> (journey environment),
                                      engagement.context.*,
                                      engagement.workflowState.*,
                                      engagement.extracted.*,
                                      engagement.nodeOutputs.<nodeId>.*,
                                      engagement.documents (json body, whole
                                      quoted token, flag-gated), and
                                      engagement.conversation.id /
                                      engagement.conversation.inboxUrl — the
                                      conversation this run is talking to and
                                      its Shared Inbox deep link. Anything else
                                      substitutes as an empty string and is
                                      reported at publish as
                                      UNRESOLVABLE_HTTP_TOKEN. Note
                                      engagement.chatLink is SEND_EMAIL-only and
                                      does NOT resolve here.
                                  headers:
                                    description: >-
                                      Request headers as key/value pairs. Values
                                      support the same {{variable}} placeholders
                                      as the url. Resolvable roots here:
                                      customer.<field> (a single flat field of
                                      the customer record), person.<attribute>
                                      (CDP), env.<key> (journey environment),
                                      engagement.context.*,
                                      engagement.workflowState.*,
                                      engagement.extracted.*,
                                      engagement.nodeOutputs.<nodeId>.*,
                                      engagement.documents (json body, whole
                                      quoted token, flag-gated), and
                                      engagement.conversation.id /
                                      engagement.conversation.inboxUrl — the
                                      conversation this run is talking to and
                                      its Shared Inbox deep link. Anything else
                                      substitutes as an empty string and is
                                      reported at publish as
                                      UNRESOLVABLE_HTTP_TOKEN. Note
                                      engagement.chatLink is SEND_EMAIL-only and
                                      does NOT resolve here.
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        key:
                                          type: string
                                        value:
                                          type: string
                                      required:
                                        - key
                                        - value
                                  body:
                                    description: >-
                                      Request body. mode none sends no body.
                                      Supports the same {{variable}}
                                      placeholders as the url; in json mode a
                                      whole quoted token
                                      ("{{engagement.documents}}") substitutes
                                      as a JSON array. Resolvable roots here:
                                      customer.<field> (a single flat field of
                                      the customer record), person.<attribute>
                                      (CDP), env.<key> (journey environment),
                                      engagement.context.*,
                                      engagement.workflowState.*,
                                      engagement.extracted.*,
                                      engagement.nodeOutputs.<nodeId>.*,
                                      engagement.documents (json body, whole
                                      quoted token, flag-gated), and
                                      engagement.conversation.id /
                                      engagement.conversation.inboxUrl — the
                                      conversation this run is talking to and
                                      its Shared Inbox deep link. Anything else
                                      substitutes as an empty string and is
                                      reported at publish as
                                      UNRESOLVABLE_HTTP_TOKEN. Note
                                      engagement.chatLink is SEND_EMAIL-only and
                                      does NOT resolve here.
                                    type: object
                                    properties:
                                      mode:
                                        type: string
                                        enum:
                                          - none
                                          - json
                                          - raw
                                      content:
                                        type: string
                                      contentType:
                                        type: string
                                    required:
                                      - mode
                                  credentialId:
                                    description: >-
                                      Deprecated/legacy: HttpCredential row id
                                      used to authenticate the request. Prefer
                                      credentialKey.
                                    type: string
                                  credentialKey:
                                    description: >-
                                      Logical credential key; the pinned
                                      environment selects the secret.
                                    type: string
                                  timeoutMs:
                                    description: >-
                                      Request timeout in milliseconds. Max 30000
                                      (30s).
                                    type: integer
                                    exclusiveMinimum: 0
                                    maximum: 30000
                                  maxAttempts:
                                    description: Max attempts including the first. Max 5.
                                    type: integer
                                    exclusiveMinimum: 0
                                    maximum: 5
                                  documentUrlTtlSeconds:
                                    description: >-
                                      TTL (seconds, ≤86400) for presigned
                                      engagement.documents URLs this node emits.
                                      Default 86400.
                                    type: integer
                                    exclusiveMinimum: 0
                                    maximum: 86400
                                  documentMimeTypes:
                                    description: >-
                                      Allowlist of MIME types this node may
                                      egress in engagement.documents, e.g.
                                      ['application/pdf'] for an endpoint that
                                      only accepts PDFs. Omit (or pass an empty
                                      list) to send every document type — the
                                      default. A document whose type is not
                                      listed is withheld and counted in the
                                      step's documents.filteredCount, never
                                      silently dropped. Match is exact, trimmed
                                      and case-insensitive; a document with no
                                      recorded type is withheld whenever a list
                                      is set. Each entry must be a MIME type an
                                      inbound document can actually have,
                                      because a well-formed typo would match
                                      nothing and withhold everything:
                                      image/jpeg, image/png, image/webp,
                                      image/gif, application/pdf, video/mp4,
                                      text/vcard, text/html, application/msword,
                                      application/vnd.ms-excel,
                                      application/vnd.openxmlformats-officedocument.wordprocessingml.document,
                                      application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
                                      application/octet-stream.
                                    type: array
                                    items:
                                      type: string
                                      minLength: 1
                                required:
                                  - method
                                  - url
                                description: >-
                                  Calls an external HTTP endpoint. Emits SUCCESS
                                  or FAILED.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: ROUTE_TO_INITIATIVE
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  initiativeId:
                                    type: string
                                    minLength: 1
                                    description: >-
                                      Target initiative id to enroll this
                                      customer into.
                                  context:
                                    description: >-
                                      Values stamped onto the new engagement,
                                      readable by its agent. A literal string,
                                      or { var: 'engagement.extracted.<slug>' }
                                      resolved at route time.
                                    type: object
                                    propertyNames:
                                      type: string
                                    additionalProperties:
                                      anyOf:
                                        - type: string
                                        - type: object
                                          properties:
                                            var:
                                              type: string
                                          required:
                                            - var
                                  description:
                                    type: string
                                required:
                                  - initiativeId
                                description: >-
                                  Terminal. Ends this engagement and enrolls the
                                  customer into another initiative, moving the
                                  live conversation onto a new session. Emits no
                                  signals — it has no outgoing edges.
                            required:
                              - id
                              - kind
                          - type: object
                            properties:
                              id:
                                type: string
                                minLength: 1
                                description: Node id, unique within the journey.
                              kind:
                                type: string
                                const: EXIT
                              name:
                                type: string
                                minLength: 1
                                description: >-
                                  The label shown on the canvas. Required before
                                  publishing.
                              position:
                                type: object
                                properties:
                                  x:
                                    type: number
                                  'y':
                                    type: number
                                required:
                                  - x
                                  - 'y'
                                description: >-
                                  Explicit canvas position. Omit it and the
                                  server auto-lays-out the graph top-down; only
                                  set it to preserve a hand-arranged layout.
                              inputs:
                                type: object
                                properties:
                                  outcome:
                                    type: string
                                description: Terminal node.
                            required:
                              - id
                              - kind
                      description: >-
                        The nodes. Exactly one ENTRY, and at least one end point
                        (EXIT or ROUTE_TO_INITIATIVE), are required to publish.
                    edges:
                      type: array
                      items:
                        type: object
                        properties:
                          from:
                            type: string
                            description: Source node id.
                          to:
                            type: string
                            description: Target node id.
                          sourceHandle:
                            type: string
                            description: >-
                              The emitted signal that activates this edge (e.g.
                              SENT, REPLIED, YES, case:<id>). A handle may wire
                              to at most one node.
                          metadata:
                            type: object
                            properties:
                              signalCategory:
                                type: string
                                enum:
                                  - lifecycle
                                  - system
                              signalDescription:
                                type: string
                        required:
                          - from
                          - to
                          - sourceHandle
                        description: >-
                          A connection: node `from` routes to `to` when it emits
                          `sourceHandle`.
                      description: The connections between node handles.
                  required:
                    - name
                    - actions
                    - edges
                  description: >-
                    The full journey graph. Drafts may be incomplete; run
                    journeys_validate before publishing.
              required:
                - definition
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $schema: https://json-schema.org/draft/2020-12/schema
                type: object
                properties:
                  id:
                    type: string
                    description: Journey (workflow version) id.
                  initiativeId:
                    type: string
                    description: The initiative this journey belongs to.
                  status:
                    type: string
                    enum:
                      - DRAFT
                      - PUBLISHED
                      - STOPPED
                    description: >-
                      DRAFT (editable), PUBLISHED (live, frozen), or STOPPED
                      (retired).
                  version:
                    type: integer
                    minimum: -9007199254740991
                    maximum: 9007199254740991
                    description: Version number within the initiative.
                  definition:
                    type: object
                    properties:
                      id:
                        description: >-
                          Journey id; carried for round-trip ergonomics.
                          Optional on create.
                        type: string
                      name:
                        type: string
                        minLength: 1
                        description: Journey name.
                      metadata:
                        type: object
                        properties:
                          initiativeType:
                            type: string
                          version:
                            type: integer
                            minimum: -9007199254740991
                            maximum: 9007199254740991
                          cancelOnEvents:
                            description: >-
                              Cancel an in-flight run when any of these events
                              arrive.
                            type: object
                            properties:
                              eventNames:
                                type: array
                                items:
                                  type: string
                              matchRunKey:
                                description: >-
                                  Cancel only the run whose key equals this
                                  event's `parallelRunsBy` property, instead of
                                  every run the person has. Leave it unset on a
                                  journey with several runs at once: that
                                  already matches on the key, and setting it to
                                  false there is refused at publish, because one
                                  completed payment would stop the person's
                                  other payments too.
                                type: boolean
                            required:
                              - eventNames
                            additionalProperties: false
                          environmentId:
                            description: >-
                              Pinned environment whose non-secret {{env.*}}
                              values HTTP nodes resolve against. Frozen at
                              publish. The server preserves the stored value
                              when a whole-graph update omits it.
                            type: string
                        additionalProperties: false
                        description: Optional journey-level metadata.
                      actions:
                        minItems: 1
                        type: array
                        items:
                          oneOf:
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: ENTRY
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    description:
                                      type: string
                                    triggerType:
                                      description: >-
                                        How people enter: manual (added by an
                                        operator or API call), segment (on
                                        entering a segment), cdp_event (when an
                                        event is received), or inbound (when a
                                        message arrives on one of the org's
                                        channels). Defaults to manual.
                                      type: string
                                      enum:
                                        - manual
                                        - segment
                                        - cdp_event
                                        - inbound
                                    segmentId:
                                      description: >-
                                        Segment id — required when triggerType
                                        is segment.
                                      type: string
                                    segmentName:
                                      description: Cached segment display name (optional).
                                      type: string
                                    eventName:
                                      description: >-
                                        CDP event name — required when
                                        triggerType is cdp_event.
                                      type: string
                                    inboundAction:
                                      description: >-
                                        Which arrival fires the trigger —
                                        required when triggerType is inbound.
                                        INSTAGRAM_COMMENT / FACEBOOK_COMMENT
                                        listen to public comments on the
                                        account's posts instead of DMs; they
                                        require Instagram or Messenger channels
                                        whose connection was granted comment
                                        permission, and enroll the commenter
                                        without opening a conversation.
                                      type: string
                                      enum:
                                        - WHATSAPP_MESSAGE
                                        - SMS_MESSAGE
                                        - INSTAGRAM_MESSAGE
                                        - MESSENGER_MESSAGE
                                        - INSTAGRAM_COMMENT
                                        - FACEBOOK_COMMENT
                                    inboundChannelIds:
                                      description: >-
                                        Channel ids to listen on — at least one
                                        required when triggerType is inbound.
                                        Must be NATIVE WhatsApp, SMS, Instagram
                                        or Messenger channels that are not
                                        deleted — WhatsApp and SMS additionally
                                        need an ONLINE sender, Instagram and
                                        Messenger have no sender row and need
                                        none (a Messenger Page still on the V1
                                        bridge is withheld as NOT_NATIVE);
                                        journeys_set_trigger names the eligible
                                        ids if you pass an ineligible one. For a
                                        comment action, only Instagram and
                                        Messenger channels are valid. Several
                                        published journeys may share one channel
                                        as long as their keywords differ:
                                        publishing a rule whose keyword (or
                                        blank catch-all) is already taken on
                                        that channel is refused with
                                        INBOUND_CHANNEL_TAKEN. Each arriving
                                        message enrols exactly one of them, the
                                        most specific matching rule, ties going
                                        to the older initiative.
                                      type: array
                                      items:
                                        type: string
                                    inboundKeyword:
                                      description: >-
                                        The word the inbound message must match
                                        for this journey to enrol — e.g.
                                        'PRECIO'. Blank or absent means the
                                        trigger is the catch-all and fires on
                                        ANY message arriving on the channel,
                                        which is almost never what you want
                                        beside other journeys on the same
                                        number. Several journeys may share one
                                        channel as long as their keywords differ
                                        — two rules with the same keyword on one
                                        channel, or two blank ones, are refused
                                        at publish with INBOUND_CHANNEL_TAKEN.
                                        The keyword is matched accent-, case-
                                        and punctuation-insensitively, and
                                        stored normalized.
                                      type: string
                                    inboundMatchMode:
                                      description: >-
                                        How inboundKeyword is matched: EXACT
                                        (the message is only-the-word),
                                        ALL_WORDS (the message contains
                                        all-the-words, in any order), or
                                        CONTAINS (the message contains-the-word,
                                        adjacent and in order). All three are
                                        word-based, so no mode ever matches
                                        inside a longer word ('precioso' does
                                        not match 'precio'). Defaults to EXACT.
                                        Ignored when inboundKeyword is blank.
                                      type: string
                                      enum:
                                        - EXACT
                                        - CONTAINS
                                        - ALL_WORDS
                                    maxEnrollments:
                                      description: >-
                                        Frequency cap: max enrollments per
                                        person within enrollmentWindow.
                                        Both-or-neither with enrollmentWindow.
                                      type: integer
                                      minimum: 1
                                      maximum: 9007199254740991
                                    enrollmentWindow:
                                      description: Rolling window for the frequency cap.
                                      type: string
                                    parallelRunsBy:
                                      description: >-
                                        Let one person have several runs of this
                                        journey at the same time, one per
                                        distinct value of this event property
                                        (e.g. "paymentLinkId"). Use it when a
                                        person can have several of the same
                                        thing in flight, two payment links or
                                        two orders, and each needs its own
                                        sequence. Three things to know. It works
                                        on cdp_event triggers only, because the
                                        run is identified by a property of the
                                        triggering event; an event that does not
                                        carry the property is refused rather
                                        than enrolled. The journey becomes SEND
                                        ONLY: no wait-for-reply, conversation or
                                        AI nodes, because an inbound message
                                        belongs to the person and not to one
                                        run, so a single reply would wake every
                                        run at once. And every stop event listed
                                        in cancelOnEvents matches on this same
                                        property, so a completed one stops only
                                        its own run and leaves the person's
                                        other runs alive. Publish is refused if
                                        any of that is violated.
                                      type: string
                                      minLength: 1
                                  additionalProperties: false
                                  description: >-
                                    Trigger node config. Exactly one ENTRY node
                                    per journey.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: SEND_MESSAGE
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    mode:
                                      description: >-
                                        What this send carries: 'template' (an
                                        approved WhatsApp template, the default
                                        when omitted) or 'free_text' (prose you
                                        write, needing `body` instead of
                                        `templateId`). free_text emits SENT and
                                        WINDOW_CLOSED, both of which must be
                                        wired — Meta accepts free-form content
                                        only within 24 hours of the customer's
                                        last message, checked before sending.
                                        Prefer this over the deprecated
                                        SEND_WHATSAPP_TEXT node, which is the
                                        same send under an older name.
                                      type: string
                                      enum:
                                        - template
                                        - free_text
                                    templateId:
                                      description: >-
                                        Approved WhatsApp template id. Resolve
                                        ids from the catalog.
                                      type: string
                                    templateName:
                                      type: string
                                    body:
                                      description: >-
                                        The message text, for mode 'free_text'
                                        only. Placeholders are named, like
                                        {{customer.name}}, and EVERY one must
                                        have a matching entry in `bindings` or
                                        publish is refused: an unbound
                                        placeholder is sent literally, braces
                                        and all. Bind an upstream HTTP response
                                        with
                                        engagement.nodeOutputs.<nodeId>.body.<field>.
                                      type: string
                                    bindings:
                                      description: >-
                                        Map of {{placeholder}} name → variable
                                        reference, for `body`. Template mode
                                        uses `templateBindings` instead.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                    channel:
                                      description: >-
                                        Always whatsapp. Other channels have
                                        their own node kind — SEND_SMS for a
                                        text, SEND_INSTAGRAM for Instagram,
                                        SEND_MESSENGER for Facebook Messenger.
                                      type: string
                                      const: whatsapp
                                    templateBindings:
                                      description: >-
                                        Map of template placeholder → variable
                                        reference, or fixed text prefixed
                                        `literal:` (e.g. `{ "2":
                                        "literal:BIENVENIDA20" }`) for a value
                                        that is the same for every recipient.
                                        EVERY placeholder the template declares
                                        (body, header, footer, button URL) needs
                                        an entry or publish is refused, since an
                                        unbound one is sent literally. The only
                                        exception: a template whose sole
                                        placeholder is {{1}}, with no map at
                                        all, falls back to the customer name
                                        (not on a Transactional).
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                    channelId:
                                      description: >-
                                        Sending WhatsApp channel (WABA) id.
                                        Required before publishing.
                                      type: string
                                    sendImmediately:
                                      description: >-
                                        Deprecated business-hours gate; prefer a
                                        preceding DELAY.
                                      type: boolean
                                    delivery:
                                      description: >-
                                        'draft' holds the rendered send in the
                                        Drafts queue until an org member
                                        approves or rejects it; the run waits at
                                        this node. Approve sends it and
                                        continues on SENT; reject emits REJECTED
                                        (optional edge — unwired, the run ends).
                                        Omit for 'immediate'. Refused on a
                                        Transactional initiative's journey
                                        (`transactional_draft_delivery`): a
                                        notification must go out. Refused
                                        (`drafts_disabled`) while drafts are
                                        turned off for the organization; a
                                        published drafted send reached while
                                        they're off is skipped (SKIPPED), never
                                        sent unreviewed.
                                      type: string
                                      enum:
                                        - immediate
                                        - draft
                                  additionalProperties: false
                                  description: >-
                                    Sends WhatsApp: an approved template
                                    (default), or free-text prose with mode
                                    'free_text'.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: SEND_SMS
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    body:
                                      description: >-
                                        The message text. Free text — SMS has no
                                        approved-template concept. Placeholders
                                        are named, like {{customer.name}}, and
                                        EVERY one must have a matching entry in
                                        `bindings` or publish is refused: an
                                        unbound placeholder is sent literally,
                                        braces and all. The opt-out footer and
                                        the brand are added by the system; do
                                        not write them into the body.
                                      type: string
                                    channelId:
                                      description: >-
                                        Sending SMS channel id. Required before
                                        publishing.
                                      type: string
                                    bindings:
                                      description: >-
                                        Map of {{placeholder}} name → variable
                                        reference. The builder writes the path
                                        as its own name ({"customer.name":
                                        "customer.name"}); an alias is allowed
                                        as long as the body uses the alias.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                    optOutText:
                                      description: >-
                                        Opt-out line for this node, overriding
                                        the organization's. Must contain the
                                        STOP keyword. Omit to use the
                                        organization's.
                                      type: string
                                    allowEmoji:
                                      description: >-
                                        Keep emoji instead of stripping them.
                                        Defaults to false, because emoji force
                                        UCS-2 encoding, which cuts a message
                                        part from 160 characters to 70 and
                                        roughly doubles the cost.
                                      type: boolean
                                  additionalProperties: false
                                  description: Sends a plain-text SMS.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: SEND_WHATSAPP_TEXT
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    body:
                                      description: >-
                                        The message text. Free text — no Meta
                                        template approval needed, which is the
                                        point of this node. Placeholders are
                                        named, like {{customer.name}}, and EVERY
                                        one must have a matching entry in
                                        `bindings` or publish is refused: an
                                        unbound placeholder is sent literally,
                                        braces and all. Bind an upstream HTTP
                                        response with
                                        engagement.nodeOutputs.<nodeId>.body.<field>.
                                      type: string
                                    channelId:
                                      description: >-
                                        Sending WhatsApp channel (WABA) id.
                                        Required before publishing; it is also
                                        the per-number send throttle key.
                                      type: string
                                    bindings:
                                      description: >-
                                        Map of {{placeholder}} name → variable
                                        reference. The builder writes the path
                                        as its own name ({"customer.name":
                                        "customer.name"}); an alias is allowed
                                        as long as the body uses the alias.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                  additionalProperties: false
                                  description: >-
                                    Sends free-text WhatsApp — author-written
                                    prose instead of an approved template. Emits
                                    SENT or WINDOW_CLOSED, and BOTH must be
                                    wired. Meta accepts free-form content only
                                    within 24 hours of the customer's last
                                    message; the node checks that BEFORE sending
                                    (Twilio would accept an out-of-window
                                    message and fail it asynchronously with
                                    63016), so WINDOW_CLOSED means nothing was
                                    sent and is where you put an approved
                                    template. A node with no upstream
                                    WAIT_FOR_REPLY / MANAGE_CONVERSATION will
                                    usually take WINDOW_CLOSED — publish warns
                                    but does not block, because a customer who
                                    wrote recently on this number in ANY journey
                                    still has an open window.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: SEND_INSTAGRAM
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    body:
                                      description: >-
                                        The message text. Free text — Instagram
                                        has no approved-template concept.
                                        Placeholders are named, like
                                        {{customer.name}}, and EVERY one must
                                        have a matching entry in `bindings` or
                                        publish is refused: an unbound
                                        placeholder is sent literally, braces
                                        and all.
                                      type: string
                                    channelId:
                                      description: >-
                                        Sending native Instagram channel id.
                                        Required before publishing, with no
                                        org-primary fallback.
                                      type: string
                                    bindings:
                                      description: >-
                                        Map of {{placeholder}} name → variable
                                        reference. The builder writes the path
                                        as its own name ({"customer.name":
                                        "customer.name"}); an alias is allowed
                                        as long as the body uses the alias.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                  additionalProperties: false
                                  description: >-
                                    Sends free-text Instagram from a chosen
                                    native account — no template concept, so
                                    every message is author-written prose. Emits
                                    SENT or WINDOW_CLOSED, and BOTH must be
                                    wired. Meta accepts free-form content only
                                    within 24 hours of the customer's last
                                    message; the node checks that BEFORE
                                    sending, so WINDOW_CLOSED means nothing was
                                    sent. Instagram has no template fallback, so
                                    WINDOW_CLOSED usually leads to EXIT — say so
                                    explicitly rather than leaving it dangling.
                                    Exception: in a run an INSTAGRAM_COMMENT
                                    trigger started, a shut window sends one
                                    private reply to that comment instead (same
                                    account, comment under 7 days old and not
                                    yet replied to); Meta decides whether it
                                    lands.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: SEND_EMAIL
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    templateId:
                                      description: >-
                                        A PUBLISHED email template id from
                                        journeys_email_templates. Required
                                        before publishing; a draft or archived
                                        template is refused at publish.
                                      type: string
                                    templateName:
                                      description: >-
                                        The template's name, cached so the
                                        canvas can label the node without a
                                        lookup. Copy it from
                                        journeys_email_templates.
                                      type: string
                                    bindings:
                                      description: >-
                                        Map of the template's variable key (its
                                        `variables[].key` in
                                        journeys_email_templates) → variable
                                        reference such as customer.name, or
                                        engagement.chatLink for the link that
                                        opens this run's web chat. Bind only
                                        what you want to reroute: a variable
                                        left out resolves its own `path`, as the
                                        template was authored.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                    fromSenderIdOverride:
                                      description: >-
                                        Sender id to send From for this node
                                        only, overriding the template's pick and
                                        the org default. Must be a sender with
                                        usableAsFrom: true in
                                        journeys_email_templates. Omit to
                                        inherit.
                                      type: string
                                    replyToSenderIdOverride:
                                      description: >-
                                        Sender id to use as Reply-To for this
                                        node only. Omit to inherit the template,
                                        then the org default.
                                      type: string
                                    delivery:
                                      description: >-
                                        'draft' holds the rendered send in the
                                        Drafts queue until an org member
                                        approves or rejects it; the run waits at
                                        this node. Approve sends it and
                                        continues on SENT; reject emits REJECTED
                                        (optional edge — unwired, the run ends).
                                        Omit for 'immediate'. Refused on a
                                        Transactional initiative's journey
                                        (`transactional_draft_delivery`): a
                                        notification must go out. Refused
                                        (`drafts_disabled`) while drafts are
                                        turned off for the organization; a
                                        published drafted send reached while
                                        they're off is skipped (SKIPPED), never
                                        sent unreviewed.
                                      type: string
                                      enum:
                                        - immediate
                                        - draft
                                  additionalProperties: false
                                  description: >-
                                    Sends a PUBLISHED email template to the
                                    customer.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: SEND_MESSENGER
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    body:
                                      description: >-
                                        The message text, at most 2000
                                        characters. Free text — no
                                        approved-template concept. Placeholders
                                        are named, like {{customer.name}}, and
                                        EVERY one must have a matching entry in
                                        `bindings` or publish is refused: an
                                        unbound placeholder is sent literally,
                                        braces and all.
                                      type: string
                                    channelId:
                                      description: >-
                                        Sending native Messenger channel
                                        (Facebook Page) id, from
                                        journeys_message_channels (sendNodeKind
                                        SEND_MESSENGER). Required before
                                        publishing, with no org-primary
                                        fallback.
                                      type: string
                                    bindings:
                                      description: >-
                                        Map of {{placeholder}} name → variable
                                        reference. The builder writes the path
                                        as its own name ({"customer.name":
                                        "customer.name"}); an alias is allowed
                                        as long as the body uses the alias.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        type: string
                                  additionalProperties: false
                                  description: >-
                                    Sends free-text Facebook Messenger from a
                                    chosen Page — every message is
                                    author-written prose. Emits SENT or
                                    WINDOW_CLOSED, and BOTH must be wired. Meta
                                    accepts it only within 24 hours of the
                                    customer's last message; the node checks
                                    that BEFORE sending, so WINDOW_CLOSED means
                                    nothing was sent. There is no template
                                    fallback, so WINDOW_CLOSED usually leads to
                                    EXIT — say so explicitly rather than leaving
                                    it dangling. Exception: in a run an
                                    FACEBOOK_COMMENT trigger started, a shut
                                    window sends one private reply to that
                                    comment instead (same Page, comment under 7
                                    days old and not yet replied to); Meta
                                    decides whether it lands.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: CONVERSATION_BLOCK
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    goal:
                                      type: string
                                    maxTimeout:
                                      description: >-
                                        How long to wait for a reply before
                                        timing out.
                                      type: string
                                    mode:
                                      type: string
                                      enum:
                                        - AGENT
                                        - ESCALATE
                                    outputs:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          id:
                                            type: string
                                          label:
                                            type: string
                                          type:
                                            type: string
                                            enum:
                                              - string
                                              - number
                                              - date
                                              - boolean
                                              - json
                                          description:
                                            type: string
                                          builtin:
                                            type: boolean
                                        required:
                                          - id
                                          - label
                                          - type
                                          - builtin
                                        additionalProperties: false
                                  additionalProperties: false
                                  description: >-
                                    Legacy combined wait + AI conversation
                                    block.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: WAIT_FOR_REPLY
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    maxTimeout:
                                      description: >-
                                        How long to wait for the first reply
                                        before timing out.
                                      type: string
                                  additionalProperties: false
                                  description: Waits for the person to reply.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: MANAGE_CONVERSATION
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    mode:
                                      description: >-
                                        AGENT (AI-led) or ESCALATE (human
                                        handoff). Defaults to AGENT.
                                      type: string
                                      enum:
                                        - AGENT
                                        - ESCALATE
                                    goal:
                                      description: >-
                                        Instructions for this conversation step
                                        only, on top of the initiative objective
                                        (e.g. 'Confirm the delivery address
                                        before anything else'). AGENT mode only;
                                        ignored in ESCALATE.
                                      type: string
                                    inactivityTimeout:
                                      description: >-
                                        Optional custom idle window (e.g. '2h',
                                        '30m') that overrides the global
                                        inactive-conversation close. Resets on
                                        each inbound message; after this much
                                        silence the node closes the conversation
                                        (routes CLOSED), unless the AI has
                                        escalated it to a human, in which case
                                        it stays open. Hard cap 24h; under 30m
                                        is allowed but flagged 'not
                                        recommended'. Requires the
                                        journey-inactivity-timeout flag.
                                      type: string
                                  additionalProperties: false
                                  description: Runs the AI-led conversation.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: DISPATCH_EVENT
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    eventName:
                                      type: string
                                      minLength: 1
                                      description: >-
                                        CDP event name to record. Must match the
                                        CDP name pattern.
                                    properties:
                                      description: >-
                                        Literal string values, or { var: path }
                                        bindings resolved to typed values at
                                        dispatch time.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        anyOf:
                                          - type: string
                                          - type: object
                                            properties:
                                              var:
                                                type: string
                                            required:
                                              - var
                                            additionalProperties: false
                                    description:
                                      type: string
                                  required:
                                    - eventName
                                  additionalProperties: false
                                  description: Records a CDP event for the person.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: DELAY
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    mode:
                                      description: >-
                                        How the wait is measured. Defaults to
                                        duration.
                                      type: string
                                      enum:
                                        - duration
                                        - until_date
                                        - until_weekday
                                    duration:
                                      description: For mode duration.
                                      type: string
                                    targetAt:
                                      description: ISO 8601 instant, for mode until_date.
                                      type: string
                                    weekdays:
                                      description: >-
                                        ISO weekdays 1=Mon..7=Sun, for mode
                                        until_weekday.
                                      type: array
                                      items:
                                        type: integer
                                        minimum: 1
                                        maximum: 7
                                    windowStartMinutes:
                                      type: integer
                                      minimum: 0
                                      maximum: 1439
                                    windowEndMinutes:
                                      type: integer
                                      minimum: 0
                                      maximum: 1439
                                    timezone:
                                      description: >-
                                        IANA timezone. Load-bearing for
                                        until_weekday.
                                      type: string
                                    description:
                                      type: string
                                  additionalProperties: false
                                  description: Pauses the run.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: DECISION
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    logic:
                                      type: string
                                      enum:
                                        - AND
                                        - OR
                                    conditions:
                                      type: array
                                      items:
                                        oneOf:
                                          - type: object
                                            properties:
                                              kind:
                                                type: string
                                                const: value
                                              selectionPath:
                                                type: string
                                                description: >-
                                                  Dot-path into the run; must start with
                                                  one of "engagement.workflowState.",
                                                  "engagement.extracted.",
                                                  "engagement.nodeOutputs.",
                                                  "engagement.conversation." (e.g.
                                                  engagement.workflowState.totalPrice).
                                                  customer.*, person.*, attributes.* and
                                                  engagement.context.* are NOT resolvable
                                                  here. Unlike the other roots,
                                                  "engagement.conversation." takes ONE OF
                                                  a closed set of keys —
                                                  hoursSinceLastInbound, lastInboundText,
                                                  lastInboundKind, documentCount,
                                                  newDocumentCount — and any other key is
                                                  refused at publish rather than resolving
                                                  blank. A single formatting helper may
                                                  follow the path ("| currency:MXN", "|
                                                  count"), including on
                                                  engagement.conversation.*, whose key is
                                                  checked with the helper stripped off.
                                              operator:
                                                type: string
                                                enum:
                                                  - eq
                                                  - neq
                                                  - gt
                                                  - lt
                                                  - contains
                                                  - matchesKeyword
                                                  - isSet
                                                description: >-
                                                  How to compare. `contains` is a plain
                                                  substring test, so "precio" also matches
                                                  "precioso". `matchesKeyword` is the
                                                  ENTRY inbound-trigger matcher instead —
                                                  accent- and case-folded, matched on word
                                                  boundaries — so an author who writes the
                                                  same word on a trigger and mid-journey
                                                  gets the same answer. Use
                                                  `matchesKeyword` to route by what the
                                                  customer said; a value that folds to no
                                                  letters or digits is refused at publish,
                                                  because it would match every message.
                                                  Must also suit the selected field: text
                                                  tests (`contains`, `matchesKeyword`) are
                                                  refused on a number, and ordering (`gt`,
                                                  `lt`) on text — see
                                                  DECISION_OPERATOR_TYPE_MISMATCH.
                                              value:
                                                type: string
                                            required:
                                              - kind
                                              - selectionPath
                                              - operator
                                              - value
                                            additionalProperties: false
                                          - type: object
                                            properties:
                                              kind:
                                                type: string
                                                const: event
                                              eventName:
                                                type: string
                                              subjectSelectionPath:
                                                type: string
                                                description: >-
                                                  Dot-path into the run; must start with
                                                  one of "engagement.workflowState.",
                                                  "engagement.extracted.",
                                                  "engagement.nodeOutputs.",
                                                  "engagement.conversation." (e.g.
                                                  engagement.workflowState.totalPrice).
                                                  customer.*, person.*, attributes.* and
                                                  engagement.context.* are NOT resolvable
                                                  here. Unlike the other roots,
                                                  "engagement.conversation." takes ONE OF
                                                  a closed set of keys —
                                                  hoursSinceLastInbound, lastInboundText,
                                                  lastInboundKind, documentCount,
                                                  newDocumentCount — and any other key is
                                                  refused at publish rather than resolving
                                                  blank. A single formatting helper may
                                                  follow the path ("| currency:MXN", "|
                                                  count"), including on
                                                  engagement.conversation.*, whose key is
                                                  checked with the helper stripped off.
                                              occurred:
                                                type: boolean
                                            required:
                                              - kind
                                              - eventName
                                              - subjectSelectionPath
                                              - occurred
                                            additionalProperties: false
                                          - type: object
                                            properties:
                                              kind:
                                                type: string
                                                const: cdp_predicate
                                              term:
                                                type: object
                                                properties:
                                                  attr:
                                                    type: string
                                                    minLength: 1
                                                    description: >-
                                                      Typed person column, `attributes.<key>`,
                                                      or `computed.<key>`. See
                                                      journeys_condition_catalog for the
                                                      available attributes.
                                                  type:
                                                    type: string
                                                    enum:
                                                      - STRING
                                                      - NUMBER
                                                      - BOOLEAN
                                                      - DATE
                                                      - JSON
                                                      - ARRAY
                                                    description: >-
                                                      CDP attribute type. Determines which
                                                      `op` values are legal — see
                                                      journeys_condition_catalog.
                                                  op:
                                                    type: string
                                                    minLength: 1
                                                    description: >-
                                                      Segments OperatorEnum value (eq | neq |
                                                      gt | lt | in_last_n | ...). Must be
                                                      legal for `type` — see
                                                      journeys_condition_catalog.
                                                  value:
                                                    description: >-
                                                      Shape depends on `op`: a plain scalar
                                                      for eq/neq/gt/lt/starts_with/…, an array
                                                      for in/not_in/contains/not_contains,
                                                      {from, to} for between, {amount, unit}
                                                      for
                                                      in_last_n/in_next_n/more_than_n_ago/more_than_n_from_now,
                                                      {minAmount, maxAmount, unit} for
                                                      between_n_and_m_ago, {daysOffset} for
                                                      exactly_n_from_today. Omit entirely for
                                                      is_null/is_not_null.
                                                    anyOf:
                                                      - type: string
                                                      - type: number
                                                      - type: boolean
                                                      - type: array
                                                        items:
                                                          anyOf:
                                                            - type: string
                                                            - type: number
                                                      - type: object
                                                        properties:
                                                          from:
                                                            type: string
                                                          to:
                                                            type: string
                                                        required:
                                                          - from
                                                          - to
                                                        additionalProperties: false
                                                      - type: object
                                                        properties:
                                                          amount:
                                                            type: integer
                                                            minimum: 1
                                                            maximum: 9999
                                                          unit:
                                                            type: string
                                                            enum:
                                                              - days
                                                              - weeks
                                                              - months
                                                        required:
                                                          - amount
                                                          - unit
                                                        additionalProperties: false
                                                      - type: object
                                                        properties:
                                                          minAmount:
                                                            type: integer
                                                            minimum: 0
                                                            maximum: 9999
                                                          maxAmount:
                                                            type: integer
                                                            minimum: 1
                                                            maximum: 9999
                                                          unit:
                                                            type: string
                                                            enum:
                                                              - days
                                                              - weeks
                                                              - months
                                                        required:
                                                          - minAmount
                                                          - maxAmount
                                                          - unit
                                                        additionalProperties: false
                                                      - type: object
                                                        properties:
                                                          daysOffset:
                                                            type: integer
                                                            minimum: -9007199254740991
                                                            maximum: 9007199254740991
                                                          rollForward:
                                                            type: object
                                                            properties:
                                                              fromDow:
                                                                type: integer
                                                                minimum: 0
                                                                maximum: 6
                                                              includeDows:
                                                                minItems: 1
                                                                type: array
                                                                items:
                                                                  type: integer
                                                                  minimum: 0
                                                                  maximum: 6
                                                            required:
                                                              - fromDow
                                                              - includeDows
                                                            additionalProperties: false
                                                        required:
                                                          - daysOffset
                                                        additionalProperties: false
                                                required:
                                                  - attr
                                                  - type
                                                  - op
                                                additionalProperties: false
                                                description: >-
                                                  A single live person/computed predicate
                                                  term. See journeys_condition_catalog for
                                                  its shape and the legal operator/value
                                                  pairing.
                                            required:
                                              - kind
                                              - term
                                            additionalProperties: false
                                          - type: object
                                            properties:
                                              kind:
                                                type: string
                                                const: cdp_object
                                              objectType:
                                                type: string
                                              matchAttr:
                                                type: string
                                              matchSelectionPath:
                                                type: string
                                                description: >-
                                                  Dot-path into the run; must start with
                                                  one of "engagement.workflowState.",
                                                  "engagement.extracted.",
                                                  "engagement.nodeOutputs.",
                                                  "engagement.conversation." (e.g.
                                                  engagement.workflowState.totalPrice).
                                                  customer.*, person.*, attributes.* and
                                                  engagement.context.* are NOT resolvable
                                                  here. Unlike the other roots,
                                                  "engagement.conversation." takes ONE OF
                                                  a closed set of keys —
                                                  hoursSinceLastInbound, lastInboundText,
                                                  lastInboundKind, documentCount,
                                                  newDocumentCount — and any other key is
                                                  refused at publish rather than resolving
                                                  blank. A single formatting helper may
                                                  follow the path ("| currency:MXN", "|
                                                  count"), including on
                                                  engagement.conversation.*, whose key is
                                                  checked with the helper stripped off.
                                              exists:
                                                type: boolean
                                            required:
                                              - kind
                                              - objectType
                                              - matchAttr
                                              - matchSelectionPath
                                              - exists
                                            additionalProperties: false
                                          - type: object
                                            properties:
                                              kind:
                                                type: string
                                                const: matched_object
                                              objectType:
                                                type: string
                                                minLength: 1
                                                description: >-
                                                  Custom-object type whose matched rows
                                                  (the rows that put this person in the
                                                  entry segment,
                                                  `workflowState.__matched.<type>`) are
                                                  re-read LIVE. Segment-triggered journeys
                                                  only; must be one of the segment's
                                                  matched types.
                                              term:
                                                type: object
                                                properties:
                                                  attr:
                                                    type: string
                                                    minLength: 1
                                                    description: >-
                                                      The BARE attribute key of the matched
                                                      object type, exactly as in its attribute
                                                      catalog (e.g. `order_status`). No
                                                      `attributes.`, `object.` or `computed.`
                                                      prefix. `type` must equal the catalogued
                                                      type.
                                                  type:
                                                    type: string
                                                    enum:
                                                      - STRING
                                                      - NUMBER
                                                      - BOOLEAN
                                                      - DATE
                                                      - JSON
                                                      - ARRAY
                                                    description: >-
                                                      CDP attribute type. Determines which
                                                      `op` values are legal — see
                                                      journeys_condition_catalog.
                                                  op:
                                                    type: string
                                                    minLength: 1
                                                    description: >-
                                                      Segments OperatorEnum value (eq | neq |
                                                      gt | lt | in_last_n | ...). Must be
                                                      legal for `type` — see
                                                      journeys_condition_catalog.
                                                  value:
                                                    description: >-
                                                      Shape depends on `op`: a plain scalar
                                                      for eq/neq/gt/lt/starts_with/…, an array
                                                      for in/not_in/contains/not_contains,
                                                      {from, to} for between, {amount, unit}
                                                      for
                                                      in_last_n/in_next_n/more_than_n_ago/more_than_n_from_now,
                                                      {minAmount, maxAmount, unit} for
                                                      between_n_and_m_ago, {daysOffset} for
                                                      exactly_n_from_today. Omit entirely for
                                                      is_null/is_not_null.
                                                    anyOf:
                                                      - type: string
                                                      - type: number
                                                      - type: boolean
                                                      - type: array
                                                        items:
                                                          anyOf:
                                                            - type: string
                                                            - type: number
                                                      - type: object
                                                        properties:
                                                          from:
                                                            type: string
                                                          to:
                                                            type: string
                                                        required:
                                                          - from
                                                          - to
                                                        additionalProperties: false
                                                      - type: object
                                                        properties:
                                                          amount:
                                                            type: integer
                                                            minimum: 1
                                                            maximum: 9999
                                                          unit:
                                                            type: string
                                                            enum:
                                                              - days
                                                              - weeks
                                                              - months
                                                        required:
                                                          - amount
                                                          - unit
                                                        additionalProperties: false
                                                      - type: object
                                                        properties:
                                                          minAmount:
                                                            type: integer
                                                            minimum: 0
                                                            maximum: 9999
                                                          maxAmount:
                                                            type: integer
                                                            minimum: 1
                                                            maximum: 9999
                                                          unit:
                                                            type: string
                                                            enum:
                                                              - days
                                                              - weeks
                                                              - months
                                                        required:
                                                          - minAmount
                                                          - maxAmount
                                                          - unit
                                                        additionalProperties: false
                                                      - type: object
                                                        properties:
                                                          daysOffset:
                                                            type: integer
                                                            minimum: -9007199254740991
                                                            maximum: 9007199254740991
                                                          rollForward:
                                                            type: object
                                                            properties:
                                                              fromDow:
                                                                type: integer
                                                                minimum: 0
                                                                maximum: 6
                                                              includeDows:
                                                                minItems: 1
                                                                type: array
                                                                items:
                                                                  type: integer
                                                                  minimum: 0
                                                                  maximum: 6
                                                            required:
                                                              - fromDow
                                                              - includeDows
                                                            additionalProperties: false
                                                        required:
                                                          - daysOffset
                                                        additionalProperties: false
                                                required:
                                                  - attr
                                                  - type
                                                  - op
                                                additionalProperties: false
                                                description: >-
                                                  Condition on the row's CURRENT
                                                  attributes. `attr` is the bare object
                                                  attribute key (e.g. `order_status`, not
                                                  `object.attributes.order_status`);
                                                  `type`/`op`/`value` follow the same
                                                  rules as a cdp_predicate term.
                                              quantifier:
                                                type: string
                                                enum:
                                                  - any
                                                  - all
                                                description: >-
                                                  `any`: YES when at least one matched row
                                                  passes. `all`: YES only when every
                                                  matched row still exists and passes. No
                                                  matched rows on the run → false.
                                            required:
                                              - kind
                                              - objectType
                                              - term
                                              - quantifier
                                            additionalProperties: false
                                        description: One decision condition.
                                    description:
                                      type: string
                                  required:
                                    - logic
                                    - conditions
                                  additionalProperties: false
                                  description: Two-way branch. Emits YES / NO.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: CASE
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    selectionPath:
                                      type: string
                                      description: >-
                                        Value to switch on; must start with one
                                        of "attributes.",
                                        "engagement.extracted.",
                                        "engagement.nodeOutputs.", "matched."
                                        (e.g. attributes.plan_tier).
                                        "matched.<type>.<attr>" (e.g.
                                        matched.order.order_status) switches on
                                        the CURRENT value of an attribute of the
                                        row that put the person in the entry
                                        segment — the first matched row of that
                                        type, read live; segment-triggered
                                        journeys only, and the type must be in
                                        the segment's matched types. A
                                        formatting helper ("| currency:MXN", "|
                                        count") is REFUSED here, unlike on a
                                        DECISION condition: CASE reads this path
                                        raw, so a helper would resolve blank and
                                        route case:default on every run.
                                    branches:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          id:
                                            type: string
                                            description: >-
                                              Stable branch id; edge handle is
                                              case:<id>.
                                          value:
                                            type: string
                                            description: Value matched. Unique within the node.
                                          label:
                                            type: string
                                            minLength: 1
                                            description: >-
                                              Required. Names the variant in analytics
                                              and on canvas.
                                        required:
                                          - id
                                          - value
                                          - label
                                        additionalProperties: false
                                      description: >-
                                        Up to 10 branches. A case:default handle
                                        is always required.
                                    description:
                                      type: string
                                  required:
                                    - selectionPath
                                    - branches
                                  additionalProperties: false
                                  description: N-way switch on a person attribute.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: RANDOM_SPLIT
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    arms:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          id:
                                            type: string
                                            description: >-
                                              Stable arm id; edge handle is
                                              split:<id>.
                                          weight:
                                            type: integer
                                            minimum: 1
                                            maximum: 100
                                            description: >-
                                              Integer percentage. A node's arms must
                                              total 100.
                                          label:
                                            type: string
                                        required:
                                          - id
                                          - weight
                                        additionalProperties: false
                                      description: >-
                                        At least 2 and at most 10 arms whose
                                        weights total exactly 100. There is no
                                        default handle — every roll lands on a
                                        declared arm.
                                    description:
                                      type: string
                                  required:
                                    - arms
                                  additionalProperties: false
                                  description: >-
                                    Randomly routes each run down one of N
                                    weighted arms.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: HTTP_REQUEST
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    method:
                                      type: string
                                      enum:
                                        - GET
                                        - POST
                                        - PUT
                                        - PATCH
                                        - DELETE
                                      description: HTTP method.
                                    url:
                                      type: string
                                      minLength: 1
                                      description: >-
                                        Target URL. Supports {{variable}}
                                        placeholders. Resolvable roots here:
                                        customer.<field> (a single flat field of
                                        the customer record), person.<attribute>
                                        (CDP), env.<key> (journey environment),
                                        engagement.context.*,
                                        engagement.workflowState.*,
                                        engagement.extracted.*,
                                        engagement.nodeOutputs.<nodeId>.*,
                                        engagement.documents (json body, whole
                                        quoted token, flag-gated), and
                                        engagement.conversation.id /
                                        engagement.conversation.inboxUrl — the
                                        conversation this run is talking to and
                                        its Shared Inbox deep link. Anything
                                        else substitutes as an empty string and
                                        is reported at publish as
                                        UNRESOLVABLE_HTTP_TOKEN. Note
                                        engagement.chatLink is SEND_EMAIL-only
                                        and does NOT resolve here.
                                    headers:
                                      description: >-
                                        Request headers as key/value pairs.
                                        Values support the same {{variable}}
                                        placeholders as the url. Resolvable
                                        roots here: customer.<field> (a single
                                        flat field of the customer record),
                                        person.<attribute> (CDP), env.<key>
                                        (journey environment),
                                        engagement.context.*,
                                        engagement.workflowState.*,
                                        engagement.extracted.*,
                                        engagement.nodeOutputs.<nodeId>.*,
                                        engagement.documents (json body, whole
                                        quoted token, flag-gated), and
                                        engagement.conversation.id /
                                        engagement.conversation.inboxUrl — the
                                        conversation this run is talking to and
                                        its Shared Inbox deep link. Anything
                                        else substitutes as an empty string and
                                        is reported at publish as
                                        UNRESOLVABLE_HTTP_TOKEN. Note
                                        engagement.chatLink is SEND_EMAIL-only
                                        and does NOT resolve here.
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          key:
                                            type: string
                                          value:
                                            type: string
                                        required:
                                          - key
                                          - value
                                        additionalProperties: false
                                    body:
                                      description: >-
                                        Request body. mode none sends no body.
                                        Supports the same {{variable}}
                                        placeholders as the url; in json mode a
                                        whole quoted token
                                        ("{{engagement.documents}}") substitutes
                                        as a JSON array. Resolvable roots here:
                                        customer.<field> (a single flat field of
                                        the customer record), person.<attribute>
                                        (CDP), env.<key> (journey environment),
                                        engagement.context.*,
                                        engagement.workflowState.*,
                                        engagement.extracted.*,
                                        engagement.nodeOutputs.<nodeId>.*,
                                        engagement.documents (json body, whole
                                        quoted token, flag-gated), and
                                        engagement.conversation.id /
                                        engagement.conversation.inboxUrl — the
                                        conversation this run is talking to and
                                        its Shared Inbox deep link. Anything
                                        else substitutes as an empty string and
                                        is reported at publish as
                                        UNRESOLVABLE_HTTP_TOKEN. Note
                                        engagement.chatLink is SEND_EMAIL-only
                                        and does NOT resolve here.
                                      type: object
                                      properties:
                                        mode:
                                          type: string
                                          enum:
                                            - none
                                            - json
                                            - raw
                                        content:
                                          type: string
                                        contentType:
                                          type: string
                                      required:
                                        - mode
                                      additionalProperties: false
                                    credentialId:
                                      description: >-
                                        Deprecated/legacy: HttpCredential row id
                                        used to authenticate the request. Prefer
                                        credentialKey.
                                      type: string
                                    credentialKey:
                                      description: >-
                                        Logical credential key; the pinned
                                        environment selects the secret.
                                      type: string
                                    timeoutMs:
                                      description: >-
                                        Request timeout in milliseconds. Max
                                        30000 (30s).
                                      type: integer
                                      exclusiveMinimum: 0
                                      maximum: 30000
                                    maxAttempts:
                                      description: Max attempts including the first. Max 5.
                                      type: integer
                                      exclusiveMinimum: 0
                                      maximum: 5
                                    documentUrlTtlSeconds:
                                      description: >-
                                        TTL (seconds, ≤86400) for presigned
                                        engagement.documents URLs this node
                                        emits. Default 86400.
                                      type: integer
                                      exclusiveMinimum: 0
                                      maximum: 86400
                                    documentMimeTypes:
                                      description: >-
                                        Allowlist of MIME types this node may
                                        egress in engagement.documents, e.g.
                                        ['application/pdf'] for an endpoint that
                                        only accepts PDFs. Omit (or pass an
                                        empty list) to send every document type
                                        — the default. A document whose type is
                                        not listed is withheld and counted in
                                        the step's documents.filteredCount,
                                        never silently dropped. Match is exact,
                                        trimmed and case-insensitive; a document
                                        with no recorded type is withheld
                                        whenever a list is set. Each entry must
                                        be a MIME type an inbound document can
                                        actually have, because a well-formed
                                        typo would match nothing and withhold
                                        everything: image/jpeg, image/png,
                                        image/webp, image/gif, application/pdf,
                                        video/mp4, text/vcard, text/html,
                                        application/msword,
                                        application/vnd.ms-excel,
                                        application/vnd.openxmlformats-officedocument.wordprocessingml.document,
                                        application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
                                        application/octet-stream.
                                      type: array
                                      items:
                                        type: string
                                        minLength: 1
                                  required:
                                    - method
                                    - url
                                  additionalProperties: false
                                  description: >-
                                    Calls an external HTTP endpoint. Emits
                                    SUCCESS or FAILED.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: ROUTE_TO_INITIATIVE
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    initiativeId:
                                      type: string
                                      minLength: 1
                                      description: >-
                                        Target initiative id to enroll this
                                        customer into.
                                    context:
                                      description: >-
                                        Values stamped onto the new engagement,
                                        readable by its agent. A literal string,
                                        or { var: 'engagement.extracted.<slug>'
                                        } resolved at route time.
                                      type: object
                                      propertyNames:
                                        type: string
                                      additionalProperties:
                                        anyOf:
                                          - type: string
                                          - type: object
                                            properties:
                                              var:
                                                type: string
                                            required:
                                              - var
                                            additionalProperties: false
                                    description:
                                      type: string
                                  required:
                                    - initiativeId
                                  additionalProperties: false
                                  description: >-
                                    Terminal. Ends this engagement and enrolls
                                    the customer into another initiative, moving
                                    the live conversation onto a new session.
                                    Emits no signals — it has no outgoing edges.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                            - type: object
                              properties:
                                id:
                                  type: string
                                  minLength: 1
                                  description: Node id, unique within the journey.
                                kind:
                                  type: string
                                  const: EXIT
                                name:
                                  type: string
                                  minLength: 1
                                  description: >-
                                    The label shown on the canvas. Required
                                    before publishing.
                                position:
                                  type: object
                                  properties:
                                    x:
                                      type: number
                                    'y':
                                      type: number
                                  required:
                                    - x
                                    - 'y'
                                  additionalProperties: false
                                  description: >-
                                    Explicit canvas position. Omit it and the
                                    server auto-lays-out the graph top-down;
                                    only set it to preserve a hand-arranged
                                    layout.
                                inputs:
                                  type: object
                                  properties:
                                    outcome:
                                      type: string
                                  additionalProperties: false
                                  description: Terminal node.
                              required:
                                - id
                                - kind
                              additionalProperties: false
                        description: >-
                          The nodes. Exactly one ENTRY, and at least one end
                          point (EXIT or ROUTE_TO_INITIATIVE), are required to
                          publish.
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            from:
                              type: string
                              description: Source node id.
                            to:
                              type: string
                              description: Target node id.
                            sourceHandle:
                              type: string
                              description: >-
                                The emitted signal that activates this edge
                                (e.g. SENT, REPLIED, YES, case:<id>). A handle
                                may wire to at most one node.
                            metadata:
                              type: object
                              properties:
                                signalCategory:
                                  type: string
                                  enum:
                                    - lifecycle
                                    - system
                                signalDescription:
                                  type: string
                              additionalProperties: false
                          required:
                            - from
                            - to
                            - sourceHandle
                          additionalProperties: false
                          description: >-
                            A connection: node `from` routes to `to` when it
                            emits `sourceHandle`.
                        description: The connections between node handles.
                    required:
                      - name
                      - actions
                      - edges
                    additionalProperties: false
                    description: The full journey graph.
                required:
                  - id
                  - initiativeId
                  - status
                  - version
                  - definition
                additionalProperties: false
        '400':
          description: Validation failed or the request cannot proceed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '401':
          description: Missing, malformed, or revoked API key.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '404':
          description: The resource does not exist in this organization.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '409':
          description: >-
            Conflicts with the current state (duplicates, wrong lifecycle
            state).
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '422':
          description: The request is well-formed but semantically invalid.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '429':
          description: Rate limit exceeded — retry after `Retry-After`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '500':
          description: Internal server error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
        '503':
          description: Transient error — retry with a narrower request.
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: Stable machine-readable error code (snake_case).
                      message:
                        type: string
                    required:
                      - code
                      - message
                required:
                  - error
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Organization API key, sent as `Authorization: Bearer boom_org_...`.'

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.