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

# List content



## OpenAPI

````yaml /api-reference-v2/openapi.json get /v2/projects/{projectId}/content
openapi: 3.0.0
info:
  title: Usertour API v2
  description: >-
    Project-scoped v2 API. Authenticate with a personal API token — an opaque
    `utp_...` string (NOT a JWT: do not try to decode it), created in the
    Usertour app under Settings → API, sent as `Authorization: Bearer utp_...`.
  version: '2.0'
  contact: {}
servers:
  - url: https://api.usertour.io
security: []
tags: []
paths:
  /v2/projects/{projectId}/content:
    get:
      tags:
        - Content
      summary: List content
      operationId: ApiContentController_list
      parameters:
        - name: projectId
          required: true
          in: path
          description: Project ID
          schema:
            type: string
        - name: limit
          required: false
          in: query
          description: Max items per page (1-100, default 20).
          schema:
            minimum: 1
            maximum: 100
            default: 20
            type: integer
        - name: cursor
          required: false
          in: query
          description: >-
            Opaque page cursor — the `cursor` query value found inside a prior
            response's `next`/`previous` URL. Normally you never build this
            yourself: just GET those URLs as-is.
          schema:
            type: string
        - name: name
          required: false
          in: query
          description: Filter by name (case-insensitive substring match).
          schema:
            type: string
        - name: type
          required: false
          in: query
          description: >-
            Filter by content type. (A survey is a flow with question blocks —
            there is no separate survey type.)
          schema:
            type: string
            enum:
              - checklist
              - flow
              - launcher
              - banner
              - tracker
              - resource-center
              - announcement
        - name: published
          required: false
          in: query
          description: >-
            Filter to content published in at least one environment (true) or
            none (false).
          schema:
            enum:
              - 'true'
              - 'false'
            type: string
        - name: deleted
          required: false
          in: query
          description: >-
            List soft-deleted (archived) content instead of live content — the
            recovery pool for restore.
          schema:
            enum:
              - 'true'
              - 'false'
            type: string
        - name: expand
          required: false
          in: query
          description: 'Inline: editedVersion and/or publishedVersion.'
          schema:
            anyOf:
              - type: string
                enum:
                  - editedVersion
                  - publishedVersion
              - type: array
                items:
                  type: string
                  enum:
                    - editedVersion
                    - publishedVersion
        - name: orderBy
          required: false
          in: query
          description: Order by createdAt / -createdAt.
          schema:
            anyOf:
              - type: string
                enum:
                  - createdAt
                  - '-createdAt'
              - type: array
                items:
                  type: string
                  enum:
                    - createdAt
                    - '-createdAt'
        - name: createdAfter
          required: false
          in: query
          description: >-
            Only items created at or after this time — ISO date or datetime WITH
            timezone. A date-only value starts at that day's first instant
            (UTC).
          schema:
            type: string
        - name: createdBefore
          required: false
          in: query
          description: >-
            Only items created at or before this time — ISO date or datetime
            WITH timezone. A date-only value includes the ENTIRE day (up to its
            last instant, UTC).
          schema:
            type: string
      responses:
        '200':
          description: List of content
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListContentResponseDto'
        '400':
          description: >-
            Invalid request — E1017 validation (may carry `issues`; an invalid
            orderBy/limit is also E1017), E1015 invalid scope, E0003 invalid
            against current domain state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '401':
          description: Missing or expired API key — E1010, E1020.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '403':
          description: >-
            Refused — E1000 invalid key, E1011 project not in token scope, E1012
            insufficient scope, E1029 environment not in token scope, E1032
            environment creation needs a token without env-targeted capabilities
            (its allowlist cannot cover a not-yet-existing environment).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '429':
          description: >-
            Rate limit exceeded — E1013. The limit follows the project's plan
            (100/500/1000/3000 requests per minute); unknown credentials share a
            per-IP bucket. Every response also carries X-RateLimit-Limit /
            -Remaining / -Reset for pacing; a 429 adds the standard Retry-After
            header (seconds to back off).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      security:
        - bearer: []
