swagger: '2.0'
info:
  title: FunnelFlux Assets API
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
  description: FunnelFlux PRO Assets API endpoints for managing funnels, pages, traffic sources, offer sources, conditions, visitor tags, categories, and related account assets.
  version: 2.0.0
  contact:
    name: FunnelFlux Support
    url: 'mailto:support@funnelflux.pro'
    email: support@funnelflux.pro
  termsOfService: 'https://funnelflux.com/pro/terms-and-conditions/'
host: api.funnelflux.pro
basePath: /v1
schemes:
  - https
consumes:
  - application/json
produces:
  - application/json
securityDefinitions:
  apiKeyInQuery:
    type: apiKey
    in: query
    name: key
    description: API key (legacy V1 behaviour). Pass `?key=USER_KEY` in query.
  apiKeyInHeader:
    type: apiKey
    in: header
    name: X-API-Key
    description: API key (legacy V1 behaviour). Pass user key in header.
security:
  - apiKeyInQuery: []
  - apiKeyInHeader: []
tags:
  - name: Traffic Sources
    description: API endpoints to manage traffic sources
  - name: Offer Sources
    description: API endpoints to manage offer sources
  - name: Funnel Groups
    description: API endpoints to manage funnel groups (campaigns)
  - name: Funnels
    description: API endpoints to manage funnels
  - name: Conditions
    description: API endpoints to manage conditions
  - name: Visitor Tags
    description: API endpoints to manage visitor tags
  - name: Page Groups
    description: API endpoints to manage page groups
  - name: Pages
    description: API endpoints to manage landers and offers
  - name: Categories
    description: API endpoints to manage categories
  - name: User
    description: API endpoints to manage user
  - name: Integration
    description: API endpoints to manage integration API keys
  - name: AI Node Settings
    description: API endpoints to manage AI node settings
parameters:
  assetStatus:
    name: status
    description: Status of resource
    in: query
    required: true
    type: string
    enum:
      - active
      - archived
      - not-deleted
      - all
  idCategory:
    name: idCategory
    description: Parent category of resource
    in: query
    required: true
    type: string
  idPage:
    name: idPage
    description: ID of page resource
    in: query
    required: true
    type: string
  pageType:
    name: pageType
    description: Type of page resource
    in: query
    required: false
    type: string
    enum:
      - lander
      - offer
  requiredPageType:
    name: pageType
    description: Type of page resource
    in: query
    required: true
    type: string
    enum:
      - lander
      - offer
  funnelType:
    name: funnelType
    description: Type of funnel
    in: query
    required: true
    type: string
    enum:
      - visual
      - flow
  optionalIdCategory:
    name: idCategory
    description: Optional category ID to filter by
    in: query
    required: false
    type: string
    allowEmptyValue: true
  optionalIdOfferSource:
    name: idOfferSource
    description: Optional offer source ID filter (offers only)
    in: query
    required: false
    type: string
    allowEmptyValue: true
  optionalFunnelType:
    name: funnelType
    description: Optional funnel type filter
    in: query
    required: false
    type: string
    enum:
      - visual
      - flow
