> ## 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.

# Update a segment



## OpenAPI

````yaml /api-reference-v2/openapi.json patch /v2/projects/{projectId}/segments/{id}
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}/segments/{id}:
    patch:
      tags:
        - Segments
      summary: Update a segment
      operationId: ApiSegmentsController_update
      parameters:
        - name: projectId
          required: true
          in: path
          description: Project ID
          schema:
            type: string
        - name: id
          required: true
          in: path
          description: Segment ID
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateSegmentBodyDto'
      responses:
        '200':
          description: Segment updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SegmentDto'
        '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'
        '404':
          description: Segment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '409':
          description: >-
            The built-in "all" segment cannot be modified or deleted (E1037) —
            create a condition segment for a filtered audience.
          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:
    UpdateSegmentBodyDto:
      type: object
      properties:
        name:
          type: string
          minLength: 1
        conditions:
          description: >-
            Replaces the conditions (condition segments only). Attribute
            conditions and groups only; top-level siblings are ANDed, wrap in a
            match:"any" group for OR — same rules as segment creation.
          type: array
          items:
            $ref: '#/components/schemas/UpdateSegmentBodyDto__schema0'
      additionalProperties: false
    SegmentDto:
      type: object
      properties:
        id:
          type: string
        object:
          type: string
          enum:
            - segment
        name:
          type: string
        bizType:
          type: string
          enum:
            - user
            - company
        kind:
          type: string
          enum:
            - all
            - condition
            - manual
          description: >-
            `all` = the built-in everyone segment (one per bizType; immutable,
            cannot be deleted); `condition` = membership computed from
            `conditions`; `manual` = explicit member list.
        conditions:
          description: >-
            Present on condition segments (decompiled to stable attribute
            codes). Top-level siblings are ANDed; an OR lives inside a
            match:"any" group — same rules as writes.
          type: array
          items:
            $ref: '#/components/schemas/SegmentDto__schema0'
        memberCount:
          description: >-
            Members in the requested environment — only on GET one segment with
            `expand=memberCount` (+ environmentId); the list endpoint never
            returns it. manual = explicit members; condition = users/companies
            matching the conditions right now; all = everyone in the
            environment. Counted with the SAME filter the users/companies list
            applies for `segmentId`, so the two always agree.
          type: number
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
      required:
        - id
        - object
        - name
        - bizType
        - kind
        - createdAt
        - updatedAt
    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
    UpdateSegmentBodyDto__schema0:
      oneOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - group
            match:
              type: string
              enum:
                - all
                - any
            conditions:
              minItems: 1
              type: array
              items:
                $ref: '#/components/schemas/UpdateSegmentBodyDto__schema0'
              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:
                - unsupported
            note:
              type: string
          required:
            - type
    SegmentDto__schema0:
      oneOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - group
            match:
              type: string
              enum:
                - all
                - any
            conditions:
              minItems: 1
              type: array
              items:
                $ref: '#/components/schemas/SegmentDto__schema0'
              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:
                - unsupported
            note:
              type: string
          required:
            - type
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: utp_... personal API token (opaque)
      type: http

````