components:
  schemas:
    ListContentResponseDto:
      type: object
      properties:
        results:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              object:
                type: string
                enum:
                  - content
              name:
                type: string
              type:
                type: string
                enum:
                  - checklist
                  - flow
                  - launcher
                  - banner
                  - tracker
                  - resource-center
                  - announcement
              buildUrl:
                type: string
                description: >-
                  URL of the app page where this content is authored and
                  previewed (the visual editor opens it there). Metadata only —
                  it plays NO part in runtime targeting; where content shows is
                  controlled by its start rules.
                nullable: true
              editedVersionId:
                type: string
              editedVersion:
                type: object
                properties:
                  id:
                    type: string
                  object:
                    type: string
                    enum:
                      - contentVersion
                  number:
                    type: number
                  firstPublishedAt:
                    type: string
                    description: >-
                      When this version FIRST went live (ISO). Non-null means
                      the version is frozen: it can never be edited again — not
                      even after unpublishing — edit by forking (by forking).
                      null means it never went live — OR its first publish
                      predates this stamp (older versions were never
                      backfilled), so on old data null is not proof it never
                      shipped. This is history, not live state: for "is it live
                      NOW, where" read the content's `environments[]`; for who
                      published what when, the publish history (available
                      through the MCP).
                    nullable: true
                  themeId:
                    type: string
                    nullable: true
                  questions:
                    type: array
                    items:
                      type: object
                      properties:
                        object:
                          type: string
                          enum:
                            - question
                        cvid:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                          enum:
                            - nps
                            - star-rating
                            - scale
                            - single-line-text
                            - multi-line-text
                            - multiple-choice
                      required:
                        - object
                        - cvid
                        - name
                        - type
                    nullable: true
                  steps:
                    type: array
                    items:
                      type: object
                      properties:
                        object:
                          type: string
                          enum:
                            - step
                        id:
                          type: string
                        cvid:
                          type: string
                          description: >-
                            Stable step handle that SURVIVES forking (unlike
                            `id`, which is regenerated) — echo it on a write to
                            update this step in place. Prefer it over `id` for
                            edits that must outlive a new version.
                          nullable: true
                        name:
                          type: string
                        type:
                          type: string
                          enum:
                            - tooltip
                            - modal
                            - hidden
                            - bubble
                        sequence:
                          type: number
                          description: >-
                            0-based display order. On write an explicit
                            `sequence` wins; steps without one fall back to
                            their array index.
                        themeId:
                          type: string
                          description: >-
                            Per-step theme override; null = this step inherits
                            the flow version's theme.
                          nullable: true
                        target:
                          type: object
                          properties:
                            selector:
                              type: string
                              minLength: 1
                              description: >-
                                A stable CSS selector for the element. The
                                runtime targets the FIRST match — so either make
                                the selector unique, or pair a stable non-unique
                                selector with `nth` to pick the intended match.
                                A non-unique selector with no `nth` targets the
                                first (often wrong) element and the tooltip
                                silently won't render.
                            text:
                              description: >-
                                Optional refinement of `selector`. Requires the
                                targeted element's visible text to equal this
                                (exact match, after trim) — use it to pin a
                                specific content/state (e.g. a stable id whose
                                displayed text you want to match: id + text). It
                                refines the element chosen by `selector`/`nth`;
                                on its own it does NOT search among multiple
                                matches, so disambiguate a non-unique selector
                                with `nth`, not `text` alone.
                              type: string
                            nth:
                              description: >-
                                Optional refinement of `selector`. 0-based index
                                to pick which match when the selector isn't
                                unique — e.g. a stable selector matching 3
                                elements + `nth: 1` targets the 2nd, giving a
                                unique result. Matches are taken in document
                                order (as they appear in the page HTML). Range
                                0–4 — only the first 5 matches are addressable;
                                a larger value is rejected.
                              type: integer
                              minimum: 0
                              maximum: 4
                          required:
                            - selector
                        placement:
                          anyOf:
                            - type: object
                              properties:
                                side:
                                  description: >-
                                    Which side of the target the tooltip sits
                                    on. OMIT side+align to auto-position (the
                                    tooltip picks a spot and flips to avoid the
                                    viewport edge — best when you can't see the
                                    element). Setting side (or align) pins that
                                    direction: the tooltip renders exactly there
                                    and no longer auto-flips, so only pin when
                                    the element is not near a screen edge. When
                                    READING a step back, check `alignType`
                                    first: under `auto` the side/align you see
                                    are just the auto starting position, not a
                                    pin.
                                  type: string
                                  enum:
                                    - top
                                    - right
                                    - bottom
                                    - left
                                align:
                                  description: Alignment along the side. See `side`.
                                  type: string
                                  enum:
                                    - start
                                    - center
                                    - end
                                sideOffset:
                                  description: >-
                                    Pixels between the target and the tooltip,
                                    along `side`.
                                  type: number
                                alignOffset:
                                  description: >-
                                    Pixel shift along the alignment axis. Only
                                    applies when `align` is `start` or `end` —
                                    at `center` alignment the runtime ignores it
                                    silently.
                                  type: number
                                alignType:
                                  description: >-
                                    Position mode. `auto` auto-positions and
                                    flips to avoid the viewport edge (ignoring
                                    side/align); `fixed` pins to side/align
                                    without flipping. Usually omit it: providing
                                    side/align implies `fixed`, and omitting
                                    them implies `auto`. Set it only to override
                                    that (e.g. `auto` while still passing a
                                    side/align you want ignored). Read-backs
                                    always carry concrete side/align even in
                                    `auto` mode (the auto starting position,
                                    bottom/center) — `alignType` is what
                                    governs, and `auto` still flips at runtime.
                                  type: string
                                  enum:
                                    - auto
                                    - fixed
                                backdrop:
                                  description: >-
                                    Dim the rest of the page while this tooltip
                                    is up.
                                  type: boolean
                                blockTarget:
                                  description: >-
                                    Make the backdrop swallow clicks on the
                                    highlighted element, so the user must use
                                    the tooltip. REQUIRES `backdrop: true` — on
                                    its own it does nothing (the renderer only
                                    consults it inside the backdrop branch).
                                  type: boolean
                              additionalProperties: false
                            - type: object
                              properties:
                                position:
                                  type: string
                                  enum:
                                    - leftTop
                                    - centerTop
                                    - rightTop
                                    - leftCenter
                                    - center
                                    - rightCenter
                                    - leftBottom
                                    - centerBottom
                                    - rightBottom
                                offsetX:
                                  description: >-
                                    Pixel shift from the grid cell. Applies in
                                    every cell EXCEPT `position: "center"`,
                                    where both offsets are ignored silently.
                                  type: number
                                offsetY:
                                  description: See `offsetX`.
                                  type: number
                                backdrop:
                                  type: boolean
                              required:
                                - position
                              additionalProperties: false
                          description: >-
                            Two placement shapes, by step kind: a TOOLTIP
                            (anchored to a `target`) uses `{ side, align,
                            sideOffset?, alignOffset?, alignType? }` positioned
                            relative to the element; a MODAL uses `{ position,
                            offsetX?, offsetY? }` on a 9-cell viewport grid
                            (e.g. `"center"`). Both may set `backdrop`;
                            `blockTarget` is TOOLTIP-ONLY (a modal already
                            covers the page) and additionally requires
                            `backdrop: true` — it makes the backdrop swallow
                            clicks on the highlighted element. A BUBBLE step is
                            positioned by its THEME's bubble placement, so the
                            only key it accepts here is `{ backdrop }`
                            (positional keys are rejected — move the bubble by
                            changing the theme); a HIDDEN step renders no UI and
                            rejects `placement` entirely.
                        width:
                          description: >-
                            Per-step width override in pixels (border-box outer
                            width) — absent = the theme's surface width.
                          type: number
                        skippable:
                          type: boolean
                        explicitCompletionStep:
                          description: >-
                            Marks this step as the flow's completion point:
                            reaching it counts the flow as COMPLETED (progress
                            hits 100 and the completion event fires there), and
                            later steps no longer report progress. With no step
                            marked, only reaching the LAST step completes the
                            flow — which is what a checklist task waiting on
                            "this flow completed" depends on.
                          type: boolean
                        content:
                          type: array
                          items:
                            $ref: >-
                              #/components/schemas/ListContentResponseDto__schema0
                        triggers:
                          type: array
                          items:
                            type: object
                            properties:
                              when:
                                description: >-
                                  REACTIVE slot — polled live in the browser
                                  while the step is on screen, so it accepts
                                  only client-evaluable condition types:
                                  attribute / current_url / element / text_input
                                  / text_filled / time_window. Event / segment /
                                  content_state conditions are server-evaluated
                                  and rejected here (E1017). A trigger with NO
                                  `when` never fires (an empty set is "not
                                  matched", not "always").
                                type: array
                                items:
                                  $ref: >-
                                    #/components/schemas/ListContentResponseDto__schema1
                              do:
                                type: array
                                items:
                                  oneOf:
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - goto_step
                                        step:
                                          type: string
                                          description: >-
                                            Target step: a step `key` declared
                                            elsewhere in the same write, or an
                                            existing step cvid. Resolved server-side
                                            to the cvid.
                                      required:
                                        - type
                                        - step
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - start_content
                                        content:
                                          type: string
                                          description: >-
                                            contentId of the flow or checklist to
                                            launch (an id from the content list) — a
                                            raw content id, NOT a step key (unlike
                                            goto_step). Must reference a flow or
                                            checklist (a banner / launcher /
                                            resource-center / tracker is rejected at
                                            write). The target must be PUBLISHED to
                                            actually start at runtime; an
                                            unknown/dangling id is rejected at
                                            validate.
                                        step:
                                          description: >-
                                            Optional cvid of a step within the
                                            launched flow to start at.
                                          type: string
                                      required:
                                        - type
                                        - content
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - navigate
                                        url:
                                          type: string
                                          description: >-
                                            Absolute URL, or an app-relative path
                                            ("/docs/x") resolved against the origin
                                            the user is on — relative paths are the
                                            normal choice for in-app navigation.
                                        newTab:
                                          description: >-
                                            Open the URL in a new browser tab
                                            instead of navigating the current one.
                                          type: boolean
                                      required:
                                        - type
                                        - url
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - dismiss
                                      required:
                                        - type
                                      description: >-
                                        Dismiss the piece the action lives on.
                                        NOT accepted everywhere this union
                                        appears: a resource center has no
                                        dismiss (closing the panel is a UI
                                        affordance, not an action) and an
                                        announcement is marked seen, never
                                        dismissed — writes there are rejected
                                        (E1017), not ignored. Flows / checklists
                                        / launchers / banners all accept it.
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - run_javascript
                                        script:
                                          type: string
                                      required:
                                        - type
                                        - script
                                      description: >-
                                        Read-back of an existing script action —
                                        scripts are not authorable through this
                                        API. Echo it back UNCHANGED (same
                                        script) when rewriting the surrounding
                                        list and the stored action is preserved;
                                        omitting it deletes it (action lists are
                                        full replacements). Authoring a new or
                                        edited script is rejected.
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - unsupported
                                        note:
                                          type: string
                                      required:
                                        - type
                                      description: >-
                                        Echo-only placeholder for a stored
                                        action this schema cannot express
                                        (`note` = internal type). Echo it back
                                        to preserve the stored action; writing
                                        one fresh is rejected.
                              waitSeconds:
                                description: >-
                                  Delay in SECONDS between the `when` conditions
                                  matching and the `do` actions firing. The
                                  timer arms the first time `when` matches and
                                  the actions fire after the wait EVEN IF the
                                  conditions have since stopped matching (the
                                  match is latched, not re-checked). Capped at
                                  300 seconds by the runtime (a larger value is
                                  clamped).
                                type: number
                            required:
                              - do
                        onClick:
                          description: >-
                            Actions that run when the user clicks the step's
                            TARGET ELEMENT on the page (click-to-advance) —
                            distinct from a `button` block, whose actions fire
                            on a button rendered inside the step. `tooltip`
                            steps only: the other kinds have no target element
                            to click, and the write rejects `onClick` on them.
                          type: array
                          items:
                            oneOf:
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - goto_step
                                  step:
                                    type: string
                                    description: >-
                                      Target step: a step `key` declared
                                      elsewhere in the same write, or an
                                      existing step cvid. Resolved server-side
                                      to the cvid.
                                required:
                                  - type
                                  - step
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - start_content
                                  content:
                                    type: string
                                    description: >-
                                      contentId of the flow or checklist to
                                      launch (an id from the content list) — a
                                      raw content id, NOT a step key (unlike
                                      goto_step). Must reference a flow or
                                      checklist (a banner / launcher /
                                      resource-center / tracker is rejected at
                                      write). The target must be PUBLISHED to
                                      actually start at runtime; an
                                      unknown/dangling id is rejected at
                                      validate.
                                  step:
                                    description: >-
                                      Optional cvid of a step within the
                                      launched flow to start at.
                                    type: string
                                required:
                                  - type
                                  - content
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - navigate
                                  url:
                                    type: string
                                    description: >-
                                      Absolute URL, or an app-relative path
                                      ("/docs/x") resolved against the origin
                                      the user is on — relative paths are the
                                      normal choice for in-app navigation.
                                  newTab:
                                    description: >-
                                      Open the URL in a new browser tab instead
                                      of navigating the current one.
                                    type: boolean
                                required:
                                  - type
                                  - url
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - dismiss
                                required:
                                  - type
                                description: >-
                                  Dismiss the piece the action lives on. NOT
                                  accepted everywhere this union appears: a
                                  resource center has no dismiss (closing the
                                  panel is a UI affordance, not an action) and
                                  an announcement is marked seen, never
                                  dismissed — writes there are rejected (E1017),
                                  not ignored. Flows / checklists / launchers /
                                  banners all accept it.
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - run_javascript
                                  script:
                                    type: string
                                required:
                                  - type
                                  - script
                                description: >-
                                  Read-back of an existing script action —
                                  scripts are not authorable through this API.
                                  Echo it back UNCHANGED (same script) when
                                  rewriting the surrounding list and the stored
                                  action is preserved; omitting it deletes it
                                  (action lists are full replacements).
                                  Authoring a new or edited script is rejected.
                              - type: object
                                properties:
                                  type:
                                    type: string
                                    enum:
                                      - unsupported
                                  note:
                                    type: string
                                required:
                                  - type
                                description: >-
                                  Echo-only placeholder for a stored action this
                                  schema cannot express (`note` = internal
                                  type). Echo it back to preserve the stored
                                  action; writing one fresh is rejected.
                        advanced:
                          type: object
                          properties:
                            hasUnsupported:
                              type: boolean
                              description: >-
                                true = this step carries stored configuration
                                this API cannot express (e.g. an auto-recorded
                                element fingerprint). Read-only signal: echoing
                                the step back preserves that configuration
                                untouched; it is not editable here.
                          required:
                            - hasUnsupported
                      required:
                        - object
                        - id
                        - cvid
                        - name
                        - type
                        - sequence
                        - themeId
                        - content
                  startRules:
                    type: object
                    properties:
                      when:
                        description: >-
                          Start conditions (full replacement when present). Omit
                          to keep the existing conditions and change only the
                          settings.
                        type: array
                        items:
                          $ref: '#/components/schemas/ListContentResponseDto__schema1'
                      frequency:
                        description: >-
                          How often the content may auto-start (flow/checklist
                          only). Left unset on a write, the builder default
                          (`once`) is seeded and STORED — read-backs show the
                          effective mode explicitly. A version stored with NO
                          frequency at all (reachable only through
                          legacy/builder-external writes, never through this
                          API) runs with NO limit: it starts again every time
                          its rules match once the prior session ends —
                          validate_content_version warns on that state.
                        type: object
                        properties:
                          mode:
                            type: string
                            enum:
                              - once
                              - multiple
                              - unlimited
                            description: >-
                              once = show a single time; multiple = up to N
                              times per window; unlimited = every time the
                              conditions match (subject to `every`).
                          every:
                            description: >-
                              Re-show window. Used by `multiple` (with `times`)
                              and `unlimited`; ignored for `once`. If omitted
                              for those modes a default window is applied.
                              Manual and programmatic starts also count toward
                              the `multiple` limit.
                            type: object
                            properties:
                              times:
                                type: number
                              duration:
                                type: number
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                            required:
                              - duration
                              - unit
                          atLeast:
                            description: >-
                              Only auto-start if no OTHER content of the SAME
                              type has been shown within this window — and since
                              only flows accept this knob, in practice: no other
                              FLOW. A banner / checklist / launcher showing does
                              NOT block it. Avoids stacking several flows on a
                              user at once.
                            type: object
                            properties:
                              duration:
                                type: number
                              unit:
                                type: string
                                enum:
                                  - seconds
                                  - minutes
                                  - hours
                                  - days
                            required:
                              - duration
                              - unit
                        required:
                          - mode
                      priority:
                        description: >-
                          Tie-breaker when a user matches the start conditions
                          for more than one piece of content at the same time —
                          the higher priority starts first. Content with no
                          priority set ranks as `medium`.
                        type: string
                        enum:
                          - highest
                          - high
                          - medium
                          - low
                          - lowest
                      waitSeconds:
                        description: >-
                          Delay in SECONDS between the start conditions matching
                          and the content becoming ELIGIBLE to start. The
                          countdown itself survives the conditions un-matching
                          mid-wait, but unlike a trigger wait (which fires its
                          actions regardless), an elapsed start-rule wait
                          guarantees nothing: the conditions are RE-CHECKED at
                          show time, and the content starts at the next moment
                          they match again. One exception: when a session of the
                          same content type starts or ends mid-wait, in-flight
                          timers are cancelled and re-armed — a still-matching
                          version then restarts its wait from zero. Capped at
                          300 seconds by the runtime (a larger value is
                          clamped).
                        type: number
                      startIfNotComplete:
                        description: >-
                          When true, this content won't auto-start for users who
                          have already completed it.
                        type: boolean
                  hideRules:
                    type: object
                    properties:
                      when:
                        type: array
                        items:
                          $ref: '#/components/schemas/ListContentResponseDto__schema1'
                    required:
                      - when
                    description: >-
                      While `when` matches, on-screen content of this version is
                      hidden — the session is SUSPENDED, not ended: when the
                      conditions stop matching the same session reappears at the
                      same step. Use start-rule conditions to keep content from
                      starting; use hide rules to blank it in specific places
                      (e.g. a settings page).
                  data:
                    description: >-
                      Decompiled type-specific body for non-flow content — the
                      same six per-type shapes as the write `data` (fully typed
                      on the content-versions endpoints). Present only with the
                      `data` expand; a flow has no `data` — its body is `steps`.
                  scheduledAt:
                    description: >-
                      Announcement versions only: the "announcement time" gating
                      feed visibility and ordering. Absent on other content
                      types and until set (publish stamps it when the author
                      left it null, so published announcements always carry
                      one).
                    type: string
                  updatedAt:
                    type: string
                    format: date-time
                  createdAt:
                    type: string
                    format: date-time
                required:
                  - id
                  - object
                  - number
                  - firstPublishedAt
                  - themeId
                  - questions
                  - updatedAt
                  - createdAt
              environments:
                type: array
                items:
                  type: object
                  properties:
                    environmentId:
                      type: string
                    published:
                      type: boolean
                      description: >-
                        Always true on a returned row: `environments[]` lists
                        ONLY the environments this content is currently
                        published to. Unpublishing removes the row — a missing
                        environment means "not published there", it never
                        appears as false.
                    publishedVersionId:
                      type: string
                    publishedAt:
                      type: string
                      format: date-time
                    publishedVersion:
                      type: object
                      properties:
                        id:
                          type: string
                        object:
                          type: string
                          enum:
                            - contentVersion
                        number:
                          type: number
                        firstPublishedAt:
                          type: string
                          description: >-
                            When this version FIRST went live (ISO). Non-null
                            means the version is frozen: it can never be edited
                            again — not even after unpublishing — edit by
                            forking (by forking). null means it never went live
                            — OR its first publish predates this stamp (older
                            versions were never backfilled), so on old data null
                            is not proof it never shipped. This is history, not
                            live state: for "is it live NOW, where" read the
                            content's `environments[]`; for who published what
                            when, the publish history (available through the
                            MCP).
                          nullable: true
                        themeId:
                          type: string
                          nullable: true
                        questions:
                          type: array
                          items:
                            type: object
                            properties:
                              object:
                                type: string
                                enum:
                                  - question
                              cvid:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                                enum:
                                  - nps
                                  - star-rating
                                  - scale
                                  - single-line-text
                                  - multi-line-text
                                  - multiple-choice
                            required:
                              - object
                              - cvid
                              - name
                              - type
                          nullable: true
                        steps:
                          type: array
                          items:
                            type: object
                            properties:
                              object:
                                type: string
                                enum:
                                  - step
                              id:
                                type: string
                              cvid:
                                type: string
                                description: >-
                                  Stable step handle that SURVIVES forking
                                  (unlike `id`, which is regenerated) — echo it
                                  on a write to update this step in place.
                                  Prefer it over `id` for edits that must
                                  outlive a new version.
                                nullable: true
                              name:
                                type: string
                              type:
                                type: string
                                enum:
                                  - tooltip
                                  - modal
                                  - hidden
                                  - bubble
                              sequence:
                                type: number
                                description: >-
                                  0-based display order. On write an explicit
                                  `sequence` wins; steps without one fall back
                                  to their array index.
                              themeId:
                                type: string
                                description: >-
                                  Per-step theme override; null = this step
                                  inherits the flow version's theme.
                                nullable: true
                              target:
                                type: object
                                properties:
                                  selector:
                                    type: string
                                    minLength: 1
                                    description: >-
                                      A stable CSS selector for the element. The
                                      runtime targets the FIRST match — so
                                      either make the selector unique, or pair a
                                      stable non-unique selector with `nth` to
                                      pick the intended match. A non-unique
                                      selector with no `nth` targets the first
                                      (often wrong) element and the tooltip
                                      silently won't render.
                                  text:
                                    description: >-
                                      Optional refinement of `selector`.
                                      Requires the targeted element's visible
                                      text to equal this (exact match, after
                                      trim) — use it to pin a specific
                                      content/state (e.g. a stable id whose
                                      displayed text you want to match: id +
                                      text). It refines the element chosen by
                                      `selector`/`nth`; on its own it does NOT
                                      search among multiple matches, so
                                      disambiguate a non-unique selector with
                                      `nth`, not `text` alone.
                                    type: string
                                  nth:
                                    description: >-
                                      Optional refinement of `selector`. 0-based
                                      index to pick which match when the
                                      selector isn't unique — e.g. a stable
                                      selector matching 3 elements + `nth: 1`
                                      targets the 2nd, giving a unique result.
                                      Matches are taken in document order (as
                                      they appear in the page HTML). Range 0–4 —
                                      only the first 5 matches are addressable;
                                      a larger value is rejected.
                                    type: integer
                                    minimum: 0
                                    maximum: 4
                                required:
                                  - selector
                              placement:
                                anyOf:
                                  - type: object
                                    properties:
                                      side:
                                        description: >-
                                          Which side of the target the tooltip
                                          sits on. OMIT side+align to
                                          auto-position (the tooltip picks a spot
                                          and flips to avoid the viewport edge —
                                          best when you can't see the element).
                                          Setting side (or align) pins that
                                          direction: the tooltip renders exactly
                                          there and no longer auto-flips, so only
                                          pin when the element is not near a
                                          screen edge. When READING a step back,
                                          check `alignType` first: under `auto`
                                          the side/align you see are just the auto
                                          starting position, not a pin.
                                        type: string
                                        enum:
                                          - top
                                          - right
                                          - bottom
                                          - left
                                      align:
                                        description: Alignment along the side. See `side`.
                                        type: string
                                        enum:
                                          - start
                                          - center
                                          - end
                                      sideOffset:
                                        description: >-
                                          Pixels between the target and the
                                          tooltip, along `side`.
                                        type: number
                                      alignOffset:
                                        description: >-
                                          Pixel shift along the alignment axis.
                                          Only applies when `align` is `start` or
                                          `end` — at `center` alignment the
                                          runtime ignores it silently.
                                        type: number
                                      alignType:
                                        description: >-
                                          Position mode. `auto` auto-positions and
                                          flips to avoid the viewport edge
                                          (ignoring side/align); `fixed` pins to
                                          side/align without flipping. Usually
                                          omit it: providing side/align implies
                                          `fixed`, and omitting them implies
                                          `auto`. Set it only to override that
                                          (e.g. `auto` while still passing a
                                          side/align you want ignored). Read-backs
                                          always carry concrete side/align even in
                                          `auto` mode (the auto starting position,
                                          bottom/center) — `alignType` is what
                                          governs, and `auto` still flips at
                                          runtime.
                                        type: string
                                        enum:
                                          - auto
                                          - fixed
                                      backdrop:
                                        description: >-
                                          Dim the rest of the page while this
                                          tooltip is up.
                                        type: boolean
                                      blockTarget:
                                        description: >-
                                          Make the backdrop swallow clicks on the
                                          highlighted element, so the user must
                                          use the tooltip. REQUIRES `backdrop:
                                          true` — on its own it does nothing (the
                                          renderer only consults it inside the
                                          backdrop branch).
                                        type: boolean
                                    additionalProperties: false
                                  - type: object
                                    properties:
                                      position:
                                        type: string
                                        enum:
                                          - leftTop
                                          - centerTop
                                          - rightTop
                                          - leftCenter
                                          - center
                                          - rightCenter
                                          - leftBottom
                                          - centerBottom
                                          - rightBottom
                                      offsetX:
                                        description: >-
                                          Pixel shift from the grid cell. Applies
                                          in every cell EXCEPT `position:
                                          "center"`, where both offsets are
                                          ignored silently.
                                        type: number
                                      offsetY:
                                        description: See `offsetX`.
                                        type: number
                                      backdrop:
                                        type: boolean
                                    required:
                                      - position
                                    additionalProperties: false
                                description: >-
                                  Two placement shapes, by step kind: a TOOLTIP
                                  (anchored to a `target`) uses `{ side, align,
                                  sideOffset?, alignOffset?, alignType? }`
                                  positioned relative to the element; a MODAL
                                  uses `{ position, offsetX?, offsetY? }` on a
                                  9-cell viewport grid (e.g. `"center"`). Both
                                  may set `backdrop`; `blockTarget` is
                                  TOOLTIP-ONLY (a modal already covers the page)
                                  and additionally requires `backdrop: true` —
                                  it makes the backdrop swallow clicks on the
                                  highlighted element. A BUBBLE step is
                                  positioned by its THEME's bubble placement, so
                                  the only key it accepts here is `{ backdrop }`
                                  (positional keys are rejected — move the
                                  bubble by changing the theme); a HIDDEN step
                                  renders no UI and rejects `placement`
                                  entirely.
                              width:
                                description: >-
                                  Per-step width override in pixels (border-box
                                  outer width) — absent = the theme's surface
                                  width.
                                type: number
                              skippable:
                                type: boolean
                              explicitCompletionStep:
                                description: >-
                                  Marks this step as the flow's completion
                                  point: reaching it counts the flow as
                                  COMPLETED (progress hits 100 and the
                                  completion event fires there), and later steps
                                  no longer report progress. With no step
                                  marked, only reaching the LAST step completes
                                  the flow — which is what a checklist task
                                  waiting on "this flow completed" depends on.
                                type: boolean
                              content:
                                type: array
                                items:
                                  $ref: >-
                                    #/components/schemas/ListContentResponseDto__schema0
                              triggers:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    when:
                                      description: >-
                                        REACTIVE slot — polled live in the
                                        browser while the step is on screen, so
                                        it accepts only client-evaluable
                                        condition types: attribute / current_url
                                        / element / text_input / text_filled /
                                        time_window. Event / segment /
                                        content_state conditions are
                                        server-evaluated and rejected here
                                        (E1017). A trigger with NO `when` never
                                        fires (an empty set is "not matched",
                                        not "always").
                                      type: array
                                      items:
                                        $ref: >-
                                          #/components/schemas/ListContentResponseDto__schema1
                                    do:
                                      type: array
                                      items:
                                        oneOf:
                                          - type: object
                                            properties:
                                              type:
                                                type: string
                                                enum:
                                                  - goto_step
                                              step:
                                                type: string
                                                description: >-
                                                  Target step: a step `key` declared
                                                  elsewhere in the same write, or an
                                                  existing step cvid. Resolved server-side
                                                  to the cvid.
                                            required:
                                              - type
                                              - step
                                          - type: object
                                            properties:
                                              type:
                                                type: string
                                                enum:
                                                  - start_content
                                              content:
                                                type: string
                                                description: >-
                                                  contentId of the flow or checklist to
                                                  launch (an id from the content list) — a
                                                  raw content id, NOT a step key (unlike
                                                  goto_step). Must reference a flow or
                                                  checklist (a banner / launcher /
                                                  resource-center / tracker is rejected at
                                                  write). The target must be PUBLISHED to
                                                  actually start at runtime; an
                                                  unknown/dangling id is rejected at
                                                  validate.
                                              step:
                                                description: >-
                                                  Optional cvid of a step within the
                                                  launched flow to start at.
                                                type: string
                                            required:
                                              - type
                                              - content
                                          - type: object
                                            properties:
                                              type:
                                                type: string
                                                enum:
                                                  - navigate
                                              url:
                                                type: string
                                                description: >-
                                                  Absolute URL, or an app-relative path
                                                  ("/docs/x") resolved against the origin
                                                  the user is on — relative paths are the
                                                  normal choice for in-app navigation.
                                              newTab:
                                                description: >-
                                                  Open the URL in a new browser tab
                                                  instead of navigating the current one.
                                                type: boolean
                                            required:
                                              - type
                                              - url
                                          - type: object
                                            properties:
                                              type:
                                                type: string
                                                enum:
                                                  - dismiss
                                            required:
                                              - type
                                            description: >-
                                              Dismiss the piece the action lives on.
                                              NOT accepted everywhere this union
                                              appears: a resource center has no
                                              dismiss (closing the panel is a UI
                                              affordance, not an action) and an
                                              announcement is marked seen, never
                                              dismissed — writes there are rejected
                                              (E1017), not ignored. Flows / checklists
                                              / launchers / banners all accept it.
                                          - type: object
                                            properties:
                                              type:
                                                type: string
                                                enum:
                                                  - run_javascript
                                              script:
                                                type: string
                                            required:
                                              - type
                                              - script
                                            description: >-
                                              Read-back of an existing script action —
                                              scripts are not authorable through this
                                              API. Echo it back UNCHANGED (same
                                              script) when rewriting the surrounding
                                              list and the stored action is preserved;
                                              omitting it deletes it (action lists are
                                              full replacements). Authoring a new or
                                              edited script is rejected.
                                          - type: object
                                            properties:
                                              type:
                                                type: string
                                                enum:
                                                  - unsupported
                                              note:
                                                type: string
                                            required:
                                              - type
                                            description: >-
                                              Echo-only placeholder for a stored
                                              action this schema cannot express
                                              (`note` = internal type). Echo it back
                                              to preserve the stored action; writing
                                              one fresh is rejected.
                                    waitSeconds:
                                      description: >-
                                        Delay in SECONDS between the `when`
                                        conditions matching and the `do` actions
                                        firing. The timer arms the first time
                                        `when` matches and the actions fire
                                        after the wait EVEN IF the conditions
                                        have since stopped matching (the match
                                        is latched, not re-checked). Capped at
                                        300 seconds by the runtime (a larger
                                        value is clamped).
                                      type: number
                                  required:
                                    - do
                              onClick:
                                description: >-
                                  Actions that run when the user clicks the
                                  step's TARGET ELEMENT on the page
                                  (click-to-advance) — distinct from a `button`
                                  block, whose actions fire on a button rendered
                                  inside the step. `tooltip` steps only: the
                                  other kinds have no target element to click,
                                  and the write rejects `onClick` on them.
                                type: array
                                items:
                                  oneOf:
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - goto_step
                                        step:
                                          type: string
                                          description: >-
                                            Target step: a step `key` declared
                                            elsewhere in the same write, or an
                                            existing step cvid. Resolved server-side
                                            to the cvid.
                                      required:
                                        - type
                                        - step
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - start_content
                                        content:
                                          type: string
                                          description: >-
                                            contentId of the flow or checklist to
                                            launch (an id from the content list) — a
                                            raw content id, NOT a step key (unlike
                                            goto_step). Must reference a flow or
                                            checklist (a banner / launcher /
                                            resource-center / tracker is rejected at
                                            write). The target must be PUBLISHED to
                                            actually start at runtime; an
                                            unknown/dangling id is rejected at
                                            validate.
                                        step:
                                          description: >-
                                            Optional cvid of a step within the
                                            launched flow to start at.
                                          type: string
                                      required:
                                        - type
                                        - content
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - navigate
                                        url:
                                          type: string
                                          description: >-
                                            Absolute URL, or an app-relative path
                                            ("/docs/x") resolved against the origin
                                            the user is on — relative paths are the
                                            normal choice for in-app navigation.
                                        newTab:
                                          description: >-
                                            Open the URL in a new browser tab
                                            instead of navigating the current one.
                                          type: boolean
                                      required:
                                        - type
                                        - url
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - dismiss
                                      required:
                                        - type
                                      description: >-
                                        Dismiss the piece the action lives on.
                                        NOT accepted everywhere this union
                                        appears: a resource center has no
                                        dismiss (closing the panel is a UI
                                        affordance, not an action) and an
                                        announcement is marked seen, never
                                        dismissed — writes there are rejected
                                        (E1017), not ignored. Flows / checklists
                                        / launchers / banners all accept it.
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - run_javascript
                                        script:
                                          type: string
                                      required:
                                        - type
                                        - script
                                      description: >-
                                        Read-back of an existing script action —
                                        scripts are not authorable through this
                                        API. Echo it back UNCHANGED (same
                                        script) when rewriting the surrounding
                                        list and the stored action is preserved;
                                        omitting it deletes it (action lists are
                                        full replacements). Authoring a new or
                                        edited script is rejected.
                                    - type: object
                                      properties:
                                        type:
                                          type: string
                                          enum:
                                            - unsupported
                                        note:
                                          type: string
                                      required:
                                        - type
                                      description: >-
                                        Echo-only placeholder for a stored
                                        action this schema cannot express
                                        (`note` = internal type). Echo it back
                                        to preserve the stored action; writing
                                        one fresh is rejected.
                              advanced:
                                type: object
                                properties:
                                  hasUnsupported:
                                    type: boolean
                                    description: >-
                                      true = this step carries stored
                                      configuration this API cannot express
                                      (e.g. an auto-recorded element
                                      fingerprint). Read-only signal: echoing
                                      the step back preserves that configuration
                                      untouched; it is not editable here.
                                required:
                                  - hasUnsupported
                            required:
                              - object
                              - id
                              - cvid
                              - name
                              - type
                              - sequence
                              - themeId
                              - content
                        startRules:
                          type: object
                          properties:
                            when:
                              description: >-
                                Start conditions (full replacement when
                                present). Omit to keep the existing conditions
                                and change only the settings.
                              type: array
                              items:
                                $ref: >-
                                  #/components/schemas/ListContentResponseDto__schema1
                            frequency:
                              description: >-
                                How often the content may auto-start
                                (flow/checklist only). Left unset on a write,
                                the builder default (`once`) is seeded and
                                STORED — read-backs show the effective mode
                                explicitly. A version stored with NO frequency
                                at all (reachable only through
                                legacy/builder-external writes, never through
                                this API) runs with NO limit: it starts again
                                every time its rules match once the prior
                                session ends — validate_content_version warns on
                                that state.
                              type: object
                              properties:
                                mode:
                                  type: string
                                  enum:
                                    - once
                                    - multiple
                                    - unlimited
                                  description: >-
                                    once = show a single time; multiple = up to
                                    N times per window; unlimited = every time
                                    the conditions match (subject to `every`).
                                every:
                                  description: >-
                                    Re-show window. Used by `multiple` (with
                                    `times`) and `unlimited`; ignored for
                                    `once`. If omitted for those modes a default
                                    window is applied. Manual and programmatic
                                    starts also count toward the `multiple`
                                    limit.
                                  type: object
                                  properties:
                                    times:
                                      type: number
                                    duration:
                                      type: number
                                    unit:
                                      type: string
                                      enum:
                                        - seconds
                                        - minutes
                                        - hours
                                        - days
                                  required:
                                    - duration
                                    - unit
                                atLeast:
                                  description: >-
                                    Only auto-start if no OTHER content of the
                                    SAME type has been shown within this window
                                    — and since only flows accept this knob, in
                                    practice: no other FLOW. A banner /
                                    checklist / launcher showing does NOT block
                                    it. Avoids stacking several flows on a user
                                    at once.
                                  type: object
                                  properties:
                                    duration:
                                      type: number
                                    unit:
                                      type: string
                                      enum:
                                        - seconds
                                        - minutes
                                        - hours
                                        - days
                                  required:
                                    - duration
                                    - unit
                              required:
                                - mode
                            priority:
                              description: >-
                                Tie-breaker when a user matches the start
                                conditions for more than one piece of content at
                                the same time — the higher priority starts
                                first. Content with no priority set ranks as
                                `medium`.
                              type: string
                              enum:
                                - highest
                                - high
                                - medium
                                - low
                                - lowest
                            waitSeconds:
                              description: >-
                                Delay in SECONDS between the start conditions
                                matching and the content becoming ELIGIBLE to
                                start. The countdown itself survives the
                                conditions un-matching mid-wait, but unlike a
                                trigger wait (which fires its actions
                                regardless), an elapsed start-rule wait
                                guarantees nothing: the conditions are
                                RE-CHECKED at show time, and the content starts
                                at the next moment they match again. One
                                exception: when a session of the same content
                                type starts or ends mid-wait, in-flight timers
                                are cancelled and re-armed — a still-matching
                                version then restarts its wait from zero. Capped
                                at 300 seconds by the runtime (a larger value is
                                clamped).
                              type: number
                            startIfNotComplete:
                              description: >-
                                When true, this content won't auto-start for
                                users who have already completed it.
                              type: boolean
                        hideRules:
                          type: object
                          properties:
                            when:
                              type: array
                              items:
                                $ref: >-
                                  #/components/schemas/ListContentResponseDto__schema1
                          required:
                            - when
                          description: >-
                            While `when` matches, on-screen content of this
                            version is hidden — the session is SUSPENDED, not
                            ended: when the conditions stop matching the same
                            session reappears at the same step. Use start-rule
                            conditions to keep content from starting; use hide
                            rules to blank it in specific places (e.g. a
                            settings page).
                        data:
                          description: >-
                            Decompiled type-specific body for non-flow content —
                            the same six per-type shapes as the write `data`
                            (fully typed on the content-versions endpoints).
                            Present only with the `data` expand; a flow has no
                            `data` — its body is `steps`.
                        scheduledAt:
                          description: >-
                            Announcement versions only: the "announcement time"
                            gating feed visibility and ordering. Absent on other
                            content types and until set (publish stamps it when
                            the author left it null, so published announcements
                            always carry one).
                          type: string
                        updatedAt:
                          type: string
                          format: date-time
                        createdAt:
                          type: string
                          format: date-time
                      required:
                        - id
                        - object
                        - number
                        - firstPublishedAt
                        - themeId
                        - questions
                        - updatedAt
                        - createdAt
                  required:
                    - environmentId
                    - published
                    - publishedVersionId
                    - publishedAt
                description: >-
                  Where this content is live RIGHT NOW: one row per environment
                  it is currently published to (empty = published nowhere). Rows
                  disappear on unpublish.
              deleted:
                type: boolean
              updatedAt:
                type: string
                format: date-time
              createdAt:
                type: string
                format: date-time
            required:
              - id
              - object
              - name
              - type
              - buildUrl
              - editedVersionId
              - environments
              - deleted
              - updatedAt
              - createdAt
        next:
          type: string
          description: >-
            Full URL of the next page — request it as-is (it already carries
            `cursor=` and your query parameters). null = no further pages.
          nullable: true
        previous:
          type: string
          description: >-
            Full URL of the previous page — request it as-is. null = already at
            the first page.
          nullable: true
      required:
        - results
        - next
        - previous
    ErrorResponseDto:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: >-
                Stable machine-readable code (e.g. E1017). Match on this, never
                on `message`.
            message:
              type: string
              description: Human-readable summary. Wording may change between releases.
            issues:
              description: >-
                Validation errors (E1017) may carry one entry per problem so
                every field can be fixed in a single round-trip. Absent on other
                errors.
              type: array
              items:
                type: object
                properties:
                  rule:
                    type: string
                    description: >-
                      Which validation layer rejected it: schema |
                      reactive_condition | action_not_allowed | step_shape |
                      reference_target | auto_start | media_url. New values may
                      be added; treat an unknown value as a generic validation
                      failure.
                  message:
                    type: string
                  path:
                    description: >-
                      Path into the request body (e.g.
                      `steps[0].triggers[0].when[1]`).
                    type: string
                required:
                  - rule
                  - message
            doc_url:
              type: string
              description: Base URL of the API documentation.
      required:
        - error
    ListContentResponseDto__schema0:
      oneOf:
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - text
            markdown:
              type: string
              description: >-
                A small markdown subset: paragraphs, `# `/`## ` headings (h1/h2
                only — no h3+), `-`/`*` and `1.` lists, ``` code fences; inline
                `**bold**`, `*italic*`, `[text](url)`, and `{{ attribute_code |
                default: "x" }}` for user attributes. Anything outside this
                subset is SILENTLY normalized, not rejected: h3+ → h2;
                blockquotes flatten to paragraphs; tables, horizontal rules,
                strikethrough, inline images/code, and liquid filters other than
                `default` are dropped. Unsupported syntax won't round-trip —
                don't rely on it.
          required:
            - type
            - markdown
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - image
            url:
              type: string
              minLength: 1
            alt:
              type: string
            link:
              type: object
              properties:
                url:
                  type: string
                newTab:
                  type: boolean
              required:
                - url
            width:
              type: object
              properties:
                unit:
                  type: string
                  enum:
                    - percent
                    - pixels
                value:
                  type: number
                  minimum: 0
              required:
                - unit
            margin:
              type: object
              properties:
                enabled:
                  type: boolean
                top:
                  type: number
                bottom:
                  type: number
                left:
                  type: number
                right:
                  type: number
          required:
            - type
            - url
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - button
            text:
              type: string
            actions:
              type: array
              items:
                oneOf:
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - goto_step
                      step:
                        type: string
                        description: >-
                          Target step: a step `key` declared elsewhere in the
                          same write, or an existing step cvid. Resolved
                          server-side to the cvid.
                    required:
                      - type
                      - step
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - start_content
                      content:
                        type: string
                        description: >-
                          contentId of the flow or checklist to launch (an id
                          from the content list) — a raw content id, NOT a step
                          key (unlike goto_step). Must reference a flow or
                          checklist (a banner / launcher / resource-center /
                          tracker is rejected at write). The target must be
                          PUBLISHED to actually start at runtime; an
                          unknown/dangling id is rejected at validate.
                      step:
                        description: >-
                          Optional cvid of a step within the launched flow to
                          start at.
                        type: string
                    required:
                      - type
                      - content
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - navigate
                      url:
                        type: string
                        description: >-
                          Absolute URL, or an app-relative path ("/docs/x")
                          resolved against the origin the user is on — relative
                          paths are the normal choice for in-app navigation.
                      newTab:
                        description: >-
                          Open the URL in a new browser tab instead of
                          navigating the current one.
                        type: boolean
                    required:
                      - type
                      - url
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - dismiss
                    required:
                      - type
                    description: >-
                      Dismiss the piece the action lives on. NOT accepted
                      everywhere this union appears: a resource center has no
                      dismiss (closing the panel is a UI affordance, not an
                      action) and an announcement is marked seen, never
                      dismissed — writes there are rejected (E1017), not
                      ignored. Flows / checklists / launchers / banners all
                      accept it.
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - run_javascript
                      script:
                        type: string
                    required:
                      - type
                      - script
                    description: >-
                      Read-back of an existing script action — scripts are not
                      authorable through this API. Echo it back UNCHANGED (same
                      script) when rewriting the surrounding list and the stored
                      action is preserved; omitting it deletes it (action lists
                      are full replacements). Authoring a new or edited script
                      is rejected.
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - unsupported
                      note:
                        type: string
                    required:
                      - type
                    description: >-
                      Echo-only placeholder for a stored action this schema
                      cannot express (`note` = internal type). Echo it back to
                      preserve the stored action; writing one fresh is rejected.
            disabledWhen:
              description: >-
                REACTIVE slot — polled live in the browser (the button disables
                the moment the conditions match). Client-evaluable condition
                types only: attribute / current_url / element / text_input /
                text_filled / time_window; event / segment / content_state are
                rejected (E1017).
              type: array
              items:
                $ref: '#/components/schemas/ListContentResponseDto__schema1'
            hiddenWhen:
              description: >-
                REACTIVE slot — polled live in the browser (the button
                shows/hides as conditions change). Same client-evaluable-only
                rule as `disabledWhen`.
              type: array
              items:
                $ref: '#/components/schemas/ListContentResponseDto__schema1'
            variant:
              type: string
              enum:
                - primary
                - secondary
            margin:
              type: object
              properties:
                enabled:
                  type: boolean
                top:
                  type: number
                bottom:
                  type: number
                left:
                  type: number
                right:
                  type: number
          required:
            - type
            - text
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - embed
            url:
              type: string
              minLength: 1
              description: >-
                Paste the page's normal URL (e.g. a youtube.com/watch link) — on
                write it is resolved through the standard oEmbed provider
                registry (YouTube, Vimeo, Loom, Figma, …) and the provider's
                official embed markup is stored, so you never hand-build /embed/
                URLs. A URL no provider claims is iframed as-is — it renders
                only if that site allows being framed (no X-Frame-Options/CSP
                block).
            width:
              type: object
              properties:
                unit:
                  type: string
                  enum:
                    - percent
                    - pixels
                value:
                  type: number
                  minimum: 0
              required:
                - unit
            height:
              description: >-
                Embed height. Optional ONLY for provider embeds (YouTube/Vimeo/…
                size themselves by aspect ratio); a URL with NO oEmbed provider
                has no ratio, and omitting a pixel height leaves the iframe at
                the browser's built-in default — a strip ~150px tall, almost
                never the intended size (validate warns). For plain-iframe URLs
                always set `{ "unit": "pixels", "value": … }`.
              type: object
              properties:
                unit:
                  type: string
                  enum:
                    - percent
                    - pixels
                value:
                  type: number
                  minimum: 0
              required:
                - unit
            margin:
              type: object
              properties:
                enabled:
                  type: boolean
                top:
                  type: number
                bottom:
                  type: number
                left:
                  type: number
                right:
                  type: number
          required:
            - type
            - url
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - question
            question:
              oneOf:
                - type: object
                  properties:
                    kind:
                      type: string
                      enum:
                        - nps
                    name:
                      type: string
                      description: >-
                        The question's internal name / analytics label (it is
                        the `questionName` on captured responses). It is NOT
                        rendered to the user — the widget shows only the input
                        (scale / options / text field), not this string. To show
                        a visible question prompt, add a `text` block in the
                        SAME step before the question block; a question with
                        only a `name` renders as bare options with no question
                        text.
                    cvid:
                      type: string
                    lowLabel:
                      type: string
                    highLabel:
                      type: string
                    bindAttribute:
                      description: >-
                        Optional: codeName of an EXISTING attribute (create the
                        attribute definition first) to ALSO save this answer
                        onto the user for targeting/segmentation — use the
                        codeName, NOT the id. The write does not check it, but
                        the version validation WARNS when the attribute is
                        missing or its dataType mismatches the answer — read
                        warnings. A wrong code that slips through silently
                        captures nothing at runtime. Match the attribute
                        dataType to the answer: number (nps / rating), string
                        (single-select choice), list (multi-select choice).
                        Leaving it unset still records the answer as a response
                        event — bind only when you need to target/segment on it.
                      type: string
                  required:
                    - kind
                    - name
                - type: object
                  properties:
                    kind:
                      type: string
                      enum:
                        - rating
                    name:
                      type: string
                      description: >-
                        The question's internal name / analytics label (it is
                        the `questionName` on captured responses). It is NOT
                        rendered to the user — the widget shows only the input
                        (scale / options / text field), not this string. To show
                        a visible question prompt, add a `text` block in the
                        SAME step before the question block; a question with
                        only a `name` renders as bare options with no question
                        text.
                    cvid:
                      type: string
                    style:
                      type: string
                      enum:
                        - star
                        - scale
                      description: >-
                        star = star rating; scale = a numeric scale. A "scale"
                        question IS a rating with style:"scale" — there is no
                        separate "scale" kind.
                    range:
                      type: object
                      properties:
                        low:
                          type: number
                        high:
                          type: number
                      required:
                        - low
                        - high
                      description: 'Numeric range, e.g. { low: 1, high: 5 }.'
                    lowLabel:
                      type: string
                    highLabel:
                      type: string
                    bindAttribute:
                      description: >-
                        Optional: codeName of an EXISTING attribute (create the
                        attribute definition first) to ALSO save this answer
                        onto the user for targeting/segmentation — use the
                        codeName, NOT the id. The write does not check it, but
                        the version validation WARNS when the attribute is
                        missing or its dataType mismatches the answer — read
                        warnings. A wrong code that slips through silently
                        captures nothing at runtime. Match the attribute
                        dataType to the answer: number (nps / rating), string
                        (single-select choice), list (multi-select choice).
                        Leaving it unset still records the answer as a response
                        event — bind only when you need to target/segment on it.
                      type: string
                  required:
                    - kind
                    - name
                    - style
                    - range
                - type: object
                  properties:
                    kind:
                      type: string
                      enum:
                        - text
                    name:
                      type: string
                      description: >-
                        The question's internal name / analytics label (it is
                        the `questionName` on captured responses). It is NOT
                        rendered to the user — the widget shows only the input
                        (scale / options / text field), not this string. To show
                        a visible question prompt, add a `text` block in the
                        SAME step before the question block; a question with
                        only a `name` renders as bare options with no question
                        text.
                    cvid:
                      type: string
                    multiline:
                      type: boolean
                    placeholder:
                      type: string
                    buttonText:
                      type: string
                    required:
                      description: >-
                        Require an answer before submit. ONLY `text` supports
                        this — nps / rating / choice cannot be marked required.
                      type: boolean
                    bindAttribute:
                      description: >-
                        Optional: codeName of an EXISTING attribute (create the
                        attribute definition first) to ALSO save this answer
                        onto the user for targeting/segmentation — use the
                        codeName, NOT the id. The write does not check it, but
                        the version validation WARNS when the attribute is
                        missing or its dataType mismatches the answer — read
                        warnings. A wrong code that slips through silently
                        captures nothing at runtime. Match the attribute
                        dataType to the answer: number (nps / rating), string
                        (single-select choice), list (multi-select choice).
                        Leaving it unset still records the answer as a response
                        event — bind only when you need to target/segment on it.
                      type: string
                  required:
                    - kind
                    - name
                    - multiline
                - type: object
                  properties:
                    kind:
                      type: string
                      enum:
                        - choice
                    name:
                      type: string
                      description: >-
                        The question's internal name / analytics label (it is
                        the `questionName` on captured responses). It is NOT
                        rendered to the user — the widget shows only the input
                        (scale / options / text field), not this string. To show
                        a visible question prompt, add a `text` block in the
                        SAME step before the question block; a question with
                        only a `name` renders as bare options with no question
                        text.
                    cvid:
                      type: string
                    options:
                      type: array
                      items:
                        type: object
                        properties:
                          label:
                            type: string
                          value:
                            type: string
                        required:
                          - label
                          - value
                      description: >-
                        Each option has a human-facing `label` and a stored
                        `value` — the `value` is what gets recorded/bound as the
                        answer.
                    allowMultiple:
                      type: boolean
                      description: >-
                        false = single-select, true = multi-select. A
                        multi-select answer needs a `list`-typed bound
                        attribute.
                    enableOther:
                      type: boolean
                    otherPlaceholder:
                      type: string
                    shuffle:
                      type: boolean
                    buttonText:
                      type: string
                    bindAttribute:
                      description: >-
                        Optional: codeName of an EXISTING attribute (create the
                        attribute definition first) to ALSO save this answer
                        onto the user for targeting/segmentation — use the
                        codeName, NOT the id. The write does not check it, but
                        the version validation WARNS when the attribute is
                        missing or its dataType mismatches the answer — read
                        warnings. A wrong code that slips through silently
                        captures nothing at runtime. Match the attribute
                        dataType to the answer: number (nps / rating), string
                        (single-select choice), list (multi-select choice).
                        Leaving it unset still records the answer as a response
                        event — bind only when you need to target/segment on it.
                      type: string
                  required:
                    - kind
                    - name
                    - options
                    - allowMultiple
            actions:
              description: >-
                Actions that fire when this question is answered (on pick for
                nps/rating/single-select; on its Submit button for
                text/multi-select). Put a `goto_step` HERE to advance to the
                next step — without it the question records the answer but the
                flow does NOT advance (validate flags the next step "not
                reachable"). Do NOT add a separate `button` block just to
                advance: it doubles up with the question's own submit
                affordance.
              type: array
              items:
                oneOf:
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - goto_step
                      step:
                        type: string
                        description: >-
                          Target step: a step `key` declared elsewhere in the
                          same write, or an existing step cvid. Resolved
                          server-side to the cvid.
                    required:
                      - type
                      - step
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - start_content
                      content:
                        type: string
                        description: >-
                          contentId of the flow or checklist to launch (an id
                          from the content list) — a raw content id, NOT a step
                          key (unlike goto_step). Must reference a flow or
                          checklist (a banner / launcher / resource-center /
                          tracker is rejected at write). The target must be
                          PUBLISHED to actually start at runtime; an
                          unknown/dangling id is rejected at validate.
                      step:
                        description: >-
                          Optional cvid of a step within the launched flow to
                          start at.
                        type: string
                    required:
                      - type
                      - content
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - navigate
                      url:
                        type: string
                        description: >-
                          Absolute URL, or an app-relative path ("/docs/x")
                          resolved against the origin the user is on — relative
                          paths are the normal choice for in-app navigation.
                      newTab:
                        description: >-
                          Open the URL in a new browser tab instead of
                          navigating the current one.
                        type: boolean
                    required:
                      - type
                      - url
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - dismiss
                    required:
                      - type
                    description: >-
                      Dismiss the piece the action lives on. NOT accepted
                      everywhere this union appears: a resource center has no
                      dismiss (closing the panel is a UI affordance, not an
                      action) and an announcement is marked seen, never
                      dismissed — writes there are rejected (E1017), not
                      ignored. Flows / checklists / launchers / banners all
                      accept it.
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - run_javascript
                      script:
                        type: string
                    required:
                      - type
                      - script
                    description: >-
                      Read-back of an existing script action — scripts are not
                      authorable through this API. Echo it back UNCHANGED (same
                      script) when rewriting the surrounding list and the stored
                      action is preserved; omitting it deletes it (action lists
                      are full replacements). Authoring a new or edited script
                      is rejected.
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - unsupported
                      note:
                        type: string
                    required:
                      - type
                    description: >-
                      Echo-only placeholder for a stored action this schema
                      cannot express (`note` = internal type). Echo it back to
                      preserve the stored action; writing one fresh is rejected.
          required:
            - type
            - question
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - columns
            columns:
              type: array
              items:
                type: object
                properties:
                  width:
                    type: object
                    properties:
                      unit:
                        type: string
                        enum:
                          - percent
                          - pixels
                          - fill
                      value:
                        type: number
                        minimum: 0
                    required:
                      - unit
                  justify:
                    description: >-
                      Horizontal alignment of this column's own block(s) within
                      the column's width — use "end"/"center" to right-align or
                      center a lone button (a single-column `columns` block).
                    type: string
                    enum:
                      - start
                      - center
                      - end
                      - between
                      - around
                      - evenly
                  align:
                    type: string
                    enum:
                      - start
                      - center
                      - end
                      - baseline
                  padding:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      top:
                        type: number
                      bottom:
                        type: number
                      left:
                        type: number
                      right:
                        type: number
                  blocks:
                    type: array
                    items:
                      $ref: '#/components/schemas/ListContentResponseDto__schema0'
                required:
                  - blocks
              description: >-
                One entry per column, laid out left-to-right. Each column is a
                mini vertical stack of `blocks` (usually one).
          required:
            - type
            - columns
          description: >-
            Lays 2+ blocks out side by side in one row. Top-level `content`
            blocks otherwise stack vertically — each is its own full-width row —
            so two `button` blocks placed directly in `content` render as two
            stacked rows, NOT a button pair. For a modal/tooltip footer with a
            Skip + primary button: one `columns` block with two `{ width: {
            unit: "fill" }, blocks: [...] }` entries, one button per column.
        - type: object
          properties:
            object:
              default: block
              type: string
              enum:
                - block
            id:
              type: string
            type:
              type: string
              enum:
                - unsupported
            note:
              type: string
          required:
            - type
    ListContentResponseDto__schema1:
      oneOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - group
            match:
              type: string
              enum:
                - all
                - any
            conditions:
              minItems: 1
              type: array
              items:
                $ref: '#/components/schemas/ListContentResponseDto__schema1'
              description: >-
                The grouped conditions — at least one. An EMPTY group is not "no
                filter": it never matches, so next to an AND it makes the whole
                rule unmatchable, and writing one is rejected. A version saved
                with an empty group in the BUILDER still reads back with it
                (validate warns); writing that list back is refused until the
                group is filled or dropped.
          required:
            - type
            - match
            - conditions
        - type: object
          properties:
            type:
              type: string
              enum:
                - attribute
            scope:
              type: string
              enum:
                - user
                - company
                - companyMembership
              description: >-
                Which entity owns the attribute — `user` (the end user),
                `company`, or `companyMembership`. Same value as the attribute
                definition's `scope` (see the attribute definitions list);
                required to disambiguate a codeName that exists in more than one
                scope.
            attribute:
              type: string
            op:
              type: string
              enum:
                - is
                - not
                - contains
                - not_contains
                - starts_with
                - ends_with
                - any
                - empty
                - lt
                - lte
                - gt
                - gte
                - between
                - 'true'
                - 'false'
                - includes_any
                - includes_all
                - not_includes_any
                - not_includes_all
                - less_than
                - exactly
                - more_than
                - before
                - 'on'
                - after
              description: >-
                Operator — the allowed set depends on the attribute dataType.
                String: is | not | contains | not_contains | starts_with |
                ends_with | any | empty. Number: is | not | lt | lte | gt | gte
                | between | any | empty. Boolean: true | false | any | empty.
                List: includes_any | includes_all | not_includes_any |
                not_includes_all | any | empty. DateTime: less_than | exactly |
                more_than (relative — `value` is a number of days) | before | on
                | after (`value` is an absolute date) | any | empty. The
                relative ops are ONE-SIDED bounds around (now − N days):
                `less_than N` = the date is AFTER now−N — so it also matches
                every FUTURE date, and on a future-dated attribute (a trial end,
                a renewal date) it is NOT "within the last N days"; `more_than
                N` = the date is BEFORE now−N. **"Signed up in the last N days"
                therefore needs BOTH bounds** — `less_than N` AND `more_than 0`
                in one `all` group; `less_than N` alone silently includes anyone
                whose date is in the future (a mis-mapped trial-end column, a
                clock/timezone slip), and those are exactly the users a new-user
                audience must not contain (observed in testing). Negative N
                shifts the bound into the future: the rolling "within the NEXT 7
                days" window is `less_than` value "0" AND `more_than` value "-7"
                (two conditions, both required). The relative ops are
                DAY-granularity only — no unit field; for hour/minute windows
                use an `event` condition with a `within` (which has a `unit`).
            value:
              description: >-
                The comparison value (string / number-as-string / date). Omit
                for any/empty/true/false.
              type: string
            value2:
              description: >-
                Upper bound for the `between` operator (`value` is the lower
                bound).
              type: string
            values:
              description: Values for the List operators (includes_any / includes_all / …).
              type: array
              items:
                type: string
          required:
            - type
            - scope
            - attribute
            - op
        - type: object
          properties:
            type:
              type: string
              enum:
                - segment
            segment:
              type: string
            in:
              type: boolean
          required:
            - type
            - segment
            - in
        - type: object
          properties:
            type:
              type: string
              enum:
                - current_url
            includes:
              type: array
              items:
                type: string
              description: >-
                URL patterns (anchored whole-url match, NOT substring/regex).
                `*` = wildcard within one url part; `:name` = one path segment.
                A bare `*` (i.e. `["*"]`) matches EVERY page on every host incl.
                deep paths — the canonical always-on / whole-site pattern (use
                it when content should be available everywhere). Scope it down
                instead with: `*/` (homepage only — path exactly `/`),
                `*/pricing` (one page), `*/app/*` (a section + below),
                `host.com/*` (any page on a specific host). Multiple patterns
                are OR-matched: the URL matches this list if it matches ANY one
                pattern (so "/tasks OR /dashboard" is one condition with both
                patterns here — no group needed).
            excludes:
              description: >-
                URL patterns to exclude (same syntax as includes); excludes win
                over includes.
              type: array
              items:
                type: string
          required:
            - type
            - includes
        - type: object
          properties:
            type:
              type: string
              enum:
                - element
            target:
              type: object
              properties:
                selector:
                  type: string
                  minLength: 1
                  description: >-
                    A stable CSS selector for the element. The runtime targets
                    the FIRST match — so either make the selector unique, or
                    pair a stable non-unique selector with `nth` to pick the
                    intended match. A non-unique selector with no `nth` targets
                    the first (often wrong) element and the tooltip silently
                    won't render.
                text:
                  description: >-
                    Optional refinement of `selector`. Requires the targeted
                    element's visible text to equal this (exact match, after
                    trim) — use it to pin a specific content/state (e.g. a
                    stable id whose displayed text you want to match: id +
                    text). It refines the element chosen by `selector`/`nth`; on
                    its own it does NOT search among multiple matches, so
                    disambiguate a non-unique selector with `nth`, not `text`
                    alone.
                  type: string
                nth:
                  description: >-
                    Optional refinement of `selector`. 0-based index to pick
                    which match when the selector isn't unique — e.g. a stable
                    selector matching 3 elements + `nth: 1` targets the 2nd,
                    giving a unique result. Matches are taken in document order
                    (as they appear in the page HTML). Range 0–4 — only the
                    first 5 matches are addressable; a larger value is rejected.
                  type: integer
                  minimum: 0
                  maximum: 4
              required:
                - selector
            state:
              type: string
              enum:
                - present
                - hidden
                - disabled
                - enabled
                - clicked
                - unclicked
              description: >-
                `present` means NOT CLIPPED AWAY: the element is in the DOM and
                its box lies inside the viewport / its scroll ancestors —
                scrolled off-screen or `display:none` never satisfies it (and
                `hidden` is its negation). It is NOT "the user can see something
                there": an EMPTY, zero-height placeholder node satisfies
                `present` (observed in testing: a checklist task keyed on an
                initially-empty `<p>` status line ticked itself the moment the
                checklist appeared, before the shopper did anything). So do not
                use element presence as a proxy for "the app has said
                something": most apps keep the container mounted and only fill
                in its text. Match the TEXT instead (`target.text` + `present`,
                or the negation trick: the old text `hidden`). Appearances
                shorter than about a second can be missed entirely.
                `disabled`/`enabled` read the element disabled state at
                evaluation time. **`clicked` means "clicked since page load AND
                the element is STILL in the DOM right now"** — both halves,
                re-checked every evaluation. The click memory latches (the
                listener attaches the FIRST time the condition is evaluated, so
                earlier clicks are invisible, and the memory survives a
                re-render), but the element lookup is redone each poll. Two
                consequences, one of them silent: (1) **an element that UNMOUNTS
                on click can NEVER satisfy it** — the click lands, the element
                vanishes, the lookup fails from then on and the condition stays
                false forever with no error (observed in testing: a tracker on a
                button that clears its own toolbar counted ZERO real clicks);
                (2) an element that unmounts and REMOUNTS satisfies it again, so
                a tracker gated on it fires once per remount — not once per page
                load. Unlike `present`, this lookup does NOT require viewport
                visibility: scrolling the target off-screen keeps `clicked`
                true. `unclicked` negates the same pair, so it is also false
                while the element is absent. To count a COMPLETED action,
                condition on what the app shows afterwards (a success toast, a
                state change) rather than `clicked` on the button that starts
                it.
          required:
            - type
            - state
        - type: object
          properties:
            type:
              type: string
              enum:
                - content_state
            content:
              type: string
              description: >-
                contentId of the FLOW or CHECKLIST whose per-user state to check
                (an id from the content list). Only flows and checklists record
                this state — referencing a banner / launcher / resource-center /
                tracker is rejected at write.
            state:
              type: string
              enum:
                - seen
                - unseen
                - completed
                - uncompleted
                - active
                - inactive
              description: >-
                The referenced flow/checklist's state for THIS user. seen =
                started at least once (for a flow, TRUE from the moment it
                opens; for a checklist, TRUE only once the user EXPANDS the
                panel — a `initialDisplay: "button"` checklist whose launcher is
                never clicked stays unseen forever); unseen = never started;
                active = currently open/running; inactive = NOT currently
                running (covers both never-started and ran-then-closed);
                completed = reached a goal/completion step; uncompleted = not
                completed. To gate piece B until flow A has run AND closed (the
                usual "show next thing after the welcome flow" sequencing), use
                `seen` AND `inactive` together — `seen` alone fires while A is
                still open (B piles on top), and `completed` alone strands users
                who skip/dismiss A.
          required:
            - type
            - content
            - state
        - type: object
          properties:
            type:
              type: string
              enum:
                - event
            event:
              type: string
            count:
              description: >-
                How many times the event must have occurred. Omit it for the
                common case "the event has happened" (treated as at_least 1).
                Set `op`/`n` for a threshold (`between` needs `n` and `n2`).
                `at_least`/`between` require n ≥ 1; use `at_most`/`exactly` with
                0 for "never happened".
              type: object
              properties:
                op:
                  type: string
                  enum:
                    - at_least
                    - at_most
                    - exactly
                    - between
                'n':
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
                n2:
                  type: integer
                  minimum: 0
                  maximum: 9007199254740991
              required:
                - op
                - 'n'
            within:
              description: >-
                Optional time window for the event count. Omit it (or use
                `any_time`) to count over all time — "the event has ever
                happened". Any other `op` (`in_the_last` / `more_than` /
                `between`) requires BOTH `value` and `unit`, and `between` also
                `value2` — rejected at write otherwise.
              type: object
              properties:
                op:
                  type: string
                  enum:
                    - in_the_last
                    - more_than
                    - between
                    - any_time
                value:
                  type: number
                value2:
                  type: number
                unit:
                  type: string
                  enum:
                    - seconds
                    - minutes
                    - hours
                    - days
              required:
                - op
            scope:
              description: >-
                Whose event activity to count (default `current_user`).
                `current_user` = only this user's own events.
                `current_user_in_company` = this user's events, but counted
                within their currently-associated company context (needs the
                user associated to a company via `group()` / the
                company-membership API). `any_user_in_company` = events by ANY
                user in this user's company — account-level activity (e.g.
                "anyone on the account has done X"). The two company scopes
                require the user to be in a company or they never match.
              type: string
              enum:
                - current_user
                - current_user_in_company
                - any_user_in_company
            where:
              type: array
              items:
                $ref: '#/components/schemas/ListContentResponseDto__schema2'
          required:
            - type
            - event
        - type: object
          properties:
            type:
              type: string
              enum:
                - text_input
            target:
              type: object
              properties:
                selector:
                  type: string
                  minLength: 1
                  description: >-
                    A stable CSS selector for the element. The runtime targets
                    the FIRST match — so either make the selector unique, or
                    pair a stable non-unique selector with `nth` to pick the
                    intended match. A non-unique selector with no `nth` targets
                    the first (often wrong) element and the tooltip silently
                    won't render.
                text:
                  description: >-
                    Optional refinement of `selector`. Requires the targeted
                    element's visible text to equal this (exact match, after
                    trim) — use it to pin a specific content/state (e.g. a
                    stable id whose displayed text you want to match: id +
                    text). It refines the element chosen by `selector`/`nth`; on
                    its own it does NOT search among multiple matches, so
                    disambiguate a non-unique selector with `nth`, not `text`
                    alone.
                  type: string
                nth:
                  description: >-
                    Optional refinement of `selector`. 0-based index to pick
                    which match when the selector isn't unique — e.g. a stable
                    selector matching 3 elements + `nth: 1` targets the 2nd,
                    giving a unique result. Matches are taken in document order
                    (as they appear in the page HTML). Range 0–4 — only the
                    first 5 matches are addressable; a larger value is rejected.
                  type: integer
                  minimum: 0
                  maximum: 4
              required:
                - selector
            op:
              type: string
              enum:
                - is
                - not
                - contains
                - not_contains
                - starts_with
                - ends_with
                - match
                - unmatch
                - any
                - empty
            value:
              type: string
          required:
            - type
            - op
        - type: object
          properties:
            type:
              type: string
              enum:
                - text_filled
            target:
              type: object
              properties:
                selector:
                  type: string
                  minLength: 1
                  description: >-
                    A stable CSS selector for the element. The runtime targets
                    the FIRST match — so either make the selector unique, or
                    pair a stable non-unique selector with `nth` to pick the
                    intended match. A non-unique selector with no `nth` targets
                    the first (often wrong) element and the tooltip silently
                    won't render.
                text:
                  description: >-
                    Optional refinement of `selector`. Requires the targeted
                    element's visible text to equal this (exact match, after
                    trim) — use it to pin a specific content/state (e.g. a
                    stable id whose displayed text you want to match: id +
                    text). It refines the element chosen by `selector`/`nth`; on
                    its own it does NOT search among multiple matches, so
                    disambiguate a non-unique selector with `nth`, not `text`
                    alone.
                  type: string
                nth:
                  description: >-
                    Optional refinement of `selector`. 0-based index to pick
                    which match when the selector isn't unique — e.g. a stable
                    selector matching 3 elements + `nth: 1` targets the 2nd,
                    giving a unique result. Matches are taken in document order
                    (as they appear in the page HTML). Range 0–4 — only the
                    first 5 matches are addressable; a larger value is rejected.
                  type: integer
                  minimum: 0
                  maximum: 4
              required:
                - selector
          required:
            - type
        - type: object
          properties:
            type:
              type: string
              enum:
                - time_window
            start:
              type: string
              description: >-
                Window start (ISO datetime). REQUIRED — the runtime never
                matches a window without a start, so an end-only window is
                rejected at write. For "until X" semantics, set start to any
                past instant and end to X.
            end:
              description: >-
                Window end (ISO datetime). Omit for an open-ended "from start
                onwards" window.
              type: string
          required:
            - type
            - start
        - type: object
          properties:
            type:
              type: string
              enum:
                - unsupported
            note:
              type: string
          required:
            - type
          description: >-
            Read-side placeholder for a stored condition this API cannot express
            (`note` says what it stands for — usually a DEAD condition the
            runtime never matches: a deleted attribute/event, an end-only time
            window). It cannot be written back (the placeholder carries no data
            to preserve): echoing it is rejected. Either remove it from the list
            you write — an explicit choice that DELETES the stored condition;
            mind that a never-matching node inside an AND list pins the whole
            rule to "never fires", so deleting it can bring the remaining
            conditions to life — or repair the original condition in the
            Usertour builder first.
    ListContentResponseDto__schema2:
      oneOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - event_attribute
            attribute:
              type: string
            op:
              type: string
              enum:
                - is
                - not
                - contains
                - not_contains
                - starts_with
                - ends_with
                - any
                - empty
                - lt
                - lte
                - gt
                - gte
                - between
                - 'true'
                - 'false'
                - includes_any
                - includes_all
                - not_includes_any
                - not_includes_all
                - less_than
                - exactly
                - more_than
                - before
                - 'on'
                - after
            value:
              type: string
            value2:
              type: string
            values:
              type: array
              items:
                type: string
          required:
            - type
            - attribute
            - op
        - type: object
          properties:
            type:
              type: string
              enum:
                - group
            match:
              type: string
              enum:
                - all
                - any
            conditions:
              minItems: 1
              type: array
              items:
                $ref: '#/components/schemas/ListContentResponseDto__schema2'
              description: >-
                The grouped conditions — at least one. An EMPTY group is not "no
                filter": it never matches, so next to an AND it makes the whole
                rule unmatchable, and writing one is rejected. A version saved
                with an empty group in the BUILDER still reads back with it
                (validate warns); writing that list back is refused until the
                group is filled or dropped.
          required:
            - type
            - match
            - conditions
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: utp_... personal API token (opaque)
      type: http

````