paths:
  /offersource/list/:
    get:
      summary: List offer sources
      operationId: listOfferSources
      tags:
        - Offer Sources
      description: List all offer sources
      parameters:
        - $ref: '#/parameters/assetStatus'
        - $ref: '#/parameters/optionalIdCategory'
      responses:
        '200':
          description: List of offer sources
          schema:
            type: array
            items:
              $ref: '#/definitions/OfferSourceInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/find/byId/:
    get:
      summary: Find offer source by ID
      operationId: findOfferSourceById
      tags:
        - Offer Sources
      description: Retrieve an offer source by ID
      parameters:
        - name: idOfferSource
          in: query
          required: true
          type: string
          description: The ID of the offer source
      responses:
        '200':
          description: The requested offer source
          schema:
            $ref: '#/definitions/OfferSource'
        '401':
          description: Not authorized
        '404':
          description: Offer source not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/find/byIds/:
    get:
      summary: Find offer sources by ID list
      operationId: findOfferSourcesByIDs
      tags:
        - Offer Sources
      description: Retrieve all offer sources with the specified ids
      parameters:
        - name: idOfferSources
          in: query
          required: true
          type: string
          description: List of the offer source IDs to retrieve
      responses:
        '200':
          description: List of offer sources with the specified ids
          schema:
            type: array
            items:
              $ref: '#/definitions/OfferSource'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/find/byStatus/:
    get:
      summary: Find offer sources by status
      operationId: findOfferSourcesByStatus
      tags:
        - Offer Sources
      description: |-
        Retrieve all offer sources with the specified status.
        Returns slim projection (same as list endpoint). Use find/byId for full objects.
      parameters:
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of offer sources with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/OfferSourceInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/find/byCategory/:
    get:
      summary: Find offer sources by category
      operationId: findOfferSourcesByCategory
      tags:
        - Offer Sources
      description: Retrieve all offer sources under the specified category
      parameters:
        - $ref: '#/parameters/idCategory'
      responses:
        '200':
          description: List of offer sources
          schema:
            type: array
            items:
              $ref: '#/definitions/OfferSource'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/save/:
    post:
      operationId: createOfferSource
      summary: Create offer source
      tags:
        - Offer Sources
      description: Create a new offer source
      parameters:
        - in: body
          name: body
          description: The offer source definition
          required: true
          schema:
            $ref: '#/definitions/OfferSource'
      responses:
        '200':
          description: Offer source created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateOfferSource
      summary: Save offer source
      tags:
        - Offer Sources
      description: Update an existing offer source. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The offer source definition
          required: true
          schema:
            $ref: '#/definitions/OfferSource'
      responses:
        '200':
          description: Offer source updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/duplicate/:
    post:
      operationId: duplicateOfferSource
      summary: Duplicate offer source
      tags:
        - Offer Sources
      description: Create duplicate of existing offer source.
      parameters:
        - name: idOfferSource
          in: query
          description: ID of the offer source to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name for the new offer source.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created offer source
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source offer source not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/delete/:
    delete:
      operationId: deleteOfferSource
      summary: Delete offer source
      tags:
        - Offer Sources
      description: Delete the specified offer sources
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Offer sources deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/archive/:
    put:
      operationId: archiveOfferSources
      summary: Archive offer sources
      tags:
        - Offer Sources
      description: Archive the specified offer sources
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Offer sources archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/unarchive/:
    put:
      operationId: unarchiveOfferSources
      summary: Unarchive offer sources
      tags:
        - Offer Sources
      description: Unarchive the specified offer sources
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Offer sources unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /offersource/move-category/:
    put:
      operationId: moveOfferSourceCategory
      summary: Move offer sources to a category
      tags:
        - Offer Sources
      description: Move the specified offer sources to a category
      parameters:
        - in: body
          name: body
          description: The asset IDs and target category
          required: true
          schema:
            $ref: '#/definitions/MoveCategoryRequest'
      responses:
        '200':
          description: Offer sources moved successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/list/:
    get:
      operationId: listTrafficSources
      summary: List traffic sources
      tags:
        - Traffic Sources
      description: List all traffic sources
      parameters:
        - $ref: '#/parameters/assetStatus'
        - $ref: '#/parameters/optionalIdCategory'
      responses:
        '200':
          description: List of traffic sources
          schema:
            type: array
            items:
              $ref: '#/definitions/TrafficSourceInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/find/byId/:
    get:
      operationId: findTrafficSourceById
      summary: Find traffic source by ID
      tags:
        - Traffic Sources
      description: Retrieve a traffic source by its id
      parameters:
        - name: idTrafficSource
          in: query
          required: true
          type: string
          description: The ID of the traffic source
      responses:
        '200':
          description: The requested traffic source
          schema:
            $ref: '#/definitions/TrafficSource'
        '401':
          description: Not authorized
        '404':
          description: Traffic source not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/find/byIds/:
    get:
      operationId: findTrafficSourcesByIDs
      summary: Find traffic sources by ID list
      tags:
        - Traffic Sources
      description: Retrieve all traffic sources with the specified ids
      parameters:
        - name: idTrafficSources
          in: query
          required: true
          type: string
          description: The list of traffic source IDs to retrieve
      responses:
        '200':
          description: List of traffic sources with the specified ids
          schema:
            type: array
            items:
              $ref: '#/definitions/TrafficSource'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/find/byStatus/:
    get:
      operationId: findTrafficSourcesByStatus
      summary: Find traffic sources by status
      tags:
        - Traffic Sources
      description: |-
        Retrieve all traffic sources with the specified status.
        Returns slim projection (same as list endpoint). Use find/byId for full objects.
      parameters:
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of traffic sources with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/TrafficSourceInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/find/byCategory/:
    get:
      operationId: findTrafficSourcesByCategory
      summary: Find traffic sources by category
      tags:
        - Traffic Sources
      description: Retrieve all traffic sources under the specified category
      parameters:
        - $ref: '#/parameters/idCategory'
      responses:
        '200':
          description: List of traffic sources
          schema:
            type: array
            items:
              $ref: '#/definitions/TrafficSource'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/save/:
    post:
      operationId: createTrafficSource
      summary: Create traffic source
      tags:
        - Traffic Sources
      description: Create a new traffic source
      parameters:
        - in: body
          name: body
          description: The traffic source definition
          required: true
          schema:
            $ref: '#/definitions/TrafficSource'
      responses:
        '200':
          description: Traffic source created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateTrafficSource
      summary: Save traffic source
      tags:
        - Traffic Sources
      description: Update an existing traffic source. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The traffic source definition
          required: true
          schema:
            $ref: '#/definitions/TrafficSource'
      responses:
        '200':
          description: Traffic source updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/duplicate/:
    post:
      operationId: duplicateTrafficSource
      summary: Duplicate traffic source
      tags:
        - Traffic Sources
      description: Create duplicate of existing traffic source.
      parameters:
        - name: idTrafficSource
          in: query
          description: ID of the traffic source to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name and optional category for the new traffic source.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created traffic source
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source traffic source not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/delete/:
    delete:
      operationId: deleteTrafficSource
      summary: Delete traffic source
      tags:
        - Traffic Sources
      description: Delete the specified traffic sources
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Traffic sources deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/archive/:
    put:
      operationId: archiveTrafficSources
      summary: Archive traffic sources
      tags:
        - Traffic Sources
      description: Archive the specified traffic sources
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Traffic sources archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/unarchive/:
    put:
      operationId: unarchiveTrafficSources
      summary: Unarchive traffic sources
      tags:
        - Traffic Sources
      description: Unarchive the specified traffic sources
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Traffic sources unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /trafficsource/move-category/:
    put:
      operationId: moveTrafficSourceCategory
      summary: Move traffic sources to a category
      tags:
        - Traffic Sources
      description: Move the specified traffic sources to a category
      parameters:
        - in: body
          name: body
          description: The asset IDs and target category
          required: true
          schema:
            $ref: '#/definitions/MoveCategoryRequest'
      responses:
        '200':
          description: Traffic sources moved successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/list/:
    get:
      operationId: listPages
      summary: List pages
      tags:
        - Pages
      description: List all pages
      parameters:
        - $ref: '#/parameters/requiredPageType'
        - $ref: '#/parameters/assetStatus'
        - $ref: '#/parameters/optionalIdCategory'
        - $ref: '#/parameters/optionalIdOfferSource'
      responses:
        '200':
          description: List of pages
          schema:
            type: array
            items:
              $ref: '#/definitions/PageInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/find/byId/:
    get:
      operationId: findPageById
      summary: Find a page by ID
      tags:
        - Pages
      description: Retrieve a page by its id
      parameters:
        - name: idPage
          in: query
          required: true
          type: string
          description: ID of the requested page
      responses:
        '200':
          description: The requested page
          schema:
            $ref: '#/definitions/Page'
        '401':
          description: Not authorized
        '404':
          description: Page not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/find/byIds/:
    get:
      operationId: findPagesByIDs
      summary: Find pages by ID list
      tags:
        - Pages
      description: Retrieve all pages with the specified ids
      parameters:
        - name: idPages
          in: query
          required: true
          type: string
          description: List of the page IDs to return
      responses:
        '200':
          description: List of pages
          schema:
            type: array
            items:
              $ref: '#/definitions/Page'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/find/byStatus/:
    get:
      operationId: findPagesByStatus
      summary: Find pages by status
      tags:
        - Pages
      description: |-
        Retrieve all pages of the specified type and status.
        Returns slim projection (same as list endpoint). Use find/byId for full objects.
      parameters:
        - $ref: '#/parameters/assetStatus'
        - $ref: '#/parameters/pageType'
      responses:
        '200':
          description: List of pages of the specified type and status
          schema:
            type: array
            items:
              $ref: '#/definitions/PageInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/find/byCategory/:
    get:
      operationId: findPagesByCategory
      summary: Find pages by category
      tags:
        - Pages
      description: Retrieve all pages of the specified type and under the specified category
      parameters:
        - $ref: '#/parameters/idCategory'
        - $ref: '#/parameters/pageType'
      responses:
        '200':
          description: List of pages
          schema:
            type: array
            items:
              $ref: '#/definitions/Page'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/save/:
    post:
      operationId: createPage
      summary: Create a new page
      tags:
        - Pages
      description: Create a new page
      parameters:
        - in: body
          name: body
          description: The page definition
          required: true
          schema:
            $ref: '#/definitions/Page'
      responses:
        '200':
          description: Page created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updatePage
      summary: Update a page
      tags:
        - Pages
      description: Update an existing page. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The page definition
          required: true
          schema:
            $ref: '#/definitions/Page'
      responses:
        '200':
          description: Page updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/duplicate/:
    post:
      operationId: duplicatePage
      summary: Duplicate a page
      tags:
        - Pages
      description: Create duplicate of existing page.
      parameters:
        - name: idPage
          in: query
          description: ID of the page to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name and optional category for the new page.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created page
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source page not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/delete/:
    delete:
      operationId: deletePage
      summary: Delete a page
      tags:
        - Pages
      description: Delete the specified pages
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Pages deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/archive/:
    put:
      operationId: archivePages
      summary: Archive pages
      tags:
        - Pages
      description: Archive the specified pages
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Pages archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/unarchive/:
    put:
      operationId: unarchivePages
      summary: Unarchive pages
      tags:
        - Pages
      description: Unarchive the specified pages
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Pages unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/move-category/:
    put:
      operationId: movePageCategory
      summary: Move pages to a category
      tags:
        - Pages
      description: Move the specified pages to a category
      parameters:
        - in: body
          name: body
          description: The asset IDs and target category
          required: true
          schema:
            $ref: '#/definitions/MoveCategoryRequest'
      responses:
        '200':
          description: Pages moved successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/list/:
    get:
      operationId: listPageGroups
      summary: List page groups
      tags:
        - Page Groups
      description: List page groups. Use globalOnly=true to return only global groups (not scoped to a specific funnel).
      parameters:
        - $ref: '#/parameters/requiredPageType'
        - $ref: '#/parameters/assetStatus'
        - name: idFunnel
          in: query
          required: false
          allowEmptyValue: true
          type: string
          description: Filter to page groups scoped to this funnel.
        - name: globalOnly
          in: query
          required: false
          type: boolean
          default: false
          description: When true, return only global page groups (those not scoped to a specific funnel).
      responses:
        '200':
          description: List of page groups
          schema:
            type: array
            items:
              $ref: '#/definitions/PageGroupInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/find/byId/:
    get:
      operationId: findPageGroupById
      summary: Find a page group by ID
      tags:
        - Page Groups
      description: Retrieve a page group by its id
      parameters:
        - name: idPageGroup
          in: query
          required: true
          type: string
          description: The ID to return
      responses:
        '200':
          description: The requested page group
          schema:
            $ref: '#/definitions/PageGroup'
        '401':
          description: Not authorized
        '404':
          description: Page not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/find/byIds/:
    get:
      operationId: findPageGroupsByIDs
      summary: Find page groups by ID list
      tags:
        - Page Groups
      description: Retrieve all page groups with the specified ids
      parameters:
        - name: idPageGroups
          in: query
          required: true
          type: string
          description: List of page group IDs to retrieve
      responses:
        '200':
          description: List of page groups with the specified ids
          schema:
            type: array
            items:
              $ref: '#/definitions/PageGroup'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/find/byStatus/:
    get:
      operationId: findPageGroupsByStatus
      summary: Find page groups by status
      tags:
        - Page Groups
      description: Retrieve all page groups of the specified type and status
      parameters:
        - $ref: '#/parameters/assetStatus'
        - $ref: '#/parameters/pageType'
        - name: idFunnel
          in: query
          required: false
          allowEmptyValue: true
          type: string
          description: The  ID of the funnel to filter to
      responses:
        '200':
          description: List of page groups of the specified type and status
          schema:
            type: array
            items:
              $ref: '#/definitions/PageGroupInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/find/byType/:
    get:
      operationId: findPageGroupsByType
      summary: Find page groups by type
      tags:
        - Page Groups
      description: Retrieve page groups of the specified type and status
      parameters:
        - name: pageGroupType
          in: query
          required: true
          type: string
          description: The type of the page group
          enum:
            - lander
            - offer
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of page groups of the specified type
          schema:
            type: array
            items:
              $ref: '#/definitions/PageGroup'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/save/:
    post:
      operationId: createPageGroup
      summary: Create a page group
      tags:
        - Page Groups
      description: Create a new page group
      parameters:
        - in: body
          name: body
          description: The page group definition
          required: true
          schema:
            $ref: '#/definitions/PageGroup'
      responses:
        '200':
          description: Page group created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updatePageGroup
      summary: Update a page group
      tags:
        - Page Groups
      description: Update an existing page group. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The page group definition
          required: true
          schema:
            $ref: '#/definitions/PageGroup'
      responses:
        '200':
          description: Page group updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/duplicate/:
    post:
      operationId: duplicatePageGroup
      summary: Duplicate a page group
      tags:
        - Page Groups
      description: Create duplicate of existing page group.
      parameters:
        - name: idPageGroup
          in: query
          description: ID of the page group to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name for the new page group.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created page group
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source page group not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/delete/:
    delete:
      operationId: deletePageGroup
      summary: Delete a page group
      tags:
        - Page Groups
      description: Delete the specified page groups
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Page groups deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/archive/:
    put:
      operationId: archivePageGroups
      summary: Archive page groups
      tags:
        - Page Groups
      description: Archive the specified page groups
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Page groups archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /page/group/unarchive/:
    put:
      operationId: unarchivePageGroups
      summary: Unarchive page groups
      tags:
        - Page Groups
      description: Unarchive the specified page groups
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Page groups unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/list/:
    get:
      operationId: listCategories
      summary: List categories
      tags:
        - Categories
      description: List persisted category rows by status and categoryType. The blank/no-category value is idCategory="" on assets and is not returned as a category row.
      parameters:
        - $ref: '#/parameters/assetStatus'
        - name: categoryType
          in: query
          required: true
          type: string
          description: Canonical category type filter. Supported values are trafficsources, offersources, lander, offer, condition, visitorTag, and logicscript.
          enum:
            - trafficsources
            - offersources
            - lander
            - offer
            - condition
            - visitorTag
            - logicscript
      responses:
        '200':
          description: List of categories
          schema:
            type: array
            items:
              $ref: '#/definitions/Category'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/find/byId/:
    get:
      operationId: findCategoryById
      summary: Find category by ID
      tags:
        - Categories
      description: Retrieve a category by its id
      parameters:
        - name: idCategory
          in: query
          required: true
          type: string
          description: ID of the category to retrieve
      responses:
        '200':
          description: The requested category
          schema:
            $ref: '#/definitions/Category'
        '401':
          description: Not authorized
        '404':
          description: Category not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/find/byIds/:
    get:
      operationId: findCategoriesByIDs
      summary: Find categories by ID list
      tags:
        - Categories
      description: Retrieve all categories with the specified ids
      parameters:
        - name: idCategories
          in: query
          required: true
          type: string
          description: List of category IDs to retrieve
      responses:
        '200':
          description: List of categories with the specified type and status
          schema:
            type: array
            items:
              $ref: '#/definitions/Category'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/save/:
    post:
      operationId: createCategory
      summary: Create a category
      tags:
        - Categories
      description: Create a new category
      parameters:
        - in: body
          name: body
          description: The category definition
          required: true
          schema:
            $ref: '#/definitions/Category'
      responses:
        '200':
          description: Category created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateCategory
      summary: Update a category
      tags:
        - Categories
      description: Update an existing category. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The category definition
          required: true
          schema:
            $ref: '#/definitions/Category'
      responses:
        '200':
          description: Page category updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/duplicate/:
    post:
      operationId: duplicateCategory
      summary: Duplicate a category
      tags:
        - Categories
      description: Create duplicate of existing category.
      parameters:
        - name: idCategory
          in: query
          description: ID of the category to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name for the new category.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created category
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source category not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/delete/:
    delete:
      operationId: deleteCategory
      summary: Delete a category
      tags:
        - Categories
      description: Delete the specified categories. Child assets are kept and moved to Uncategorized (idCategory="") before the category is soft-deleted.
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Categories deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/archive/:
    put:
      operationId: archiveCategories
      summary: Archive categories
      tags:
        - Categories
      description: Archive the specified categories
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Categories archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /category/unarchive/:
    put:
      operationId: unarchiveCategories
      summary: Unarchive categories
      tags:
        - Categories
      description: Unarchive the specified categories
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Categories unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/list/:
    get:
      operationId: listCampaigns
      summary: List funnel groups
      tags:
        - Funnel Groups
      description: List all campaigns (DEPRECATED - use /funnelgroup/list/ instead)
      deprecated: true
      parameters:
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of campaigns
          schema:
            type: array
            items:
              $ref: '#/definitions/CampaignInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/find/byId/:
    get:
      operationId: findCampaignById
      summary: Find funnel group by ID
      tags:
        - Funnel Groups
      description: Retrieve a campaign by its id (DEPRECATED - use /funnelgroup/find/byId/ instead)
      deprecated: true
      parameters:
        - name: idCampaign
          in: query
          required: true
          type: string
          description: The ID of the funnel group to retrieve
      responses:
        '200':
          description: The requested campaign
          schema:
            $ref: '#/definitions/Campaign'
        '401':
          description: Not authorized
        '404':
          description: Campaign not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/find/byIds/:
    get:
      operationId: findCampaignsByIDs
      summary: Find funnel groups by ID list
      tags:
        - Funnel Groups
      description: Retrieve all campaigns with the specified ids
      parameters:
        - name: idCampaigns
          in: query
          required: true
          type: string
          description: List of the funnel group IDs to retrieve
      responses:
        '200':
          description: List of campaigns with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/Campaign'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/find/byStatus/:
    get:
      operationId: findCampaignsByStatus
      summary: Find funnel groups by status
      tags:
        - Funnel Groups
      description: |-
        Retrieve all funnel groups (campaigns) with the specified status.
        Returns slim projection (same as list endpoint). Use find/byId for full objects.
      parameters:
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of funnel groups with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/CampaignInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/save/:
    post:
      operationId: createCampaign
      summary: Create a funnel group
      tags:
        - Funnel Groups
      description: Create a new campaign
      parameters:
        - in: body
          name: body
          description: The campaign definition
          required: true
          schema:
            $ref: '#/definitions/Campaign'
      responses:
        '200':
          description: Campaign created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateCampaign
      summary: Update a funnel group
      tags:
        - Funnel Groups
      description: Update an existing campaign. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The campaign definition
          required: true
          schema:
            $ref: '#/definitions/Campaign'
      responses:
        '200':
          description: Campaign updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/duplicate/:
    post:
      operationId: duplicateCampaign
      summary: Duplicate a funnel group
      tags:
        - Funnel Groups
      description: Create duplicate of existing campaign.
      parameters:
        - name: idCampaign
          in: query
          description: ID of the campaign to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name for the new campaign.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created campaign
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source campaign not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/delete/:
    delete:
      operationId: deleteCampaign
      summary: Delete a funnel group
      tags:
        - Funnel Groups
      description: Delete the specified campaigns along with all their funnels
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Campaigns deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/list/:
    get:
      operationId: listFunnels
      summary: List funnels
      tags:
        - Funnels
      description: List all funnels
      parameters:
        - $ref: '#/parameters/assetStatus'
        - $ref: '#/parameters/optionalFunnelType'
      responses:
        '200':
          description: List of funnels
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/find/byId:
    get:
      operationId: findFunnelById
      summary: Find funnel by ID
      tags:
        - Funnels
      description: Retrieve a funnel by its id
      parameters:
        - name: idFunnel
          in: query
          required: true
          type: string
          description: The ID of the funnel to retrieve
      responses:
        '200':
          description: The requested funnel
          schema:
            $ref: '#/definitions/Funnel'
        '401':
          description: Not authorized
        '404':
          description: Funnel not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/find/byIds/:
    get:
      operationId: findFunnelsByIDs
      summary: Find funnels by ID list
      tags:
        - Funnels
      description: Retrieve all funnels with the specified ids
      parameters:
        - name: idFunnels
          in: query
          required: true
          type: string
          description: List of the funnel IDs to filter to
      responses:
        '200':
          description: List of funnels with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/Funnel'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/find/byStatus/:
    get:
      operationId: findFunnelsByStatus
      summary: Find funnels by status
      tags:
        - Funnels
      description: Retrieve all funnels with the specified status
      parameters:
        - name: idCampaign
          in: query
          required: false
          type: string
          description: The funnel group to filter to
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of funnels with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/find/byType/:
    get:
      operationId: findFunnelsByType
      summary: Find funnels by type
      tags:
        - Funnels
      description: Retrieve all funnels with the specified type
      parameters:
        - $ref: '#/parameters/funnelType'
      responses:
        '200':
          description: List of funnels with the specified type
          schema:
            type: array
            items:
              $ref: '#/definitions/Funnel'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/find/byCategory/:
    get:
      operationId: findFunnelsByCategory
      summary: Find funnels by category
      tags:
        - Funnels
      description: Retrieve all funnels under the specified category
      parameters:
        - $ref: '#/parameters/idCategory'
      responses:
        '200':
          description: List of funnels in the category
          schema:
            type: array
            items:
              $ref: '#/definitions/Funnel'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/save/:
    post:
      operationId: createFunnel
      summary: Create a funnel
      tags:
        - Funnels
      description: Create a new funnel
      parameters:
        - in: body
          name: body
          description: The funnel definition
          required: true
          schema:
            $ref: '#/definitions/Funnel'
      responses:
        '200':
          description: Funnel created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateFunnel
      summary: Update a funnel
      tags:
        - Funnels
      description: Update an existing funnel. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The funnel definition
          required: true
          schema:
            $ref: '#/definitions/Funnel'
      responses:
        '200':
          description: Funnel updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/duplicate/:
    post:
      operationId: duplicateFunnel
      summary: Duplicate a funnel
      tags:
        - Funnels
      description: Create duplicate of existing funnel.
      parameters:
        - name: idFunnel
          in: query
          description: ID of the funnel to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name and required funnel group for the new funnel.
          required: true
          schema:
            $ref: '#/definitions/FunnelDuplicateRequest'
      responses:
        '200':
          description: The newly created funnel
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source funnel not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/delete/:
    delete:
      operationId: deleteFunnel
      summary: Delete a funnel
      tags:
        - Funnels
      description: Delete the specified funnels along with their nodes and connections
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Funnels deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/archive/:
    put:
      operationId: archiveFunnels
      summary: Archive a funnel
      tags:
        - Funnels
      description: Archive the specified funnels
      parameters:
        - in: body
          name: body
          description: The list of funnel IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Funnels archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/unarchive/:
    put:
      operationId: unarchiveFunnels
      summary: Unarchive a funnel
      tags:
        - Funnels
      description: Unarchive the specified funnels
      parameters:
        - in: body
          name: body
          description: The list of funnel IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Funnels archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /campaign/funnel/move/:
    put:
      operationId: moveFunnels
      summary: Move a funnel
      tags:
        - Funnels
      description: Move the specified funnels under another campaign
      parameters:
        - name: idCampaign
          in: query
          required: true
          type: string
          description: The ID of the funnel group to move to
        - in: body
          name: body
          description: The list of funnel IDs to move
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Funnels moved successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/list/:
    get:
      operationId: listConditions
      summary: List conditions
      tags:
        - Conditions
      description: List all conditions. Use globalOnly=true to return only global conditions (not scoped to a specific funnel). idFunnel takes precedence over globalOnly when both are set.
      parameters:
        - $ref: '#/parameters/assetStatus'
        - name: idFunnel
          in: query
          required: false
          allowEmptyValue: true
          type: string
          description: Filter to conditions scoped to this funnel. Takes precedence over globalOnly.
        - $ref: '#/parameters/optionalIdCategory'
        - name: globalOnly
          in: query
          required: false
          type: boolean
          default: false
          description: When true, return only global conditions (those not scoped to a specific funnel).
      responses:
        '200':
          description: List of conditions
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelConditionInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/find/byId/:
    get:
      operationId: findConditionById
      summary: Find condition by ID
      tags:
        - Conditions
      description: Retrieve a condition by its id
      parameters:
        - name: idCondition
          in: query
          required: true
          type: string
          description: The ID of the condition to query
      responses:
        '200':
          description: The requested condition
          schema:
            $ref: '#/definitions/FunnelCondition'
        '401':
          description: Not authorized
        '404':
          description: Condition not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/find/byIds/:
    get:
      operationId: findConditionsByIDs
      summary: Find conditions by ID list
      tags:
        - Conditions
      description: Retrieve all conditions with the specified ids
      parameters:
        - name: idConditions
          in: query
          required: true
          type: string
          description: List of the condition IDs to retrieve
      responses:
        '200':
          description: The requested conditions
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelCondition'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/find/byStatus/:
    get:
      operationId: findConditionsByStatus
      summary: Find conditions by status
      tags:
        - Conditions
      description: |-
        Retrieve all conditions with the specified status, optionally filtering by parent funnel id.
        Returns slim projection (same as list endpoint). Use find/byId for full objects.
      parameters:
        - $ref: '#/parameters/assetStatus'
        - name: idFunnel
          in: query
          required: false
          allowEmptyValue: true
          type: string
          description: The optional parent funnel ID to filter the query to
      responses:
        '200':
          description: The requested conditions
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelConditionInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/find/byCategory/:
    get:
      operationId: findConditionsByCategory
      summary: Find conditions by category
      tags:
        - Conditions
      description: 'Retrieve all conditions under the specified category, optionally filtering by parent funnel id'
      parameters:
        - $ref: '#/parameters/idCategory'
        - name: idFunnel
          in: query
          required: false
          allowEmptyValue: true
          type: string
          description: The optional ID of the funnel to filter to
      responses:
        '200':
          description: The requested conditions
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelCondition'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/save/:
    post:
      operationId: createCondition
      summary: Create a condition
      tags:
        - Conditions
      description: Create a new condition
      parameters:
        - in: body
          name: body
          description: The condition definition
          required: true
          schema:
            $ref: '#/definitions/FunnelCondition'
      responses:
        '200':
          description: Condition created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateCondition
      summary: Update a condition
      tags:
        - Conditions
      description: Update an existing condition. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The condition definition
          required: true
          schema:
            $ref: '#/definitions/FunnelCondition'
      responses:
        '200':
          description: Condition updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/duplicate/:
    post:
      operationId: duplicateCondition
      summary: Duplicate a condition
      tags:
        - Conditions
      description: Create duplicate of existing condition.
      parameters:
        - name: idCondition
          in: query
          description: ID of the condition to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name for the new condition.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created condition
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source condition not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/delete/:
    delete:
      operationId: deleteCondition
      summary: Delete a condition
      tags:
        - Conditions
      description: Delete the specified conditions
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Conditions deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/archive/:
    put:
      operationId: archiveConditions
      summary: Archive conditions
      tags:
        - Conditions
      description: Archive the specified conditions
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Conditions archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/unarchive/:
    put:
      operationId: unarchiveConditions
      summary: Unarchive conditions
      tags:
        - Conditions
      description: Unarchive the specified conditions
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Conditions unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /condition/move-category/:
    put:
      operationId: moveConditionCategory
      summary: Move conditions to a category
      tags:
        - Conditions
      description: Move the specified conditions to a category
      parameters:
        - in: body
          name: body
          description: The asset IDs and target category
          required: true
          schema:
            $ref: '#/definitions/MoveCategoryRequest'
      responses:
        '200':
          description: Conditions moved successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/find/byId/:
    get:
      operationId: findVisitorTagById
      summary: Find visitor tag by ID
      tags:
        - Visitor Tags
      description: Retrieve a visitor tag by its id. Visitor tags are account-level assets.
      parameters:
        - name: idTag
          in: query
          required: true
          type: string
          description: The ID of the tag to return
      responses:
        '200':
          description: The requested visitor tag
          schema:
            $ref: '#/definitions/FunnelVisitorTag'
        '401':
          description: Not authorized
        '404':
          description: Visitor tag not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/list/:
    get:
      operationId: listVisitorTags
      summary: List visitor tags
      tags:
        - Visitor Tags
      description: Retrieve all non-deleted visitor tags. Visitor tags are account-level assets.
      parameters:
        - name: idCategory
          in: query
          required: false
          type: string
          description: Optional category filter
      responses:
        '200':
          description: List of visitor tags
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelVisitorTag'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/find/byStatus/:
    get:
      operationId: findVisitorTagsByStatus
      summary: Find visitor tags by status
      tags:
        - Visitor Tags
      description: Retrieve all visitor tags with the specified status
      parameters:
        - $ref: '#/parameters/assetStatus'
        - name: idCategory
          in: query
          required: false
          type: string
          description: Optional category filter
      responses:
        '200':
          description: List of visitor tags
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelVisitorTag'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/save/:
    post:
      operationId: createVisitorTag
      summary: Create a visitor tag
      tags:
        - Visitor Tags
      description: Create a new visitor tag
      parameters:
        - in: body
          name: body
          description: The visitor tag definition
          required: true
          schema:
            $ref: '#/definitions/FunnelVisitorTag'
      responses:
        '200':
          description: Visitor tag created successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateVisitorTag
      summary: Update a visitor tag
      tags:
        - Visitor Tags
      description: Update an existing visitor tag. The id cannot be changed.
      parameters:
        - in: body
          name: body
          description: The visitor tag definition
          required: true
          schema:
            $ref: '#/definitions/FunnelVisitorTag'
      responses:
        '200':
          description: Visitor tag updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/duplicate/:
    post:
      operationId: duplicateVisitorTag
      summary: Duplicate a visitor tag
      tags:
        - Visitor Tags
      description: Create a duplicate of an existing visitor tag.
      parameters:
        - name: idTag
          in: query
          description: ID of the visitor tag to duplicate.
          required: true
          type: string
        - name: body
          in: body
          description: Name for the new visitor tag.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: The newly created visitor tag
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Source visitor tag not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/delete/:
    delete:
      operationId: deleteVisitorTag
      summary: Delete visitor tags
      tags:
        - Visitor Tags
      description: Delete the specified visitor tags
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Visitor tags deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/archive/:
    put:
      operationId: archiveVisitorTags
      summary: Archive visitor tags
      tags:
        - Visitor Tags
      description: Archive the specified visitor tags
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Visitor tags archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/unarchive/:
    put:
      operationId: unarchiveVisitorTags
      summary: Unarchive visitor tags
      tags:
        - Visitor Tags
      description: Unarchive the specified visitor tags
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Visitor tags unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /visitortag/move-category/:
    put:
      operationId: moveVisitorTagCategory
      summary: Move visitor tags to category
      tags:
        - Visitor Tags
      description: Move visitor tags to the specified category
      parameters:
        - in: body
          name: body
          required: true
          schema:
            $ref: '#/definitions/MoveCategoryRequest'
      responses:
        '200':
          description: Visitor tags moved successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'

  # ============================================================================
  # FUNNELGROUP ENDPOINTS (V2 aliases for campaign endpoints)
  # Note: These are identical to campaign endpoints but with updated naming
  # Campaign endpoints are maintained for backward compatibility but deprecated
  # ============================================================================
  /funnelgroup/list/:
    get:
      operationId: listFunnelGroups
      summary: List funnel groups
      tags:
        - Funnel Groups
      description: List all funnel groups (campaigns) - V2 endpoint
      parameters:
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of funnel groups
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelGroupInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/find/byId/:
    get:
      operationId: findFunnelGroupById
      summary: Find funnel group by ID
      tags:
        - Funnel Groups
      description: Retrieve a funnel group by its id - V2 endpoint
      parameters:
        - name: idFunnelGroup
          in: query
          required: true
          type: string
          description: The ID of the funnel group to retrieve
      responses:
        '200':
          description: The requested funnel group
          schema:
            $ref: '#/definitions/FunnelGroup'
        '401':
          description: Not authorized
        '404':
          description: Funnel group not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/find/byIds/:
    get:
      operationId: findFunnelGroupsByIDs
      summary: Find funnel groups by ID list
      tags:
        - Funnel Groups
      description: Retrieve all funnel groups with the specified ids - V2 endpoint
      parameters:
        - name: idFunnelGroups
          in: query
          required: true
          type: string
          description: List of the funnel group IDs to retrieve
      responses:
        '200':
          description: List of funnel groups with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/FunnelGroup'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/find/byStatus/:
    get:
      operationId: findFunnelGroupsByStatus
      summary: Find funnel groups by status
      tags:
        - Funnel Groups
      description: |-
        Retrieve all funnel groups with the specified status.
        Returns slim projection (same as list endpoint). Use find/byId for full objects.
        Note: Response uses CampaignInfo field names (idCampaign, campaignName) for backward compatibility.
      parameters:
        - $ref: '#/parameters/assetStatus'
      responses:
        '200':
          description: List of funnel groups with the specified status
          schema:
            type: array
            items:
              $ref: '#/definitions/CampaignInfo'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/save/:
    post:
      operationId: createFunnelGroup
      summary: Create a new funnel group
      tags:
        - Funnel Groups
      description: Create a new funnel group - V2 endpoint
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: '#/definitions/FunnelGroup'
      responses:
        '200':
          description: Funnel group created successfully
          schema:
            $ref: '#/definitions/FunnelGroup'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateFunnelGroup
      summary: Update an existing funnel group
      tags:
        - Funnel Groups
      description: Update an existing funnel group - V2 endpoint
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: '#/definitions/FunnelGroup'
      responses:
        '200':
          description: Funnel group updated successfully
          schema:
            $ref: '#/definitions/FunnelGroup'
        '401':
          description: Not authorized
        '404':
          description: Funnel group not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/duplicate/:
    post:
      operationId: duplicateFunnelGroup
      summary: Duplicate a funnel group
      tags:
        - Funnel Groups
      description: Duplicate an existing funnel group.
      parameters:
        - name: idFunnelGroup
          in: query
          required: true
          type: string
          description: ID of the funnel group to duplicate.
        - name: body
          in: body
          description: Name for the new funnel group.
          required: true
          schema:
            $ref: '#/definitions/DuplicateRequest'
      responses:
        '200':
          description: Funnel group duplicated successfully
          schema:
            $ref: '#/definitions/DuplicateResponse'
        '401':
          description: Not authorized
        '404':
          description: Funnel group not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/delete/:
    delete:
      operationId: deleteFunnelGroup
      summary: Delete a funnel group
      tags:
        - Funnel Groups
      description: Delete a funnel group - V2 endpoint
      parameters:
        - name: idFunnelGroup
          in: query
          required: true
          type: string
          description: The ID of the funnel group to delete
      responses:
        '200':
          description: Funnel group deleted successfully
        '401':
          description: Not authorized
        '404':
          description: Funnel group not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/archive/:
    put:
      operationId: archiveFunnelGroups
      summary: Archive funnel groups
      tags:
        - Funnel Groups
      description: Archive the specified funnel groups
      parameters:
        - in: body
          name: body
          description: The list of IDs to archive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Funnel groups archived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /funnelgroup/unarchive/:
    put:
      operationId: unarchiveFunnelGroups
      summary: Unarchive funnel groups
      tags:
        - Funnel Groups
      description: Unarchive the specified funnel groups
      parameters:
        - in: body
          name: body
          description: The list of IDs to unarchive
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: Funnel groups unarchived successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'

  /user/settings/:
    get:
      operationId: getUserSettings
      summary: Get user settings
      tags:
        - User
      description: Retrieve a user settings of current or specified user
      parameters:
        - name: userId
          in: query
          description: |-
            The user's ID for who need to return settings. Optional, if not passed the user ID from 'key' will be taken.
            Useful if need to request any user settings by id using internal key (edge, reporting)
          required: false
          type: string
          x-nullable: false
      responses:
        '200':
          description: The requested user settings
          schema:
            $ref: '#/definitions/UserSettings'
        '401':
          description: Not authorized
        '404':
          description: User not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: saveUserSettings
      summary: Save user settings
      tags:
        - User
      description: Create or update user settings of current user
      parameters:
        - in: body
          name: body
          description: The user settings definition
          required: true
          schema:
            $ref: '#/definitions/UserSettings'
      responses:
        '200':
          description: User settings created/updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    delete:
      operationId: deleteUserSettings
      summary: Delete user settings
      tags:
        - User
      description: Delete user settings of current user
      responses:
        '200':
          description: User settings deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  #region Integration API keys
  /integration/api-keys/:
    get:
      operationId: listAPIKeys
      summary: List integration API keys
      tags:
        - Integration
      description: List all user's API keys
      responses:
        '200':
          description: List of API keys
          schema:
            type: array
            items:
              $ref: '#/definitions/IntegrationAPIKey'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    post:
      operationId: generateAPIKey
      summary: Generate integration API key
      tags:
        - Integration
      description: Generate new API key for specified integration API
      parameters:
        - in: body
          name: body
          required: true
          description: The body of the query
          schema:
            $ref: '#/definitions/GenerateIntegrationAPIKeyRequest'
      responses:
        '200':
          description: Generated API key data
          schema:
            $ref: '#/definitions/IntegrationAPIKey'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateAPIKey
      summary: Update integration API key
      tags:
        - Integration
      description: Update existing API key data
      parameters:
        - in: body
          name: body
          description: The user settings definition
          required: true
          schema:
            $ref: '#/definitions/UpdateIntegrationAPIKeyRequest'
      responses:
        '200':
          description: API key data updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    delete:
      operationId: deleteAPIKey
      summary: Delete integration API key
      tags:
        - Integration
      description: Delete specified integration API key
      parameters:
        - in: body
          name: body
          required: true
          description: The ID to process
          schema:
            $ref: '#/definitions/DeleteIntegrationAPIKeyRequest'
      responses:
        '200':
          description: API key deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /ainodesetting/save:
    post:
      operationId: createAINodeSetting
      summary: Create AI node settings
      tags:
        - AI Node Settings
      description: Create AI node settings
      parameters:
        - in: body
          name: body
          description: The AI node settings definition
          required: true
          schema:
            $ref: '#/definitions/AINodeSetting'
      responses:
        '200':
          description: AI node settings created/updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
    put:
      operationId: updateAINodeSetting
      summary: Update AI node settings
      tags:
        - AI Node Settings
      description: Update AI node settings
      parameters:
        - in: body
          name: body
          description: The AI node settings definition
          required: true
          schema:
            $ref: '#/definitions/AINodeSetting'
      responses:
        '200':
          description: AI node settings created/updated successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /ainodesetting/find/byId:
    get:
      operationId: findAINodeSettingById
      summary: Find AI node settings by ID
      tags:
        - AI Node Settings
      description: Retrieve AI node settings by its id
      parameters:
        - name: idAINodeSetting
          in: query
          required: true
          type: string
          description: The ID of the AI node settings to retrieve
      responses:
        '200':
          description: The requested AI node settings
          schema:
            $ref: '#/definitions/AINodeSetting'
        '401':
          description: Not authorized
        '404':
          description: AI node settings not found
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /ainodesetting/find/byIds/:
    get:
      summary: Find AI node settings by ID list
      operationId: findAINodeSettingByIds
      tags:
        - AI Node Settings
      description: Retrieve all AI node settings with the specified ids
      parameters:
        - name: idAINodeSettings
          in: query
          required: true
          type: string
          description: List of the AI node setting IDs to retrieve
      responses:
        '200':
          description: List of AI node settings with the specified ids
          schema:
            type: array
            items:
              $ref: '#/definitions/AINodeSetting'
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  /ainodesetting/delete:
    delete:
      operationId: deleteAINodeSetting
      summary: Delete AI node settings
      tags:
        - AI Node Settings
      description: Delete AI node settings
      parameters:
        - in: body
          name: body
          description: The list of IDs to delete
          required: true
          schema:
            $ref: '#/definitions/StringList'
      responses:
        '200':
          description: AI node settings deleted successfully
        '401':
          description: Not authorized
        default:
          description: Unexpected error
          schema:
            $ref: '#/definitions/Error'
  
#endregion
definitions:
  DuplicateRequest:
    type: object
    required:
      - name
    properties:
      name:
        type: string
        minLength: 1
        maxLength: 256
        description: Name for the new asset
      parentId:
        type: string
        description: Optional parent/category ID for the new asset
        x-nullable: true
      bodyUpdates:
        type: object
        description: Optional field overrides to merge into the duplicated asset. Keys are JSON field names (e.g. baseURL, trackingFieldSlots). Protected fields (ID, owner, status) cannot be changed via this field — they are always set by the server after the merge.
        additionalProperties: true
        x-nullable: true
  FunnelDuplicateRequest:
    type: object
    required:
      - name
      - parentId
    properties:
      name:
        type: string
        minLength: 1
        maxLength: 256
        description: Name for the new funnel
      parentId:
        type: string
        minLength: 1
        description: Required funnel group ID for the new funnel.
      bodyUpdates:
        type: object
        description: Optional field overrides to merge into the duplicated funnel. Keys are JSON field names. Protected fields (ID, owner, status, idFunnelGroup) cannot be changed via this field — they are always set by the server after the merge.
        additionalProperties: true
        x-nullable: true
  DuplicateResponse:
    type: object
    properties:
      id:
        type: string
        description: ID of the newly created asset
  OfferSourceCategoryInfo:
    type: object
    required:
      - idCategory
      - categoryName
      - status
    properties:
      idCategory:
        type: string
        description: ID of the category
        x-nullable: false
      categoryName:
        type: string
        minLength: 1
        maxLength: 256
        description: Category's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      offerSources:
        type: array
        items:
          $ref: '#/definitions/OfferSourceInfo'
        x-nullable: false
  OfferSourceInfo:
    type: object
    description: Slim offer source projection returned by list and findByStatus endpoints.
    required:
      - idOfferSource
      - offerSourceName
      - status
    properties:
      idOfferSource:
        type: string
        description: ID of the offer source
        x-nullable: false
      offerSourceName:
        type: string
        minLength: 1
        maxLength: 256
        description: Offer source's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idCategory:
        type: string
        description: ID of the parent category
        x-nullable: false
      categoryName:
        type: string
        maxLength: 256
        description: Name of the parent category
  OfferSource:
    type: object
    required:
      - idOfferSource
      - offerSourceName
    properties:
      idOfferSource:
        type: string
        description: ID of the offer source
        x-nullable: false
      offerSourceName:
        type: string
        minLength: 1
        maxLength: 256
        description: Offer source's name.
        x-nullable: false
      queryParams:
        type: object
        description: Query parameters to add to the url. Tokens can be used as values.
        additionalProperties:
          type: string
      postbackSubId:
        type: string
        description: Name of the subid parameter your offer source sends back to FunnelFlux when a conversion occurs
        default: ''
        x-nullable: false
      postbackTxId:
        type: string
        description: Name of the unique transaction id parameter your offer source sends back to FunnelFlux when a conversion occurs
        default: ''
        x-nullable: false
      postbackPayout:
        type: string
        description: Name of the payout parameter your offer source sends back to FunnelFlux when a conversion occurs
        default: ''
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idCategory:
        type: string
        description: Category ID. Empty if uncategorized
        default: ''
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      idOfferSource: '1'
      offerSourceName: offerSourceName
      postbackSubId: subid
      postbackTxId: txid
      postbackPayout: payout
      queryParams:
        param1: value1
        param2: value2
  TrackingField:
    required:
      - name
      - value
    properties:
      name:
        type: string
        x-nullable: false
      previousName:
        type: string
        default: ''
        x-nullable: false
      value:
        type: string
        default: null
        x-nullable: true
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
  TrafficSourceCategoryInfo:
    type: object
    required:
      - idCategory
      - categoryName
      - status
    properties:
      idCategory:
        type: string
        description: ID of the category
        x-nullable: false
      categoryName:
        type: string
        minLength: 1
        maxLength: 256
        description: Category's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      trafficSources:
        type: array
        items:
          $ref: '#/definitions/TrafficSourceInfo'
        x-nullable: false
  TrafficSourceInfo:
    type: object
    description: Slim traffic source projection returned by list and findByStatus endpoints.
    required:
      - idTrafficSource
      - trafficSourceName
      - status
    properties:
      idTrafficSource:
        type: string
        description: ID of the traffic source
        x-nullable: false
      trafficSourceName:
        type: string
        minLength: 1
        maxLength: 256
        description: Traffic source's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idCategory:
        type: string
        description: ID of the parent category
        x-nullable: false
      categoryName:
        type: string
        maxLength: 256
        description: Name of the parent category
  TrafficSource:
    type: object
    required:
      - costType
      - idTrafficSource
      - trafficSourceName
    properties:
      idTrafficSource:
        type: string
        description: ID of the traffic source
        x-nullable: false
      trafficSourceName:
        type: string
        minLength: 1
        maxLength: 256
        description: Traffic source's name.
        x-nullable: false
      costType:
        type: string
        default: cpe
        enum:
          - cpe
          - cpa
        x-nullable: false
      defaultCost:
        type: string
        default: ''
        x-nullable: false
      trackingFields:
        type: object
        description: DEPRECATED
        additionalProperties:
          type: string
      trackingFieldSlots:
        type: object
        description: 'Allowed keys are campaign, external and c1 to c20 - see example'
        additionalProperties:
          $ref: '#/definitions/TrackingField'
        example:
          campaign:
            name: campaign
            value: null
          external:
            name: external
            value: '{externalid}'
          c1:
            name: source
            value: '{source}'
          c2:
            name: target
            previousName: old_target
            value: '{target}'
          c3:
            name: zone
            value: '{zone}'
      postback:
        $ref: '#/definitions/Postback'
      customEventPostback:
        $ref: '#/definitions/CustomEventPostback'
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idCategory:
        type: string
        description: Category ID. Empty if uncategorized
        default: ''
        x-nullable: false
      customScenarioData:
        type: object
        description: Free form object for storing custom scenario data (deprecated)
        additionalProperties: true
      conversionTrackingSettings:
        type: object
        description: Free form object for storing conversion tracking settings (UI usage only)
        additionalProperties: true
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
      incomingCostModifier:
        type: number
        description: 'Incoming cost modifier in percent. This value is used to adjust the incoming cost of a traffic source. For example, if the incoming cost is $1 and the incoming cost modifier is 50, the incoming cost will be adjusted to $0.5. This number should be between 0 and 500.'
        default: 1
        x-nullable: false
      outgoingRevenueModifier:
        type: number
        description: 'Outgoing revenue modifier in percent. This value is used to adjust the outgoing revenue of a traffic source. For example, if the outgoing revenue is $1 and the outgoing revenue modifier is 50, the outgoing revenue sent in postbacks will be $0.5. This number should be between 0 and 500.'
        default: 1
        x-nullable: false
      outgoingPostbackProbability:
        type: number
        description: 'Outgoing postback probability in percent. This value is used to determine the probability of sending a postback to the traffic source. For example, if the outgoing postback probability is 50, then there is a 50% chance that a postback will be sent to the traffic source. This number should be between 0 and 100.'
        default: 100
        x-nullable: true
      disableZeroRevenuePostbacks:
        type: boolean
        description: 'If true, then zero revenue postbacks will not be sent for this traffic source. This is useful for filtering events of zero revenue which may not be desirable to send to the traffic source.'
        default: false
        x-nullable: false
    example:
      idTrafficSource: '1'
      trafficSourceName: trafficSourceName
      defaultCost: '0'
      postback:
        postbackType: none
        idTrafficSource: idTrafficSource
      customEventPostback:
        idTrafficSource: idTrafficSource
        customEvents:
          '1':
            postbackType: postbackURL
            postbackURL: none
      costType: cpe
      trackingFieldSlots:
        c1:
          name: source
          value: '{source}'
        c2:
          name: target
          value: '{target}'
        c3:
          name: zone
          value: '{zone}'
  StringList:
    type: object
    required:
      - entries
    properties:
      entries:
        type: array
        items:
          type: string
        x-nullable: false
    example:
      entries:
        - entries
        - entries
  MoveCategoryRequest:
    type: object
    required:
      - entries
      - idCategory
    properties:
      entries:
        type: array
        items:
          type: string
        description: List of asset IDs to move
      idCategory:
        type: string
        description: Target category ID (empty string to remove from category)
  Postback:
    type: object
    required:
      - idTrafficSource
      - postbackType
    properties:
      idTrafficSource:
        type: string
        x-nullable: false
      postbackType:
        type: string
        default: none
        enum:
          - none
          - postbackURL
          - html
        x-nullable: false
      postbackCode:
        description: DEPRECATED
        type: string
        default: null
        x-nullable: true
      postbackURL:
        type: string
        default: null
        x-nullable: true
      postbackHTML:
        type: string
        default: null
        x-nullable: true
    example:
      postbackURL: postbackURL
      postbackType: none
      idTrafficSource: idTrafficSource
  CustomEventPostback:
    type: object
    required:
      - idTrafficSource
    properties:
      idTrafficSource:
        type: string
        x-nullable: false
      customEvents:
        type: object
        additionalProperties:
          type: object
          properties:
            postbackType:
              type: string
              enum:
                - none
                - postbackURL
                - html
              x-nullable: false
            postbackURL:
              type: string
              x-nullable: true
            postbackHTML:
              type: string
              x-nullable: true
          required:
            - postbackType
    example:
      idTrafficSource: 0DWYrkQBIJkc
      customEvents:
        '1':
          postbackType: postbackURL
          postbackURL: none
        '2':
          postbackType: postbackURL
          postbackURL: none
  FunnelNodeRotatorParams:
    type: object
    properties:
      rotatorType:
        type: string
        description: How the rotator will operate.
        default: random
        enum:
          - random
          - ai
        x-nullable: false
      stickinessMode:
        type: string
        description: |
          Controls rotation behavior for repeat visitors within their session.
          - none: Always rotate randomly (default behavior)
          - sticky: Always show same destination for returning visitors
          - antiAffinity: Cycle through all destinations before repeating any
        default: none
        enum:
          - none
          - sticky
          - antiAffinity
        x-nullable: false
    example:
      rotatorType: random
      stickinessMode: none
  FunnelNodePageParams:
    type: object
    required:
      - idPage
    properties:
      idPage:
        type: string
        description: ID of the lander or offer page
        x-nullable: false
      accumulateUrlParams:
        type: boolean
        description: 'If true, then the accumulated URL params are forwarded to this node''s url'
        default: false
        x-nullable: false
      additionalTokens:
        type: object
        description: Tokens to compute and then forward to this node's url
        additionalProperties:
          type: string
      redirectOverride:
        $ref: '#/definitions/PageRedirectType'
        description: Allows to override a page's default redirectType
        x-nullable: false
    example:
      idPage: '1'
      accumulateUrlParams: false
      additionalTokens:
        key1: value1
        key2: value2
  FunnelNodeExternalUrlParams:
    type: object
    required:
      - url
    properties:
      url:
        type: string
        description: URL to redirect to
        x-nullable: false
      redirectType:
        type: string
        description: What http code should be used to redirect to the external URL.
        default: '307'
        enum:
          - '301'
          - '307'
        x-nullable: false
    example:
      url: url
      redirectType: '307'
  FunnelNodeConditionParams:
    type: object
    required:
      - idCondition
    properties:
      idCondition:
        type: string
        description: ID of the condition
        x-nullable: false
    example:
      idCondition: '1'
  FunnelNodeVisitorTagParams:
    type: object
    properties:
      addTagIds:
        type: array
        description: Tag IDs to add to the visitor
        items:
          type: string
        x-nullable: false
      removeTagIds:
        type: array
        description: Tag IDs to remove from the visitor
        items:
          type: string
        x-nullable: false
    example:
      addTagIds:
        - tagid1
        - tagid2
      removeTagIds:
        - tagid3
  FunnelNodePageGroupParams:
    type: object
    required:
      - idPageGroup
    properties:
      idPageGroup:
        type: string
        description: ID of the page group
        x-nullable: false
      pageOverrides:
        type: array
        items:
          $ref: '#/definitions/FunnelNodePageParams'
        x-nullable: false
  FunnelNodeLabelParams:
    type: object
    required:
      - labelText
    properties:
      labelColor:
        type: string
        description: A hex code for the label's background color
        default: e5e5e5
        x-nullable: true
      labelText:
        type: string
        description: The text to display on the label
        default: My label here
    example:
      labelColor: e5e5e5
      labelText: My label here
  PageGroupInfo:
    type: object
    description: Slim page group projection returned by list and findByStatus endpoints.
    required:
      - idPageGroup
      - pageGroupName
      - status
      - pageType
      - idCategory
    properties:
      idPageGroup:
        type: string
        x-nullable: false
      pageGroupName:
        type: string
        minLength: 1
        maxLength: 256
        description: Page group's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      pageType:
        type: string
        description: Type of pages in this group (lander or offer)
        enum:
          - lander
          - offer
        x-nullable: false
      idCategory:
        type: string
        description: ID of the category
        x-nullable: false
      categoryName:
        type: string
        maxLength: 256
        description: Name of the parent category
  PageGroup:
    type: object
    required:
      - idPageGroup
      - pageGroupName
      - pageType
      - pages
      - routing
    properties:
      idPageGroup:
        type: string
        x-nullable: false
      pageGroupName:
        type: string
        minLength: 1
        maxLength: 256
        description: Page group's name.
        x-nullable: false
      pageType:
        $ref: '#/definitions/PageType'
        description: What kind of pages in this group.
        x-nullable: false
      routing:
        type: string
        enum:
          - rotator
          - actionMapped
        x-nullable: false
      pages:
        type: array
        description: List of page entries
        items:
          $ref: '#/definitions/PageGroupEntry'
        x-nullable: false
      restrictToFunnelId:
        type: string
        description: |-
          If empty, then page group is global and can be used by multiple funnels, otherwise, page group is local and
          can be used only by the funnel with id specified in this field.
        default: ''
        x-nullable: false
      stickinessMode:
        type: string
        description: |
          Controls rotation behavior for repeat visitors (only applies when routing is "rotator").
          - none: Always rotate randomly (default behavior)
          - sticky: Always show same page for returning visitors
          - antiAffinity: Cycle through all pages before repeating any
        default: none
        enum:
          - none
          - sticky
          - antiAffinity
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      idPageGroup: idPageGroup
      pageGroupName: page group name
      routing: rotator
      pageType: lander
      stickinessMode: none
      pages:
        - idPage: idPage
          weight: 0.08008281904610115
        - idPage: idPage
          weight: 0.08008281904610115
      restrictToFunnelId: funnel-id
      status: active
  PageGroupEntry:
    type: object
    required:
      - idPage
      - weight
    properties:
      idPage:
        type: string
        x-nullable: false
      weight:
        type: number
        format: double
        description: The page's weight from 0.0 to 1.0
        minimum: 0
        maximum: 1
        x-nullable: true
    example:
      idPage: idPage
      weight: 0.08008281904610115
  FunnelNode:
    type: object
    required:
      - idNode
      - nodeName
      - nodeType
    properties:
      idNode:
        type: string
        description: ID of the node
        x-nullable: false
      nodeName:
        type: string
        x-nullable: false
      nodeType:
        type: string
        description: |-
          The type of this node. Depending on the value, different parameters may be required.
          <ul>
            <li>If nodeType is 'root' or 'rotator' then the property 'nodeRotatorParams' is optional</li>
            <li>If nodeType is 'lander' or 'offer' then the property 'nodePageParams' is required</li>
            <li>If nodeType is 'externalUrl' then the property 'nodeExternalUrlParams' is required</li>
            <li>If nodeType is 'condition' then the property 'nodeConditionParams' is required</li>
            <li>If nodeType is 'landerGroup' or 'offerGroup' then the property 'nodePageGroupParams' is required</li>
            <li>If nodeType is 'visitorTag' then the property 'nodeVisitorTagParams' is required</li>
            <li>If nodeType is 'actionProxy' then no additional node parameters are required (routing is defined via connectionActionProxyParams on outgoing connections)</li>
            <li>If nodeType is 'label' then the property 'nodeLabelParams' is required</li>
          </ul>
        enum:
          - root
          - rotator
          - lander
          - offer
          - externalUrl
          - condition
          - visitorTag
          - landerGroup
          - offerGroup
          - actionProxy
          - label
        x-nullable: false
      nodeRotatorParams:
        $ref: '#/definitions/FunnelNodeRotatorParams'
      nodePageParams:
        $ref: '#/definitions/FunnelNodePageParams'
      nodeExternalUrlParams:
        $ref: '#/definitions/FunnelNodeExternalUrlParams'
      nodeConditionParams:
        $ref: '#/definitions/FunnelNodeConditionParams'
      nodeVisitorTagParams:
        $ref: '#/definitions/FunnelNodeVisitorTagParams'
      nodePageGroupParams:
        $ref: '#/definitions/FunnelNodePageGroupParams'
      nodeLabelParams:
        $ref: '#/definitions/FunnelNodeLabelParams'
      posX:
        type: number
        format: double
        description: Node's X position in the funnel canvas.
        default: 0
        x-nullable: false
      posY:
        type: number
        format: double
        description: Node's Y position in the funnel canvas.
        default: 0
        x-nullable: false
      isGlobalNode:
        type: boolean
        description: Whether the node is global or not
        default: false
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
    example:
      nodeName: nodeName
      nodeVisitorTagParams:
        addTagIds:
          - tagid1
        removeTagIds: []
      nodeType: root
      nodePageParams:
        idPage: '1'
        accumulateUrlParams: false
        additionalTokens:
          key1: value1
          key2: value2
      idNode: '1'
      nodeRotatorParams:
        rotatorType: random
      nodeExternalUrlParams:
        url: url
      posX: 2.027123023002322
      posY: 4.145608029883936
      idFunnel: 1
      nodeConditionParams:
        idCondition: '1'
  FunnelConnectionRotatorParams:
    type: object
    required:
      - weight
    properties:
      weight:
        type: number
        format: double
        description: The connection weight from 0.0 to 1.0
        minimum: 0
        maximum: 1
        x-nullable: true
    example:
      weight: 0.68
  FunnelConnectionPageParams:
    type: object
    required:
      - onActionNumbers
    properties:
      onActionNumbers:
        description: The array of 'Action' numbers that will lead the visitor through this connection.
        type: array
        items:
          type: integer
          format: int32
          minimum: 1
          maximum: 255
          x-nullable: false
      isConversion:
        type: boolean
        description: Determines if this action leads to a conversion of the source page node
        default: false
        x-nullable: false
      inlineConversionSpecs:
        type: object
        description: Inline conversion specs for this connection
        properties:
          txOverride:
            type: string
            x-nullable: true
          revenueOverride:
            type: number
            format: float
            x-nullable: true
          eventData1Override:
            type: string
            maxLength: 1024
            description: Custom data field 1 override (max 1024 bytes, no HTML tags)
            x-nullable: true
          eventData2Override:
            type: string
            maxLength: 1024
            description: Custom data field 2 override (max 1024 bytes, no HTML tags)
            x-nullable: true
      isCustomEvent:
        type: boolean
        description: Determines if this action leads to a custom event of the source page node
        default: false
        x-nullable: false
      inlineCustomEventSpecs:
        type: object
        description: Inline custom event specs for this connection
        properties:
          customEventNumber:
            type: number
            format: int32
            x-nullable: false
          revenueOverride:
            type: number
            format: float
            x-nullable: true
          eventData1Override:
            type: string
            maxLength: 1024
            description: Custom data field 1 override (max 1024 bytes, no HTML tags)
            x-nullable: true
          eventData2Override:
            type: string
            maxLength: 1024
            description: Custom data field 2 override (max 1024 bytes, no HTML tags)
            x-nullable: true
    example:
      isConversion: false
      isCustomEvent: true
      inlineCustomEventSpecs:
        customEventNumber: 1
        revenueOverride: 12
      onActionNumbers:
        - 47
  FunnelConnectionCodeParams:
    type: object
    required:
      - onDoneNumber
    properties:
      onDoneNumber:
        type: integer
        format: int32
        description: '''Done'' number that will lead the visitor through this connection.'
        minimum: 1
        maximum: 255
        x-nullable: false
    example:
      onDoneNumber: 8
  FunnelConnectionConditionParams:
    type: object
    minProperties: 1
    properties:
      onRouteId:
        type: string
        minLength: 1
        maxLength: 64
        pattern: '^[a-z0-9_]{1,64}$'
        description: |-
          Stable V2 condition route reference. For V2 conditions, this is the canonical connection key.
          Must match one routes[].idRoute on the referenced condition.
          Use `default` for the default route connection.
          If any route on the referenced condition uses idRoute/priority, every connection from that condition node must use onRouteId.
      onRouteNumber:
        type: integer
        format: int32
        description: |-
          Legacy V1 route reference. Used only for legacy conditions without routes[].idRoute.
          For V2 conditions, use onRouteId; onRouteNumber is not canonical.
          For V2 it may be sent as a numeric priority snapshot for compatibility/debugging, but routing identity is onRouteId.
        minimum: 0
        maximum: 255
        x-nullable: true
    example:
      onRouteId: route_a
  FunnelConnectionActionProxyParams:
    type: object
    required:
      - onActionNumbers
    properties:
      onActionNumbers:
        description: The array of 'Action' numbers that will lead the visitor through this connection.
        type: array
        items:
          type: integer
          format: int32
          minimum: 1
          maximum: 255
          x-nullable: false
    example:
      onActionNumbers:
        - 1
  FunnelConnection:
    type: object
    required:
      - idConnection
      - idSourceNode
      - idTargetNode
    properties:
      idConnection:
        type: string
        description: ID of the funnel
        x-nullable: false
      idSourceNode:
        type: string
        description: |-
          ID of the connection's source node. Depending on the type of the source node, different parameters
          may be required.
          <ul>
            <li>If source's nodeType is 'root' or 'rotator' then the property 'connectionRotatorParams' is required</li>
            <li>If source's nodeType is 'lander', 'offer', 'landerGroup' or 'offerGroup' then the property
              'connectionPageParams' is required</li>
            <li>If source's nodeType is 'condition' then the property 'connectionConditionParams' is required</li>
            <li>If source's nodeType is 'actionProxy' then the property 'connectionActionProxyParams' is required</li>
          </ul>
        x-nullable: false
      idTargetNode:
        type: string
        description: ID of the connection's target node
        x-nullable: false
      connectionRotatorParams:
        $ref: '#/definitions/FunnelConnectionRotatorParams'
      connectionPageParams:
        $ref: '#/definitions/FunnelConnectionPageParams'
      connectionCodeParams:
        $ref: '#/definitions/FunnelConnectionCodeParams'
      connectionConditionParams:
        $ref: '#/definitions/FunnelConnectionConditionParams'
      connectionActionProxyParams:
        $ref: '#/definitions/FunnelConnectionActionProxyParams'
      labelLocation:
        type: number
        format: double
        description: |-
          Connection label's location on the link between the source and target nodes. From 0.0 to 1.0.
          0.0 - positioned on the source node and 1.0 - positioned on the target node.
        default: 0.5
        x-nullable: false
    example:
      idConnection: '1'
      connectionCodeParams:
        onDoneNumber: 8
      connectionPageParams:
        isConversion: false
        onActionNumbers:
          - 47
      idFunnel: '1'
      idSourceNode: '1'
      idTargetNode: '1'
      labelLocation: 4.965
      connectionRotatorParams:
        weight: 0.68
  RuleGenericParams:
    type: object
    required:
      - values
    properties:
      values:
        type: array
        description: Values to test against
        items:
          type: string
        x-nullable: false
    example:
      values:
        - values
        - values
  RuleVisitorTagParams:
    type: object
    required:
      - tagId
    properties:
      tagId:
        type: string
        description: Visitor tag ID to test against the current visitor/session tag set
        x-nullable: false
    example:
      tagId: tag_id_here
  RuleTimeDateParams:
    type: object
    required:
      - day
      - month
      - year
    properties:
      year:
        type: integer
        format: int32
        minimum: 1970
        x-nullable: false
      month:
        type: integer
        format: int32
        minimum: 1
        maximum: 12
        x-nullable: false
      day:
        type: integer
        format: int32
        minimum: 1
        maximum: 31
        x-nullable: false
      utcOffsetMinutes:
        type: integer
        format: int32
        description: UTC offset in minutes for timezone-aware evaluation. If not set, uses visitor timezone.
        x-nullable: true
    description: The date is tested against the visitor's timezone.
    example:
      year: 1970
      month: 2
      day: 18
  RuleTimeOfDayParams:
    type: object
    required:
      - hour
      - minutes
    properties:
      hour:
        type: integer
        format: int32
        minimum: 0
        maximum: 23
        x-nullable: true
      minutes:
        type: integer
        format: int32
        minimum: 0
        maximum: 59
        x-nullable: true
      utcOffsetMinutes:
        type: integer
        format: int32
        description: UTC offset in minutes for timezone-aware evaluation. If not set, uses visitor timezone.
        x-nullable: true
    description: The time is tested against the visitor's timezone
    example:
      hour: 12
      minutes: 13
  RuleTimeDayOfWeekParams:
    type: object
    required:
      - day
    properties:
      day:
        type: string
        enum:
          - sunday
          - monday
          - tuesday
          - wednesday
          - thursday
          - friday
          - saturday
        x-nullable: false
      utcOffsetMinutes:
        type: integer
        format: int32
        description: UTC offset in minutes for timezone-aware evaluation. If not set, uses visitor timezone.
        x-nullable: true
    description: The day is tested against the visitor's timezone
    example:
      day: sunday
  RuleTimeDayOfMonthParams:
    type: object
    required:
      - day
    properties:
      day:
        type: integer
        format: int32
        minimum: 1
        maximum: 31
        x-nullable: false
      utcOffsetMinutes:
        type: integer
        format: int32
        description: UTC offset in minutes for timezone-aware evaluation. If not set, uses visitor timezone.
        x-nullable: true
    description: The day is tested against the visitor's timezone
    example:
      day: 3
  RuleTimeMonthOfYearParams:
    type: object
    required:
      - month
    properties:
      month:
        type: integer
        format: int32
        minimum: 1
        maximum: 12
        x-nullable: false
      utcOffsetMinutes:
        type: integer
        format: int32
        description: UTC offset in minutes for timezone-aware evaluation. If not set, uses visitor timezone.
        x-nullable: true
    description: The month is tested against the visitor's timezone
    example:
      month: 7
  RuleTrackingFieldParams:
    type: object
    required:
      - fieldName
    properties:
      fieldName:
        type: string
        x-nullable: false
      fieldValues:
        type: array
        items:
          type: string
        x-nullable: true
    example:
      fieldName: fieldName
      fieldValues:
        - fieldValues
        - fieldValues
  FunnelConditionRule:
    type: object
    required:
      - attribute
      - test
    properties:
      attribute:
        type: string
        description: |-
          Depending on the selected attribute, some other properties may become required.
          <ul>
            <li>For 'Time: Date', timeDateParams is required</li>
            <li>For 'Time: Time of Day', timeOfDayParams is required</li>
            <li>For 'Time: Day of Week', timeDayOfWeekParams is required</li>
            <li>For 'Time: Day of Month', timeDayOfMonthParams is required</li>
            <li>For 'Time: Month of Year', timeMonthOfYearParams is required</li>
            <li>For 'Tracking Field', trackingFieldParams is required</li>
            <li>For 'visitorTag', visitorTagParams is required. Use test 'is' for present and 'is not' for not present.</li>
            <li>For all other attributes, genericParams is required</li>
          </ul>
          UI labels may present visitorTag + is as 'Visitor Tag: Present' and visitorTag + is not as 'Visitor Tag: Not Present'.
        enum:
          - 'Location: Continent'
          - 'Location: Country'
          - 'Location: City'
          - 'Location: Region'
          - 'Location: Timezone'
          - 'Location: UTC Offset'
          - 'Device: Type'
          - 'Device: Brand'
          - 'Device: Model'
          - 'Device: OS'
          - 'Device: OS Version'
          - 'Device: Browser'
          - 'Device: Main Language'
          - 'Device: Browser Language'
          - 'Device: Browser Version'
          - 'Connection: IP'
          - 'Connection: ISP'
          - 'Connection: Mobile Carrier'
          - 'Connection: User Agent'
          - 'Connection: Referrer'
          - 'Connection: Initial Referrer'
          - 'Connection: Current URL'
          - 'Connection: Connection Type'
          - 'Time: Date'
          - 'Time: Day of Week'
          - 'Time: Day of Month'
          - 'Time: Month of Year'
          - 'Time: Time of Day'
          - Traffic Source
          - Tracking Field
          - Tracking Domain
          - visitorTag
        x-nullable: false
      test:
        type: string
        description: Test operator
        # NOTE: The comparison operators (>, >=, <, <=) cause the swagger code generator
        # to create duplicate constant names. After regenerating, you must manually fix
        # the generated constants in funnel_condition_rule.go to use GT, GTE, LT, LTE suffixes.
        enum:
          - is
          - is not
          - contains
          - does not contain
          - any in
          - not in
          - in range
          - '>'
          - '>='
          - '<'
          - '<='
          - is empty
          - is not empty
        x-nullable: false
      genericParams:
        $ref: '#/definitions/RuleGenericParams'
      timeDateParams:
        $ref: '#/definitions/RuleTimeDateParams'
      timeOfDayParams:
        $ref: '#/definitions/RuleTimeOfDayParams'
      timeDayOfWeekParams:
        $ref: '#/definitions/RuleTimeDayOfWeekParams'
      timeDayOfMonthParams:
        $ref: '#/definitions/RuleTimeDayOfMonthParams'
      timeMonthOfYearParams:
        $ref: '#/definitions/RuleTimeMonthOfYearParams'
      trackingFieldParams:
        $ref: '#/definitions/RuleTrackingFieldParams'
      visitorTagParams:
        $ref: '#/definitions/RuleVisitorTagParams'
    example:
      timeDayOfMonthParams:
        day: 3
      timeDayOfWeekParams:
        day: sunday
      trackingFieldParams:
        fieldName: fieldName
        fieldValues:
          - fieldValues
          - fieldValues
      visitorTagParams:
        tagId: tag_id_here
      test: is
      genericParams:
        values:
          - values
          - values
      timeOfDayParams:
        hour: 12
        minutes: 13
      timeDateParams:
        year: 1970
        month: 2
        day: 18
      timeMonthOfYearParams:
        month: 7
      attribute: 'Location: Continent'
  FunnelConditionGroup:
    type: object
    required:
      - operator
      - rules
    properties:
      operator:
        type: string
        enum:
          - or
          - and
        x-nullable: false
      rules:
        type: array
        items:
          $ref: '#/definitions/FunnelConditionRule'
        x-nullable: false
    example:
      rules:
        - timeDayOfMonthParams:
            day: 3
          timeDayOfWeekParams:
            day: sunday
          trackingFieldParams:
            fieldName: fieldName
            fieldValues:
              - fieldValues
              - fieldValues
          test: is
          genericParams:
            values:
              - values
              - values
          timeOfDayParams:
            hour: 12
            minutes: 13
          timeDateParams:
            year: 1970
            month: 2
            day: 18
          timeMonthOfYearParams:
            month: 7
          attribute: 'Location: Continent'
        - timeDayOfMonthParams:
            day: 3
          timeDayOfWeekParams:
            day: sunday
          trackingFieldParams:
            fieldName: fieldName
            fieldValues:
              - fieldValues
              - fieldValues
          test: is
          genericParams:
            values:
              - values
              - values
          timeOfDayParams:
            hour: 12
            minutes: 13
          timeDateParams:
            year: 1970
            month: 2
            day: 18
          timeMonthOfYearParams:
            month: 7
          attribute: 'Location: Continent'
      operator: or
  FunnelConditionRoute:
    type: object
    required:
      - groups
      - operator
      - routeName
    properties:
      idRoute:
        type: string
        minLength: 1
        maxLength: 64
        pattern: '^[a-z0-9_]{1,64}$'
        description: |-
          Stable condition route identifier for V2 condition routing.
          Required when the condition uses V2 route IDs. Must be unique within the condition.
          Allowed characters: lowercase a-z, 0-9, underscore. Maximum 64 characters.
          The reserved value `default` is required for the default route and cannot be used by any other route.
          When upgrading an active condition to V2, update every referencing condition-node connection to use connectionConditionParams.onRouteId before routing traffic through the updated condition.
      routeName:
        type: string
        description: |-
          Human-readable route name. In V2, `Default Route` is reserved for the default route only.
        x-nullable: false
      operator:
        type: string
        enum:
          - or
          - and
        x-nullable: false
      groups:
        type: array
        items:
          $ref: '#/definitions/FunnelConditionGroup'
      priority:
        type: integer
        format: int32
        minimum: 0
        maximum: 255
        description: |-
          V2 route evaluation order. Required when idRoute is present.
          Lower values are evaluated first. Priority 0 is reserved for the default route.
          Priorities must be unique within the condition.
          Changing priority changes evaluation order only; V2 funnel connection identity is routes[].idRoute plus connectionConditionParams.onRouteId.
          Do not update an active condition to V2 without also updating its funnel connections to onRouteId; V2 conditions with legacy numeric-only connections fail closed at Edge.
  FunnelCondition:
    type: object
    required:
      - conditionName
      - idCondition
      - routes
    properties:
      idCondition:
        type: string
        description: ID of the condition
        x-nullable: false
      conditionName:
        type: string
        minLength: 1
        maxLength: 256
        x-nullable: false
      routes:
        type: array
        items:
          $ref: '#/definitions/FunnelConditionRoute'
      idCategory:
        type: string
        description: Category ID. Empty if uncategorized
        default: ''
        x-nullable: false
      restrictToFunnelId:
        type: string
        description: 'If empty, then can be used in all funnels, otherwise, id of the funnel that can use this condition.'
        default: ''
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      idCondition: idCondition
      conditionName: Some Name
      idCategory: idCategory
      restrictToFunnelId: restrictToFunnelId
      status: active
      routes:
        - operator: or
          routeName: Default Route
          groups: []
        - operator: or
          routeName: Route with Rules
          groups:
            - rules:
                - timeDayOfMonthParams:
                    day: 3
                  timeDayOfWeekParams:
                    day: sunday
                  trackingFieldParams:
                    fieldName: fieldName
                    fieldValues:
                      - fieldValues
                      - fieldValues
                  test: is
                  genericParams:
                    values:
                      - values
                      - values
                  timeOfDayParams:
                    hour: 12
                    minutes: 13
                  timeDateParams:
                    year: 1970
                    month: 2
                    day: 18
                  timeMonthOfYearParams:
                    month: 7
                  attribute: 'Location: Continent'
              operator: or

  FunnelConditionCategoryInfo:
    type: object
    required:
      - idCategory
      - categoryName
      - status
    properties:
      idCategory:
        type: string
        description: ID of the condition's category
        x-nullable: false
      categoryName:
        type: string
        minLength: 1
        maxLength: 256
        description: Category's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      conditions:
        type: array
        items:
          $ref: '#/definitions/FunnelConditionInfo'
        x-nullable: false
  FunnelConditionInfo:
    type: object
    description: Slim condition projection returned by list and findByStatus endpoints.
    required:
      - idCondition
      - conditionName
      - status
    properties:
      idCondition:
        type: string
        description: ID of the condition
        x-nullable: false
      conditionName:
        type: string
        minLength: 1
        maxLength: 256
        description: Condition's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idCategory:
        type: string
        description: ID of the parent category
        x-nullable: false
      categoryName:
        type: string
        maxLength: 256
        description: Name of the parent category
  FunnelVisitorTag:
    type: object
    description: Account-level visitor tag asset
    required:
      - idTag
      - tagName
    properties:
      idTag:
        type: string
        description: ID of the tag
        x-nullable: false
      tagName:
        type: string
        minLength: 1
        maxLength: 256
        description: Tag name
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      color:
        type: string
        description: Display color for the tag
      idCategory:
        type: string
        description: Category ID for organizing tags
      categoryName:
        type: string
        maxLength: 256
        description: Category name for organizing tags
    example:
      idTag: idTag
      tagName: tagName
      color: '#FF5733'
      idCategory: cat-001
      categoryName: Tags
  Funnel:
    type: object
    required:
      - idCampaign
      - idFunnel
      - funnelName
    # TODO: make funnelType property as required after FE will start using it
    properties:
      idFunnel:
        type: string
        description: ID of the funnel
        x-nullable: false
      idCampaign:
        type: string
        description: ID of the parent campaign (legacy alias for idFunnelGroup)
        x-nullable: false
      idFunnelGroup:
        type: string
        description: ID of the parent funnel group
        x-nullable: false
      funnelName:
        type: string
        minLength: 1
        maxLength: 256
        description: Funnel's name.
        x-nullable: false
      funnelType:
        $ref: '#/definitions/FunnelType'
        x-nullable: false
      canvasWidth:
        type: integer
        format: int32
        default: 0
        minimum: 0
        x-nullable: false
      canvasHeight:
        type: integer
        format: int32
        default: 0
        minimum: 0
        x-nullable: false
      accumulatedUrlParams:
        type: object
        description: Query parameters to add to the tracking url for this funnel
        additionalProperties:
          type: string
      incomingCostOverrides:
        type: object
        description: |-
          A list of traffic source cost overrides. The key represents the traffic source id and the value the new cost
          to apply to new visits from that traffic source.
        additionalProperties:
          type: string
      postbackOverrides:
        type: array
        description: A list of traffic source postback overrides for this funnel.
        items:
          $ref: '#/definitions/Postback'
      ipAnonymizer:
        type: string
        description: 'IP Anonymizer Type. If not set, use option from user settings'
        enum:
          - disabled
          - All IPs
          - EU IPs
        x-nullable: true
      nodes:
        type: array
        description: A list of nodes used in this funnel
        items:
          $ref: '#/definitions/FunnelNode'
      connections:
        type: array
        description: A list of connections linking this funnel's nodes.
        items:
          $ref: '#/definitions/FunnelConnection'
      defaultCost:
        type: string
        default: ''
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      owner:
        type: string
        description: |-
          Only filled by loading endpoints. Ignored for all saving operations as the owner is already passed as
          the endpoint's key query param.
        default: ''
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      funnelName: funnelName
      idFunnel: '1'
      nodes:
        - nodeName: nodeName
          nodeVisitorTagParams:
            addTagIds:
              - tagid1
              - tagid2
            removeTagIds:
              - tagid3
          nodeType: root
          nodePageParams:
            idPage: '1'
            accumulateUrlParams: false
            additionalTokens:
              key1: value1
              key2: value2
          idNode: '1'
          nodeRotatorParams:
            rotatorType: random
          nodeExternalUrlParams:
            url: url
          posX: 2.027
          posY: 4.145
          idFunnel: 1
          nodeConditionParams:
            idCondition: '1'
      idCampaign: '1'
      defaultCost: '{bid}'
      incomingCostOverrides:
        key1: value1
        key2: value2
      postbackOverrides:
        - postbackURL: url
          postbackType: postbackURL
          idTrafficSource: idTrafficSource
        - postbackHTML: html code
          postbackType: html
          idTrafficSource: idTrafficSource
      connections:
        - idConnection: '1'
          connectionCodeParams:
            onDoneNumber: 8
          connectionPageParams:
            isConversion: false
            onActionNumbers:
              - 47
          idFunnel: 1
          idSourceNode: '1'
          idTargetNode: '1'
          labelLocation: 4.965
          connectionRotatorParams:
            weight: 0.684
        - idConnection: '1'
          connectionCodeParams:
            onDoneNumber: 8
          connectionPageParams:
            isConversion: false
            onActionNumbers:
              - 47
          idFunnel: '1'
          idSourceNode: '1'
          idTargetNode: '1'
          labelLocation: 4.965
          connectionRotatorParams:
            weight: 0.684
  CampaignInfo:
    type: object
    required:
      - idCampaign
      - campaignName
      - status
    properties:
      idCampaign:
        type: string
        description: ID of the campaign
        x-nullable: false
      campaignName:
        type: string
        minLength: 1
        maxLength: 256
        description: Campaign's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      funnels:
        type: array
        items:
          $ref: '#/definitions/FunnelInfo'
        x-nullable: false
  FunnelInfo:
    type: object
    description: Slim funnel projection returned by list and findByStatus endpoints.
    required:
      - idFunnel
      - funnelName
      - status
      - idFunnelGroup
    properties:
      idFunnel:
        type: string
        description: ID of the funnel
        x-nullable: false
      funnelName:
        type: string
        minLength: 1
        maxLength: 256
        description: Funnel's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idFunnelGroup:
        type: string
        description: ID of the parent funnel group
        x-nullable: false
      funnelGroupName:
        type: string
        maxLength: 256
        description: Name of the parent funnel group
  Campaign:
    type: object
    required:
      - campaignName
      - idCampaign
    properties:
      idCampaign:
        type: string
        description: ID of the campaign
        x-nullable: false
      campaignName:
        type: string
        minLength: 1
        maxLength: 256
        description: Campaign's name.
        x-nullable: false
      accumulatedUrlParams:
        type: object
        description: |-
          Query parameters to add to the tracking url for all the funnels of this campaign, unless a specific
          funnel overwrites them
        additionalProperties:
          type: string
      defaultCost:
        type: string
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      idCampaign: '1'
      campaignName: campaignName

  # ============================================================================
  # FUNNELGROUP MODEL DEFINITIONS (V2 aliases for campaign models)
  # Note: These are identical to campaign models but with updated naming
  # Campaign models are maintained for backward compatibility but deprecated
  # ============================================================================
  FunnelGroupInfo:
    type: object
    required:
      - idFunnelGroup
      - funnelGroupName
      - status
    properties:
      idFunnelGroup:
        type: string
        description: ID of the funnel group
        x-nullable: false
      funnelGroupName:
        type: string
        minLength: 1
        maxLength: 256
        description: Funnel group's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      funnels:
        type: array
        items:
          $ref: '#/definitions/FunnelInfo'
        x-nullable: false
  FunnelGroup:
    type: object
    required:
      - funnelGroupName
      - idFunnelGroup
    properties:
      idFunnelGroup:
        type: string
        description: ID of the funnel group
        x-nullable: false
      funnelGroupName:
        type: string
        minLength: 1
        maxLength: 256
        description: Funnel group's name.
        x-nullable: false
      accumulatedUrlParams:
        type: object
        description: |-
          Query parameters to add to the tracking url for all the funnels of this funnel group, unless a specific
          funnel overwrites them
        additionalProperties:
          type: string
      defaultCost:
        type: string
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      idFunnelGroup: '1'
      funnelGroupName: funnelGroupName

  OfferParams:
    type: object
    properties:
      idOfferSource:
        type: string
        description: ID of the offer's source.
        x-nullable: false
      payout:
        $ref: '#/definitions/Decimal'
        description: Default payout amount
      externalProductIds:
        type: object
        properties:
          clickfunnels:
            type: string
          shopify:
            type: string
        x-nullable: false
    example:
      idOfferSource: '1'
      payout: '1.465'
      externalProductIds:
        clickfunnels: '718e618'
        shopify: ahjqu-zmsj
  Category:
    type: object
    required:
      - categoryName
      - categoryType
      - idCategory
    properties:
      idCategory:
        type: string
        description: ID of category. Use an empty string on assets to mean no category; empty string is not a persisted category row.
        x-nullable: false
      categoryName:
        type: string
        minLength: 1
        maxLength: 256
        description: Category name
        x-nullable: false
      categoryType:
        type: string
        description: Category type
        enum:
          - trafficsources
          - offersources
          - lander
          - offer
          - condition
          - visitorTag
          - logicscript
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
    example:
      idCategory: '1'
      categoryName: someName
      categoryType: offer
  PageCategoryInfo:
    type: object
    required:
      - idCategory
      - categoryName
      - status
    properties:
      idCategory:
        type: string
        description: ID of the category
        x-nullable: false
      categoryName:
        type: string
        minLength: 1
        maxLength: 256
        description: Category's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      pages:
        type: array
        items:
          $ref: '#/definitions/PageInfo'
        x-nullable: false
  PageInfo:
    type: object
    description: Slim page projection returned by list and findByStatus endpoints.
    required:
      - idPage
      - pageName
      - status
      - idCategory
      - pageType
      - idOfferSource
    properties:
      idPage:
        type: string
        description: ID of the page
        x-nullable: false
      pageName:
        type: string
        minLength: 1
        maxLength: 256
        description: Page's name.
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      idCategory:
        type: string
        description: ID of the category
        x-nullable: false
      categoryName:
        type: string
        maxLength: 256
        description: Name of the parent category
      pageType:
        type: string
        description: Type of page (lander or offer)
        enum:
          - lander
          - offer
        x-nullable: false
      idOfferSource:
        type: string
        description: ID of the offer source for offer pages
        x-nullable: false
      offerSourceName:
        type: string
        maxLength: 256
        description: Name of the offer source for offer pages
  Page:
    type: object
    required:
      - baseURL
      - idPage
      - pageName
      - pageType
      - redirectType
    properties:
      idPage:
        type: string
        description: ID of the page
        x-nullable: false
      pageType:
        $ref: '#/definitions/PageType'
        description: What kind of page. If 'offer' then 'offerParams' is required
        x-nullable: false
      pageName:
        type: string
        minLength: 1
        maxLength: 256
        description: Page's name.
        x-nullable: false
      baseURL:
        type: string
        description: Redirects to this URL when page is displayed
        x-nullable: false
      queryParams:
        type: object
        description: Query parameters to add to the base url. Tokens can be used as values.
        additionalProperties:
          type: string
      redirectType:
        $ref: '#/definitions/PageRedirectType'
        description: |-
          How to redirect to the page's URL.
          'umr' means 'Ultimate Meta Refresh'.
          By default, it uses the redirect type mentioned in the system settings for landers and offers.
        x-nullable: false
      idCategory:
        type: string
        description: Category ID. Empty if uncategorized
        default: ''
        x-nullable: false
      notes:
        type: string
        description: Optional notes for this page
        default: ''
        x-nullable: false
      offerParams:
        $ref: '#/definitions/OfferParams'
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      meta:
        type: object
        description: Free form object to store any custom data
        additionalProperties: true
      disableAppendVid:
        type: boolean
        description: Whether the page can be append visitor id or not.
    example:
      pageType: lander
      notes: notes
      idPage: '1'
      baseURL: 'https://some-url.com'
      redirectType: '301'
      pageName: pageName
      disableAppendVid: true
      url: url
      idCategory: category-id
      offerParams:
        idOfferSource: '1'
        payout: '1.456'
  UserSettings:
    type: object
    required:
      - defaultCustomDomain
      - defaultHomepageURL
      - defaultLanderRedirect
      - defaultOfferRedirect
      - ipAnonymizer
    properties:
      defaultHomepageURL:
        type: string
        description: 'URL of default homepage, keep empty for 404 response'
        default: null
        x-nullable: true
      defaultOfferRedirect:
        $ref: '#/definitions/PageRedirectType'
        description: Default redirect type for offers. See more about types in Page.redirectType description
        x-nullable: false
      defaultLanderRedirect:
        $ref: '#/definitions/PageRedirectType'
        description: Default redirect type for landers. See more about types in Page.redirectType description
        x-nullable: false
      ipAnonymizer:
        type: string
        description: IP Anonymizer name
        enum:
          - disabled
          - All IPs
          - EU IPs
        x-nullable: false
      defaultCustomDomain:
        type: string
        description: Default custom domain name from 'customDomains' collection
        x-nullable: true
      thirdPartyKeys:
        $ref: '#/definitions/ThirdPartyKeys'
        description: Keys from third parties
      savedViews:
        type: array
        items:
          type: string
      customEventAliases:
        type: object
        description: Custom event number to alias mappings for reporting
        additionalProperties: false
        properties:
          '1':
            $ref: '#/definitions/CustomEventAliasInfo'
          '2':
            $ref: '#/definitions/CustomEventAliasInfo'
          '3':
            $ref: '#/definitions/CustomEventAliasInfo'
          '4':
            $ref: '#/definitions/CustomEventAliasInfo'
          '5':
            $ref: '#/definitions/CustomEventAliasInfo'
          '6':
            $ref: '#/definitions/CustomEventAliasInfo'
          '7':
            $ref: '#/definitions/CustomEventAliasInfo'
          '8':
            $ref: '#/definitions/CustomEventAliasInfo'
          '9':
            $ref: '#/definitions/CustomEventAliasInfo'
          '10':
            $ref: '#/definitions/CustomEventAliasInfo'
    example:
      defaultHomepageURL: 'https://example.com/'
      defaultOfferRedirect: '301'
      defaultLanderRedirect: '307'
      ipAnonymizer: EU IPs
      defaultCustomDomain: domain1.com
      customEventAliases:
        '1':
          alias: Lead
          shortAlias: Lead
        '2':
          alias: Complete Registration
          shortAlias: Reg
  CustomEventAliasInfo:
    type: object
    description: Alias information for a custom event number
    required:
      - alias
      - shortAlias
    properties:
      alias:
        type: string
        description: Alias for the custom event
      shortAlias:
        type: string
        description: Short alias for the custom event
  ThirdPartyKeys:
    type: object
    properties:
      clickbankIPN:
        type: string
        x-nullable: false
  IntegrationAPI:
    type: string
    description: All possible APIs that can be used by the user
    enum:
      - OPTIMIZER
    x-nullable: false
  IntegrationAPIKeyStatus:
    type: string
    enum:
      - ACTIVE
      - DISABLED
    x-nullable: false
  IntegrationAPIKey:
    type: object
    required:
      - key
      - api
      - name
      - status
    properties:
      key:
        type: string
        description: Generated API key
        x-nullable: false
      api:
        $ref: '#/definitions/IntegrationAPI'
        description: API that can be used with given key
      name:
        type: string
        minLength: 1
        maxLength: 256
        description: API key name
        x-nullable: false
      status:
        $ref: '#/definitions/IntegrationAPIKeyStatus'
  GenerateIntegrationAPIKeyRequest:
    type: object
    required:
      - api
      - name
    properties:
      api:
        $ref: '#/definitions/IntegrationAPI'
        description: API that can be used with given key
      name:
        type: string
        minLength: 1
        maxLength: 256
        description: API key name
        x-nullable: false
  UpdateIntegrationAPIKeyRequest:
    type: object
    required:
      - key
      - name
      - status
    properties:
      key:
        type: string
        description: API key to update
        x-nullable: false
      name:
        type: string
        minLength: 1
        maxLength: 256
        description: API key name
        x-nullable: false
      status:
        $ref: '#/definitions/IntegrationAPIKeyStatus'
  DeleteIntegrationAPIKeyRequest:
    type: object
    required:
      - key
    properties:
      key:
        type: string
        description: API key to delete
        x-nullable: false
  Error:
    type: object
    required:
      - code
      - message
    properties:
      code:
        type: integer
        format: int32
        x-nullable: false
      message:
        type: string
        x-nullable: false
      field:
        type: string
        description: An optional field that may contains name of field that caused the error
        x-nullable: false
  Decimal:
    type: string
    x-go-type:
      type: Decimal
      import:
        package: github.com/funnelflux/flux-saas-runtime/core/util/decimal
  Status:
    type: string
    enum:
      - active
      - archived
      - deleted
    default: active
    x-nullable: false
  FunnelType:
    type: string
    enum:
      - visual
      - flow
    default: visual
    x-nullable: false
  PageType:
    type: string
    enum:
      - lander
      - offer
    x-nullable: false
  PageRedirectType:
    type: string
    enum:
      - '301'
      - '307'
      - meta
      - umr
    x-nullable: false
  AINodeSetting:
    type: object
    required:
      - funnelId
      - segmentBy
      - routingGoal
      - lookbackWindow
      - updateFrequency
    properties:
      idAINodeSetting:
        type: string
        description: ID of the AI Node Setting
        x-nullable: false
      aiNodeSettingName:
        type: string
        minLength: 1
        maxLength: 256
        description: AI Node Setting's name.
        x-nullable: false
      idCategory:
        type: string
        description: Category ID. Empty if uncategorized
        default: ''
        x-nullable: false
      status:
        $ref: '#/definitions/Status'
        x-nullable: false
      funnelId:
        type: string
        description: ID of the funnel
        x-nullable: false
      segmentBy:
        type: string
        description: Segment by
        x-nullable: false
        enum:
          - 'default'
          - 'trafficSource'
      eventType:
        type: string
        description: Event Type
        x-nullable: false
        enum:
          - 'conversions'
          - 'customEvent1'
          - 'customEvent2'
          - 'customEvent3'
          - 'customEvent4'
          - 'customEvent5'
          - 'customEvent6'
          - 'customEvent7'
          - 'customEvent8'
          - 'customEvent9'
          - 'customEvent10' 
      routingGoal:
        type: string
        description: Routing goal
        x-nullable: false
        enum:
          - 'bestNextNode'
          - 'bestNextPage'
          - 'bestNextNodeToPage'
      model:
        type: string
        description: AI Model 
        x-nullable: false 
        enum:
          - 'conversionRate'
          - 'revenuePerView'
      lookbackWindow:
        type: integer
        description: Lookback window in hours
        format: int32
        x-nullable: false
      updateFrequency:
        type: integer
        description: Update frequency in hours
        format: int32
        x-nullable: false
      calculationParams:
        $ref: '#/definitions/AINodeSettingCalculationParams'
        description: Calculation parameters
        x-nullable: true
    example:
      nodeId: '1'
      funnelId: '1'
      segmentBy: default
      routingGoal: bestNextNode
      eventType: conversions
      model: conversionRate
      lookbackWindow: 24
      updateFrequency: 24
      calculationParams:
        minimumPercentagePerVariant: 0.1
  AINodeSettingCalculationParams:
      type: object
      properties:
        sensitivityFactor:
          type: number
          format: double
          description: Controls how much to flatten probability distributions (0.0-10.0+, default 3.0)
          x-nullable: true
        minimumPercentagePerVariant:
          type: number
          format: double
          description: Minimum percentage (0-30) each variant should get
          x-nullable: true
        capVariantPercentage:
          type: number
          format: double
          description: Maximum percentage (50-100) any variant can have
          x-nullable: true
