openapi: 3.0.3
info:
  title: Qonversion REST API v4
  version: '4.0'
  description: Qonversion REST API v4 follows REST standards. It has predictable resource-oriented URLs,
    accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response
    codes, authentication, and verbs.
security:
- secretAuth: []
servers:
- url: https://api.qonversion.io/v4
  description: Production
paths:
  /products:
    get:
      operationId: v4ListProducts
      summary: List products
      description: 'Returns a paginated list of products for the authenticated project.

        Products are ordered by creation date (newest first).

        Manifest-compliant: list envelope, string enums, ISO 8601 timestamps.

        '
      tags:
      - Products
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        description: Maximum number of products to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: 'Cursor for pagination. Pass the `id` of the last product from the previous page
          to fetch the next page.

          '
        required: false
        schema:
          type: string
      - name: filter[type]
        in: query
        description: 'Filter products by type. Can be repeated for multiple values (OR logic).

          '
        required: false
        schema:
          type: string
          x-extensible-enum:
          - subscription_with_promo
          - subscription
          - consumable
          - lifetime
      responses:
        '200':
          description: A paginated list of products.
          headers:
            x-request-id:
              description: Unique request identifier for tracing.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ProductList'
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/products
                    data:
                    - object: product
                      id: premium_monthly
                      url: /v4/products/premium_monthly
                      type: subscription
                      duration: P1M
                      apple_product_id: com.example.monthly
                      google_product_id: com.example.monthly
                      google_base_plan_id: monthly-base
                      stripe_product_id: prod_abc123
                      created_at: '2025-09-15T12:30:00Z'
                      updated_at: '2025-11-03T10:26:40Z'
                    has_more: false
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/products
                    data: []
                    has_more: false
        '400':
          description: Invalid request parameters.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
              example:
                error:
                  type: request
                  code: invalid_request
                  message: Parameter 'limit' must be an integer between 1 and 100
        '401':
          description: Missing or invalid authentication token.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateProduct
      summary: Create a product
      description: Creates a new product for the authenticated project.
      tags:
      - Products
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ProductCreate'
      responses:
        '201':
          description: Created product
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the created product.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Product'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: Product already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /products/{product_id}:
    get:
      operationId: v4GetProduct
      summary: Get a product
      description: Returns a single product by ID.
      tags:
      - Products
      security:
      - secretAuth: []
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 255
        description: Product identifier.
        example: premium_monthly
      responses:
        '200':
          description: Product details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Product'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    patch:
      operationId: v4PatchProduct
      summary: Update a product (partial)
      tags:
      - Products
      security:
      - secretAuth: []
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 255
        description: Product identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ProductPatch'
      responses:
        '200':
          description: Updated product
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Product'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteProduct
      summary: Delete a product
      description: Deletes a product by ID. Returns 204 on success. Returns 404 if the product does not
        exist.
      tags:
      - Products
      security:
      - secretAuth: []
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 255
        description: Product identifier.
        example: premium_monthly
      responses:
        '204':
          description: Product deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Product not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /users:
    post:
      operationId: v4CreateUser
      summary: Create a user
      description: |
        Create a new Qonversion user. The server generates the `QON_…` user id
        and returns it in the response body and the `Location` header.

        v3's `POST /v3/users/{id}` accepted a client-supplied id; v4
        standardises on server-issued ids across every resource.

        Pass an `Idempotency-Key` header to make retries safe — the same key
        returns the originally-created user instead of creating a duplicate.
      tags:
      - Users
      security:
      - secretAuth: []
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        schema:
          type: string
        description: Client-generated key that makes retries safe.
        example: 7f4c2e3a-1e5a-4d63-a2cb-0ddc2a2dc4fa
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4UserCreate'
            example:
              environment: prod
      responses:
        '201':
          description: User created
          headers:
            Location:
              description: Canonical URL of the newly-created user.
              schema:
                type: string
                example: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4User'
              example:
                object: user
                id: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
                url: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
                environment: prod
                identity_id: null
                created_at: '2026-04-20T12:00:00Z'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /users/{user_id}:
    get:
      operationId: v4GetUser
      summary: Get a user
      description: Returns a single user by ID.
      tags:
      - Users
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        schema:
          type: string
        description: Qonversion User ID. SDK-generated IDs are prefixed with `QON_`.
        example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      responses:
        '200':
          description: User details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4User'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /customers:
    get:
      operationId: v4ListCustomers
      summary: List customers
      description: 'Returns a paginated list of customers for the authenticated project.

        Manifest-compliant: list envelope, ISO 8601 timestamps.

        '
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: page
        in: query
        description: Page number (1-based).
        required: false
        schema:
          type: integer
          minimum: 1
      - name: limit
        in: query
        description: Maximum number of customers to return.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: sort_by
        in: query
        description: Field to sort results by.
        required: false
        schema:
          type: string
          x-extensible-enum:
          - created_at
          - revenue
          - total_revenue
      - name: sort_order
        in: query
        description: Sort direction.
        required: false
        schema:
          type: string
          enum:
          - asc
          - desc
      - name: environment
        in: query
        description: "Filter by environment: `0` = sandbox, `1` = production."
        required: false
        schema:
          type: integer
          enum:
          - 0
          - 1
      - name: search
        in: query
        description: Search query string.
        required: false
        schema:
          type: string
      - name: filter[status][]
        in: query
        description: 'Filter by customer status. Repeatable: filter[status][]=active&filter[status][]=churned.'
        required: false
        schema:
          type: array
          items:
            type: string
      - name: filter[target_platform][]
        in: query
        description: Filter by target platform. Repeatable.
        required: false
        schema:
          type: array
          items:
            type: string
      responses:
        '200':
          description: A paginated list of customers.
          headers:
            x-request-id:
              description: Unique request identifier for tracing.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4CustomerList'
              example:
                object: list
                url: /v4/customers
                data:
                  - client_id: cl_01HXYZABCDEFGHJKMNPQRSTVWX
                    environment: 2
                    platform: iOS
                    status: active
                    country: US
                    since: '2026-03-18T09:42:11Z'
                    last_seen: '2026-04-22T18:05:33Z'
                    net_payments_usd: 59.97
                    payments_count: 3
                has_more: true
                next_cursor: cl_01HXYZABCDEFGHJKMNPQRSTVWX
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /customers/metrics:
    get:
      operationId: v4GetCustomersMetrics
      summary: Get aggregated customer metrics
      description: Returns aggregated metrics for customers of the authenticated project.
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: environment
        in: query
        description: "Filter by environment: `0` = sandbox, `1` = production."
        required: false
        schema:
          type: integer
          enum:
          - 0
          - 1
      - name: search
        in: query
        description: Search query string.
        required: false
        schema:
          type: string
      - name: filter[status][]
        in: query
        description: Filter by customer status. Repeatable.
        required: false
        schema:
          type: array
          items:
            type: string
      - name: filter[target_platform][]
        in: query
        description: Filter by target platform. Repeatable.
        required: false
        schema:
          type: array
          items:
            type: string
      responses:
        '200':
          description: Customer metrics data.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Aggregated customer metrics wrapped in the v4 envelope (object, url).
                  Scalar counters reflect the current filter set (environment, status, platform, search).
              example:
                object: customer_metrics
                url: /v4/customers/metrics
                active_subscribers: '1284'
                active_trials: '312'
                avg_payment_count: 2.4
                avg_price: 14.99
                billing_retry: '18'
                canceled_trials: 57
                churned_subscribers: 94
                clients_with_event: '9420'
                sales: 4612
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /customers/{customer_id}:
    get:
      operationId: v4GetCustomer
      summary: Get a customer
      description: Returns a single customer by ID.
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: customer_id
        in: path
        required: true
        schema:
          type: string
        description: Customer identifier.
        example: customer_abc123
      responses:
        '200':
          description: Customer details.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Customer object wrapped in the v4 envelope (object, url, data). The
                  `data` block bundles the customer record with attribution, user properties,
                  device info, and recent track events.
              example:
                object: customer
                url: /v4/customers/customer_abc123
                data:
                  customer:
                    client_id: customer_abc123
                    external_identity: user@example.com
                    environment: 2
                    platform: iOS
                    country: US
                    status: active
                    since: '2026-03-18T09:42:11Z'
                    last_seen: '2026-04-22T18:05:33Z'
                  device:
                    platform: iOS
                    os_version: '17.4'
                    device_model: iPhone15,3
                    app_version: 4.12.0
                    sdk_version: 5.9.1
                  attributionData:
                    - key: source
                      value: organic
                    - key: campaign
                      value: spring_sale
                  userProperties:
                    - key: plan_tier
                      value: premium
                    - key: onboarding_variant
                      value: B
                  trackEvents:
                    - event: subscription_started
                      at: '2026-03-18T09:42:45Z'
                      product_id: com.example.pro.monthly
                      revenue_usd: 9.99
                  netPayments: 59.97
                  currency: USD
                  conversionRate: 1.0
                  canRemoveCustomer: true
                  canEditEntitlements: true
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Customer not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteCustomer
      summary: Delete a customer (GDPR)
      description: 'Permanently deletes a customer and all associated personal data.

        This operation is irreversible and intended for GDPR right-to-erasure requests.

        Returns 204 on success.

        '
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: customer_id
        in: path
        required: true
        schema:
          type: string
        description: Customer identifier.
        example: customer_abc123
      responses:
        '204':
          description: Customer deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Customer not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /customers/{customer_id}/properties:
    post:
      operationId: v4SetCustomerProperties
      summary: Set customer properties
      description: 'Sets one or more custom properties on a customer.

        Accepts up to 100 key/value pairs per request.

        Keys must be 1–256 characters; values must be at most 1024 characters.

        '
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: customer_id
        in: path
        required: true
        schema:
          type: string
        description: Customer identifier.
        example: customer_abc123
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4CustomerPropertiesRequest'
      responses:
        '200':
          description: Properties set successfully. Returns updated customer data.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Property-save result wrapped in the v4 envelope (object, url, data).
                  `data.saved_properties` lists the (key, value) pairs that were accepted;
                  `data.property_errors` lists any rejected pairs with the reason — both are
                  always present, empty arrays on success.
              example:
                object: customer_properties
                url: /v4/customers/customer_abc123/properties
                data:
                  saved_properties:
                    - key: plan_tier
                      value: premium
                    - key: referral_source
                      value: email_campaign
                  property_errors: []
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Customer not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /customers/{customer_id}/permissions:
    get:
      operationId: v4ListCustomerPermissions
      summary: List customer permissions
      description: Returns a list of all active permissions for the specified customer.
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: customer_id
        in: path
        required: true
        schema:
          type: string
        description: Customer identifier.
        example: customer_abc123
      responses:
        '200':
          description: A list of permissions.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4PermissionList'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Customer not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4GrantCustomerPermission
      summary: Grant a permission to a customer
      description: 'Grants a permission to the specified customer.

        Returns 201 with a Location header pointing to the new permission resource.

        If `expires_at` is provided it must be a valid RFC 3339 / ISO 8601 timestamp.

        '
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: customer_id
        in: path
        required: true
        schema:
          type: string
        description: Customer identifier.
        example: customer_abc123
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4CustomerPermissionRequest'
      responses:
        '201':
          description: Permission granted.
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the created permission resource.
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Created permission resource. The `permission_id` and `expires_at`
                  fields echo the request body alongside the standard `object` and `url`
                  envelope keys.
                required:
                - object
                - url
                - permission_id
                - expires_at
                properties:
                  object:
                    type: string
                    enum:
                    - customer_permission
                  url:
                    type: string
                    example: /v4/customers/customer_abc123/permissions/premium_access
                  permission_id:
                    type: string
                    example: premium_access
                  expires_at:
                    type: string
                    format: date-time
                    nullable: true
                    example: '2026-01-01T00:00:00Z'
              example:
                object: customer_permission
                url: /v4/customers/customer_abc123/permissions/premium_access
                permission_id: premium_access
                expires_at: '2026-01-01T00:00:00Z'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Customer not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /customers/{customer_id}/permissions/{permission_id}:
    delete:
      operationId: v4RevokeCustomerPermission
      summary: Revoke a customer permission
      description: 'Revokes a specific permission from a customer.

        Returns 204 on success. Returns 404 if the customer or permission does not exist.

        '
      tags:
      - Customers
      security:
      - secretAuth: []
      parameters:
      - name: customer_id
        in: path
        required: true
        schema:
          type: string
        description: Customer identifier.
        example: customer_abc123
      - name: permission_id
        in: path
        required: true
        schema:
          type: string
        description: Permission identifier.
        example: premium_access
      responses:
        '204':
          description: Permission revoked
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Customer or permission not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /entitlements:
    get:
      operationId: v4ListEntitlements
      summary: List entitlement definitions
      description: 'Returns a paginated list of entitlement definitions for the authenticated project.

        Entitlements are ordered by creation date (newest first).

        '
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        description: Maximum number of entitlements to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: 'Cursor for pagination. Pass the `id` of the last entitlement from the previous page
          to fetch the next page.

          '
        required: false
        schema:
          type: string
      responses:
        '200':
          description: A paginated list of entitlement definitions.
          headers:
            x-request-id:
              description: Unique request identifier for tracing.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4EntitlementDefinitionList'
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/entitlements
                    data:
                    - object: entitlement
                      id: premium
                      url: /v4/entitlements/premium
                      description: Premium access entitlement
                      product_ids:
                      - premium_monthly
                      - premium_annual
                      created_at: '2025-09-15T12:30:00Z'
                      updated_at: '2025-11-03T10:26:40Z'
                    has_more: false
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/entitlements
                    data: []
                    has_more: false
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateEntitlement
      summary: Create an entitlement definition
      description: Creates a new entitlement definition for the authenticated project.
      tags:
      - Entitlements
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4EntitlementDefinitionCreate'
      responses:
        '201':
          description: Created entitlement definition.
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the created entitlement.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4EntitlementDefinition'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: Entitlement already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /entitlements/{entitlement_id}:
    get:
      operationId: v4GetEntitlement
      summary: Get an entitlement definition
      description: Returns a single entitlement definition by ID.
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: entitlement_id
        in: path
        required: true
        schema:
          type: string
        description: Entitlement identifier.
        example: premium
      responses:
        '200':
          description: Entitlement definition details.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4EntitlementDefinition'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Entitlement not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    patch:
      operationId: v4PatchEntitlement
      summary: Update an entitlement definition (partial)
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: entitlement_id
        in: path
        required: true
        schema:
          type: string
        description: Entitlement identifier.
        example: premium
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4EntitlementDefinitionPatch'
      responses:
        '200':
          description: Updated entitlement definition.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4EntitlementDefinition'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Entitlement not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteEntitlement
      summary: Delete an entitlement definition
      description: Deletes an entitlement definition by ID. Returns 204 on success. Returns 404 if not
        found.
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: entitlement_id
        in: path
        required: true
        schema:
          type: string
        description: Entitlement identifier.
        example: premium
      responses:
        '204':
          description: Entitlement deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Entitlement not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /users/{user_id}/entitlements:
    get:
      operationId: v4ListUserEntitlements
      summary: List user entitlements
      description: 'Returns all entitlements currently granted to the specified user.
        The response is wrapped in the standard list envelope, but pagination is not
        supported on this endpoint — `has_more` is always `false` and the full set
        is returned in a single call.'
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        schema:
          type: string
        description: User identifier.
        example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      responses:
        '200':
          description: A list of user entitlements.
          headers:
            x-request-id:
              description: Unique request identifier for tracing.
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4UserEntitlementList'
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4GrantUserEntitlement
      summary: Grant an entitlement to a user
      description: 'Grants an entitlement definition to a specific user, optionally
        with an expiry time. Attempting to extend or modify a user entitlement whose
        source is a paid purchase (store or Stripe) returns `422 paid_entitlement`.'
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        schema:
          type: string
        description: User identifier.
        example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4GrantEntitlementRequest'
      responses:
        '201':
          description: Entitlement granted.
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the granted user entitlement.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4UserEntitlement'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User or entitlement not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: Entitlement already granted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /users/{user_id}/entitlements/{entitlement_id}:
    delete:
      operationId: v4RevokeUserEntitlement
      summary: Revoke a user entitlement
      description: 'Revokes a previously granted entitlement from a user. Only entitlements
        whose source is `manual` can be revoked. Returns 204 on success, 404 if the
        entitlement is not active for the user, and `422 paid_entitlement` when the
        entitlement came from a paid purchase (store or Stripe).'
      tags:
      - Entitlements
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        schema:
          type: string
        description: User identifier.
        example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      - name: entitlement_id
        in: path
        required: true
        schema:
          type: string
        description: Entitlement identifier.
        example: premium
      responses:
        '204':
          description: Entitlement revoked
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User or entitlement not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: 'Paid entitlement — cannot revoke an entitlement that came
            from a store or Stripe purchase.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /offerings:
    get:
      operationId: v4ListOfferings
      summary: List offerings
      deprecated: true
      description: Legacy — Offerings are superseded by Remote Configs; use Remote Configs for new integrations. Returns regular offerings only. Experiment-variant offerings (owned by the experiments service) are excluded.
      tags: [Offerings]
      security: [{secretAuth: []}]
      parameters:
        - {name: limit, in: query, required: false, schema: {type: integer, minimum: 1, maximum: 100, default: 20}}
        - {name: starting_after, in: query, required: false, schema: {type: string, maxLength: 64, pattern: '^[a-zA-Z0-9._:\- ]+$'}, description: 'Cursor for pagination. Pass the `id` of the last offering from the previous page. If the referenced offering no longer exists the server restarts pagination from the first row and emits an `X-Qon-Pagination-Restarted: true` response header.'}
      responses:
        '200':
          description: A paginated list of offerings.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4OfferingList'}
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/offerings
                    data:
                      - object: offering
                        id: premium_monthly
                        url: /v4/offerings/premium_monthly
                        tag: 1
                        product_ids: [premium_monthly_799, premium_annual_4999]
                        created_at: '2025-09-15T12:30:00Z'
                        updated_at: '2025-11-03T10:26:40Z'
                      - object: offering
                        id: winback
                        url: /v4/offerings/winback
                        tag: 0
                        product_ids: [premium_annual_2999]
                        created_at: '2025-10-02T09:15:00Z'
                        updated_at: '2025-10-02T09:15:00Z'
                    has_more: false
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/offerings
                    data: []
                    has_more: false
        '400':
          description: Invalid request parameters.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Error'}
              example:
                error:
                  type: request
                  code: invalid_data
                  message: Failed validate request data
                _meta:
                  fields:
                    - name: limit
                      messages:
                        - must be an integer between 1 and 100
        '401': {description: Missing or invalid authentication token., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
    post:
      operationId: v4CreateOffering
      summary: Create an offering
      deprecated: true
      description: Legacy — Offerings are superseded by Remote Configs; create Remote Configs for new integrations instead. Creates a new offering for the authenticated project. If the project has no offerings yet, the new one is auto-promoted to main (`tag` will be `1` in the response even if it was omitted in the request). Prefer `POST /v4/offerings/{offering_id}/set-main` over passing `tag=1` here when switching the main of an existing project.
      tags: [Offerings]
      security: [{secretAuth: []}]
      parameters:
        - {name: Idempotency-Key, in: header, required: false, schema: {type: string}}
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: '#/components/schemas/V4OfferingCreate'}
            example:
              id: premium_monthly
              product_ids: [premium_monthly_799, premium_annual_4999]
      responses:
        '201':
          description: Offering created.
          headers: {Location: {description: Canonical URL., schema: {type: string}}}
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Offering'}
              example:
                object: offering
                id: premium_monthly
                url: /v4/offerings/premium_monthly
                tag: 1
                product_ids: [premium_monthly_799, premium_annual_4999]
                created_at: '2025-11-03T10:26:40Z'
                updated_at: '2025-11-03T10:26:40Z'
        '400':
          description: |
            Invalid request body. Typed codes include `invalid_data` (schema
            validation failed), `invalid_product_id` (a `product_ids` entry is
            empty/too long/contains disallowed characters), `product_not_in_project`
            (a `product_ids` entry is not registered in the project), and
            `cannot_set_main_directly` (`tag: 1` was supplied — promote via
            `POST /offerings/{id}/set-main` instead).
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Error'}
              example:
                error:
                  type: request
                  code: invalid_data
                  message: Failed validate request data
        '401': {description: Missing or invalid authentication token., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '409':
          description: An offering with this `id` already exists.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Error'}
              example:
                error:
                  type: resource
                  code: already_exists
                  message: Offering with these parameters already exists
        '415': {description: Unsupported Content-Type., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '422': {description: Operation cannot be performed in the current state., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
  /offerings/{offering_id}:
    parameters:
      - {name: offering_id, in: path, required: true, schema: {type: string, maxLength: 64, pattern: '^[a-zA-Z0-9._:\- ]+$'}, example: premium_monthly}
    get:
      operationId: v4GetOffering
      summary: Get an offering
      deprecated: true
      description: Legacy — Offerings are superseded by Remote Configs; use Remote Configs for new integrations. Returns a single offering by ID.
      tags: [Offerings]
      security: [{secretAuth: []}]
      responses:
        '200':
          description: Offering details.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Offering'}
              example:
                object: offering
                id: premium_monthly
                url: /v4/offerings/premium_monthly
                tag: 1
                product_ids: [premium_monthly_799, premium_annual_4999]
                created_at: '2025-09-15T12:30:00Z'
                updated_at: '2025-11-03T10:26:40Z'
        '400': {description: Invalid offering id., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Missing or invalid authentication token., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404':
          description: Offering not found in this project.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Error'}
              example:
                error:
                  type: resource
                  code: not_found
                  message: Offering not found
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
    patch:
      operationId: v4PatchOffering
      summary: Update an offering
      deprecated: true
      description: Legacy — Offerings are superseded by Remote Configs; use Remote Configs for new integrations. Partial update. Only supplied fields are changed. `product_ids` replaces the full list in the given order — pass `[]` to detach all products, omit the field to leave the list unchanged.
      tags: [Offerings]
      security: [{secretAuth: []}]
      requestBody:
        required: true
        content:
          application/json:
            schema: {$ref: '#/components/schemas/V4OfferingPatch'}
            example:
              product_ids: [premium_monthly_799]
      responses:
        '200':
          description: Offering updated.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Offering'}
              example:
                object: offering
                id: premium_monthly
                url: /v4/offerings/premium_monthly
                tag: 1
                product_ids: [premium_monthly_799]
                created_at: '2025-09-15T12:30:00Z'
                updated_at: '2025-11-14T08:42:11Z'
        '400': {description: Invalid request body., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Missing or invalid authentication token., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Offering not found in this project., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '409':
          description: An offering with this `id` already exists.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Error'}
              example:
                error:
                  type: resource
                  code: already_exists
                  message: Offering with these parameters already exists
        '415': {description: Unsupported Content-Type., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '422':
          description: |
            Operation cannot be performed in the current state. Typed codes:
            `cannot_patch_experiment_variant` (offering is owned by the
            experiments service), `cannot_demote_main` (attempted to demote
            the project's current main offering — use `set-main` on a
            different offering instead).
          content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
    delete:
      operationId: v4DeleteOffering
      summary: Delete an offering
      deprecated: true
      description: Legacy — Offerings are superseded by Remote Configs; use Remote Configs for new integrations. Removes the offering and its product attachments. Experiment-variant offerings (owned by the experiments service) cannot be deleted via this API and return `422`.
      tags: [Offerings]
      security: [{secretAuth: []}]
      responses:
        '204': {description: Offering deleted.}
        '400': {description: Invalid offering id., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Missing or invalid authentication token., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Offering not found in this project., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '422': {description: 'Offering cannot be deleted. Typed code: `cannot_delete_experiment_variant` — the offering is owned by the experiments service.', content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
  /offerings/{offering_id}/set-main:
    parameters:
      - {name: offering_id, in: path, required: true, schema: {type: string, maxLength: 64, pattern: '^[a-zA-Z0-9._:\- ]+$'}, example: premium_monthly}
    post:
      operationId: v4SetMainOffering
      summary: Set main offering
      deprecated: true
      description: |
        Legacy — Offerings are superseded by Remote Configs; use Remote Configs for new integrations.

        Atomically marks the offering as the project's main offering
        (`tag = 1`) and clears the previous main (`tag = 0`), inside a single
        transaction. No request body required — the action target is fully
        identified by the path parameter. Pass an `Idempotency-Key` header to
        make retries safe (the same key replays the original response).
        Experiment-variant offerings return `422` (typed code
        `cannot_setmain_experiment_variant`).
      tags: [Offerings]
      security: [{secretAuth: []}]
      parameters:
        - {name: Idempotency-Key, in: header, required: false, schema: {type: string}}
      responses:
        '200':
          description: Offering marked as main.
          content:
            application/json:
              schema: {$ref: '#/components/schemas/V4Offering'}
              example:
                object: offering
                id: winback
                url: /v4/offerings/winback
                tag: 1
                product_ids: [premium_annual_2999]
                created_at: '2025-10-02T09:15:00Z'
                updated_at: '2025-11-14T08:45:00Z'
        '400': {description: Invalid offering id., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Missing or invalid authentication token., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Offering not found in this project., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '409': {description: Transactional conflict during set-main., content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '422': {description: 'Operation cannot be performed in the current state. Typed code: `cannot_setmain_experiment_variant` — the offering is owned by the experiments service.', content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
  /remote-configurations:
    get:
      operationId: v4ListRemoteConfigurations
      summary: List remote configurations
      description: 'Returns a paginated list of remote configurations for the authenticated project.

        Configurations are ordered by creation date (newest first). List items do not include
        the inline `payload` values — read a single configuration or the payload endpoint to
        fetch them.

        '
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        description: Maximum number of configurations to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: 'Cursor for pagination. Pass the `id` of the last configuration from the previous
          page to fetch the next page.

          '
        required: false
        schema:
          type: string
      responses:
        '200':
          description: A paginated list of remote configurations.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfigurationList'
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/remote-configurations
                    data:
                    - object: remote_configuration
                      id: 82a42dc2-76f6-46c2-b883-846acaf2070a
                      url: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a
                      name: Onboarding copy
                      status: active
                      context_key: onboarding_copy_v1
                      segment_percent: 100
                      segmentation_conditions: []
                      priority: 1
                      started_at: '2025-11-03T10:26:40Z'
                      finished_at: null
                      last_applied_at: null
                      created_at: '2025-09-15T12:30:00Z'
                      updated_at: '2025-11-03T10:26:40Z'
                    has_more: false
                    next_cursor: null
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/remote-configurations
                    data: []
                    has_more: false
                    next_cursor: null
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateRemoteConfiguration
      summary: Create a remote configuration
      description: Creates a new remote configuration. New configurations start in `draft` status.
        Returns 201 with the created configuration and a Location header.
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        schema:
          type: string
        description: Idempotency key for safe retries.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4RemoteConfigurationCreate'
      responses:
        '201':
          description: Remote configuration created
          headers:
            Location:
              description: URL of the created remote configuration
              schema:
                type: string
                example: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfiguration'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /remote-configurations/{config_id}:
    get:
      operationId: v4GetRemoteConfiguration
      summary: Get a remote configuration
      description: Returns a single remote configuration by ID, including its read-only inline
        `payload` values (`{}` when unset).
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
        example: 82a42dc2-76f6-46c2-b883-846acaf2070a
      responses:
        '200':
          description: Remote configuration details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfigurationDetail'
              example:
                object: remote_configuration
                id: 82a42dc2-76f6-46c2-b883-846acaf2070a
                url: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a
                name: Onboarding copy
                status: active
                context_key: onboarding_copy_v1
                segment_percent: 100
                segmentation_conditions: []
                priority: 1
                started_at: '2025-11-03T10:26:40Z'
                finished_at: null
                last_applied_at: null
                payload:
                  button_color: '#FF0000'
                  max_items: 5
                created_at: '2025-09-15T12:30:00Z'
                updated_at: '2025-11-03T10:26:40Z'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    put:
      operationId: v4UpdateRemoteConfiguration
      summary: Update a remote configuration (full replace)
      description: Replaces the configuration's editable fields. `name` is required; omitted optional
        fields are reset. Use the status and payload endpoints to change status or payload values.
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4RemoteConfigurationUpdate'
      responses:
        '200':
          description: Updated remote configuration
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfiguration'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteRemoteConfiguration
      summary: Delete a remote configuration
      description: Deletes a remote configuration by ID. Returns 204 on success.
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      responses:
        '204':
          description: Remote configuration deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Cannot delete an active configuration; archive it first via PATCH /remote-configurations/{config_id}/status.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /remote-configurations/{config_id}/status:
    patch:
      operationId: v4ChangeRemoteConfigurationStatus
      summary: Change remote configuration status
      description: 'Changes the status of a remote configuration. Allowed transitions:
        `draft` → `active`, `draft` → `archived`, `active` → `archived`. Archiving is terminal —
        an archived configuration can only be deleted. Only `active` configurations are served
        to the SDK.'
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4RemoteConfigurationStatusRequest'
      responses:
        '200':
          description: Updated remote configuration with new status.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfiguration'
        '400':
          description: Invalid request or status transition
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /remote-configurations/{config_id}/payload-mapping:
    get:
      operationId: v4GetRemoteConfigurationPayloadMapping
      summary: Get the payload mapping
      description: 'Returns the payload **mapping** — the key → type schema that tells the SDK how to
        interpret each payload key. This is the schema, not the values: see the payload endpoint for
        the JSON values delivered to the SDK.'
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      responses:
        '200':
          description: Payload mapping
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfigurationPayloadMapping'
              example:
                object: payload_mapping
                url: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a/payload-mapping
                config_id: 82a42dc2-76f6-46c2-b883-846acaf2070a
                data:
                  button_color: Color
                  max_items: Number
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4SetRemoteConfigurationPayloadMapping
      summary: Set the payload mapping
      description: 'Replaces the payload **mapping** (key → type schema). Full replace: the supplied
        `data` object becomes the complete mapping. Allowed types: `String`, `Number`, `Bool`, `Json`,
        `Color`, `Products`, `Screens`.'
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4RemoteConfigurationPayloadMappingRequest'
      responses:
        '200':
          description: Updated payload mapping
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfigurationPayloadMapping'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /remote-configurations/{config_id}/payload:
    get:
      operationId: v4GetRemoteConfigurationPayload
      summary: Get the payload values
      description: 'Returns the payload **values** — the actual JSON object delivered to the SDK for
        this configuration (`{}` when unset). This is distinct from the payload mapping, which
        describes the key → type schema.'
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      responses:
        '200':
          description: Payload values
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfigurationPayload'
              example:
                object: remote_config_payload
                url: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a/payload
                config_id: 82a42dc2-76f6-46c2-b883-846acaf2070a
                data:
                  button_color: '#FF0000'
                  max_items: 5
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    put:
      operationId: v4UpdateRemoteConfigurationPayload
      summary: Replace the payload values
      description: 'Replaces the payload **values** delivered to the SDK. Full replace: the supplied
        `data` object entirely overwrites the stored payload — to change one key, read the current
        payload, modify it, and send the whole object back. An empty object `{}` clears the payload.
        Requests are limited to 64 KiB.'
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4RemoteConfigurationPayloadRequest'
      responses:
        '200':
          description: Updated payload values
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RemoteConfigurationPayload'
        '400':
          description: 'Invalid request — e.g. `data` is not a JSON object, or the payload exceeds the 64 KiB limit.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /remote-configurations/{config_id}/users/{user_id}:
    post:
      operationId: v4AttachUserToRemoteConfiguration
      summary: Attach a user to a remote configuration
      description: Pins a specific user to this configuration, overriding segment and percentage
        targeting rules. The pin is never re-evaluated and survives config edits
        until removed; it also invalidates the SDK's in-memory config cache.
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      - name: user_id
        in: path
        required: true
        schema:
          type: string
        description: User identifier.
      responses:
        '204':
          description: User attached to remote configuration
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration or user not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: User already attached to this configuration
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DetachUserFromRemoteConfiguration
      summary: Detach a user from a remote configuration
      description: Removes a user's manual pin to this configuration, invalidates
        the SDK's in-memory config cache, and makes the user eligible for automatic
        targeting evaluation on the next request.
      tags:
      - Remote Configurations
      security:
      - secretAuth: []
      parameters:
      - name: config_id
        in: path
        required: true
        schema:
          type: string
        description: Remote configuration identifier.
      - name: user_id
        in: path
        required: true
        schema:
          type: string
        description: User identifier.
      responses:
        '204':
          description: User detached from remote configuration
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Remote configuration or user not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /segments:
    get:
      operationId: v4ListSegments
      summary: List segments
      description: 'Returns a paginated list of segments for the authenticated project.

        Segments are ordered by creation date (newest first).

        '
      tags:
      - Segments
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        description: Maximum number of segments to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: 'Cursor for pagination. Pass the `id` of the last segment from the previous page
          to fetch the next page.

          '
        required: false
        schema:
          type: string
      responses:
        '200':
          description: A paginated list of segments.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4SegmentList'
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/segments
                    data:
                    - object: segment
                      id: premium-users
                      url: /v4/segments/premium-users
                      name: Premium Users
                      is_system: false
                      conditions: []
                      created_at: '2025-09-15T12:30:00Z'
                      updated_at: '2025-11-03T10:26:40Z'
                    has_more: false
                    next_cursor: null
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/segments
                    data: []
                    has_more: false
                    next_cursor: null
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateSegment
      summary: Create a segment
      description: Creates a new segment. Returns 201 with the created segment and Location header.
      tags:
      - Segments
      security:
      - secretAuth: []
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        schema:
          type: string
        description: Idempotency key for safe retries.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4SegmentCreate'
      responses:
        '201':
          description: Segment created
          headers:
            Location:
              description: URL of the created segment
              schema:
                type: string
                example: /v4/segments/premium-users
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Segment'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: Segment already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /segments/system:
    get:
      operationId: v4ListSystemSegments
      summary: List system segments
      description: 'Returns all predefined system segments. System segments are read-only

        and cannot be modified or deleted.

        '
      tags:
      - Segments
      security:
      - secretAuth: []
      responses:
        '200':
          description: List of system segments.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4SegmentList'
              example:
                object: list
                url: /v4/segments/system
                data:
                - object: segment
                  id: q-all-users
                  url: /v4/segments/q-all-users
                  name: All users
                  is_system: true
                  conditions: []
                  created_at: '2025-09-15T12:30:00Z'
                  updated_at: '2025-11-03T10:26:40Z'
                - object: segment
                  id: q-active-subscribers
                  url: /v4/segments/q-active-subscribers
                  name: Active subscribers
                  is_system: true
                  conditions: []
                  created_at: '2025-09-15T12:30:00Z'
                  updated_at: '2025-11-03T10:26:40Z'
                has_more: false
                next_cursor: null
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /segments/{segment_id}:
    get:
      operationId: v4GetSegment
      summary: Get a segment
      description: Returns a single segment by ID.
      tags:
      - Segments
      security:
      - secretAuth: []
      parameters:
      - name: segment_id
        in: path
        required: true
        schema:
          type: string
        description: Segment identifier.
        example: premium-users
      responses:
        '200':
          description: Segment details
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Segment'
              example:
                object: segment
                id: premium-users
                url: /v4/segments/premium-users
                name: Premium Users
                is_system: false
                conditions:
                - metric: environment
                  comparator: eq
                  value: prod
                  negate: false
                - metric: renewable
                  comparator: eq
                  value: '1'
                  negate: false
                created_at: '2025-09-15T12:30:00Z'
                updated_at: '2025-11-03T10:26:40Z'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Segment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    put:
      operationId: v4UpdateSegment
      summary: Update a segment (full replace)
      description: Replaces all fields of a segment. All fields are required.
      tags:
      - Segments
      security:
      - secretAuth: []
      parameters:
      - name: segment_id
        in: path
        required: true
        schema:
          type: string
        description: Segment identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4SegmentUpdate'
      responses:
        '200':
          description: Updated segment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Segment'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Segment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteSegment
      summary: Delete a segment
      description: Deletes a segment by ID. Returns 204 on success. System segments cannot be deleted
        (422).
      tags:
      - Segments
      security:
      - secretAuth: []
      parameters:
      - name: segment_id
        in: path
        required: true
        schema:
          type: string
        description: Segment identifier.
      responses:
        '204':
          description: Segment deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Segment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Cannot delete system segment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments:
    get:
      operationId: v4ListExperiments
      summary: List experiments
      description: Returns all experiments for the authenticated project.
      tags:
      - Experiments
      security:
      - secretAuth: []
      responses:
        '200':
          description: A list of experiments.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                required:
                - object
                - url
                - data
                - has_more
                properties:
                  object:
                    type: string
                    enum:
                    - list
                  url:
                    type: string
                    example: /v4/experiments
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/V4Experiment'
                  has_more:
                    type: boolean
                    example: false
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateExperiment
      summary: Create an experiment
      description: Creates a new experiment. Returns 201 with the created experiment and Location header.
      tags:
      - Experiments
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ExperimentCreateRequest'
      responses:
        '201':
          description: Experiment created.
          headers:
            Location:
              description: URL of the created experiment.
              schema:
                type: string
                example: /v4/experiments/my-experiment
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Experiment'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments/summary:
    get:
      operationId: v4GetExperimentsSummary
      summary: Get experiments analytics summary
      description: Returns aggregated analytics summary for experiments.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: from
        in: query
        description: Start of the time range (ISO 8601).
        required: false
        schema:
          type: string
      - name: to
        in: query
        description: End of the time range (ISO 8601).
        required: false
        schema:
          type: string
      - name: environment
        in: query
        description: Filter by environment.
        required: false
        schema:
          type: string
      - name: summary_metric
        in: query
        description: Metric to summarize.
        required: false
        schema:
          type: string
      - name: currency
        in: query
        description: Currency code (ISO 4217).
        required: false
        schema:
          type: string
      - name: unit
        in: query
        description: Aggregation unit (e.g. day, week, month).
        required: false
        schema:
          type: string
      - name: week_starts_on
        in: query
        description: Day of week that a week starts on (e.g. monday, sunday).
        required: false
        schema:
          type: string
      - name: max_series
        in: query
        description: Maximum number of series to return.
        required: false
        schema:
          type: integer
      - name: filter[experiment_uid]
        in: query
        description: Filter by experiment UID.
        required: false
        schema:
          type: string
      - name: filter[experiment_uid][]
        in: query
        description: Filter by multiple experiment UIDs.
        required: false
        schema:
          type: array
          items:
            type: string
      responses:
        '200':
          description: Analytics summary data.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Experiments summary payload. `items` contains one entry per experiment
                  matched by `filter[experiment_uid][]`, with nested `groups` carrying the
                  group metadata (control flag, weight, bound remote config).
              example:
                total_count: 1
                items:
                  - uid: a6a360a2-41ed-4964-b45a-ea1b0c3e3386
                    experiment_id: 210
                    project_id: 789
                    name: Paywall layout A/B
                    alias_id: paywall_layout_ab
                    desc: Compare two paywall layouts on iOS onboarding
                    segment_percent: 100
                    primary_metric: subscription-cancellation
                    goal_direction: decrease
                    goal_value: 4
                    context_key: ''
                    context_specific: false
                    status: finished
                    finished_at: 1712246400
                    created_at: 1709654400
                    updated_at: 1777051834
                    groups:
                      - uid: df0ab472
                        experiment_group_id: 407
                        experiment_id: 210
                        project_id: 789
                        name: Control group
                        control: 1
                        weight: 1
                        created_at: 1709654400
                        updated_at: 1709654400
                      - uid: 3c458035
                        experiment_group_id: 408
                        experiment_id: 210
                        project_id: 789
                        name: Test variant #1
                        control: 0
                        weight: 1
                        remote_config_uid: 25561136-dc1b-4625-9a05-0550d1a04508
                        created_at: 1709654400
                        updated_at: 1709655000
                        remote_config:
                          remote_config_uid: 25561136-dc1b-4625-9a05-0550d1a04508
                          project_id: 789
                          payload:
                            headline: Unlock Pro
                            cta: Start free trial
                          created_at: 1709654400
                          updated_at: 0
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments/{experiment_id}:
    get:
      operationId: v4GetExperiment
      summary: Get an experiment
      description: Returns a single experiment by ID.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      responses:
        '200':
          description: Experiment details.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Experiment'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    patch:
      operationId: v4PatchExperiment
      summary: Partially update an experiment
      description: Updates specified fields of an experiment. Only provided fields are updated.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ExperimentPatchRequest'
      responses:
        '200':
          description: Updated experiment.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Experiment'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteExperiment
      summary: Delete an experiment
      description: Deletes an experiment by ID. Returns 204 on success.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      responses:
        '204':
          description: Experiment deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments/{experiment_id}/status:
    post:
      operationId: v4ChangeExperimentStatus
      summary: Change experiment status
      description: Changes the status of an experiment (e.g. start, pause, finish).
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ExperimentStatusRequest'
      responses:
        '200':
          description: Updated experiment with new status.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Experiment'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments/{experiment_id}/groups:
    get:
      operationId: v4ListExperimentGroups
      summary: List experiment groups
      description: Returns all groups for the specified experiment.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      responses:
        '200':
          description: A list of experiment groups.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                required:
                - object
                - url
                - data
                - has_more
                properties:
                  object:
                    type: string
                    enum:
                    - list
                  url:
                    type: string
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/V4ExperimentGroup'
                  has_more:
                    type: boolean
                    example: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateExperimentGroup
      summary: Create an experiment group
      description: Creates a new group for the specified experiment. Returns 201 with Location header.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ExperimentGroupCreateRequest'
      responses:
        '201':
          description: Experiment group created.
          headers:
            Location:
              description: URL of the created group.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ExperimentGroup'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments/{experiment_id}/groups/{group_id}:
    patch:
      operationId: v4PatchExperimentGroup
      summary: Update an experiment group
      description: Updates fields of the specified experiment group. All fields optional.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      - name: group_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Group identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ExperimentGroupCreateRequest'
      responses:
        '200':
          description: Updated experiment group.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ExperimentGroup'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment or group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteExperimentGroup
      summary: Delete an experiment group
      description: Deletes the specified experiment group. Returns 204 on success.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      - name: group_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Group identifier.
      responses:
        '204':
          description: Group deleted
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment or group not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /experiments/{experiment_id}/users/{user_id}:
    post:
      operationId: v4AttachUserToExperiment
      summary: Attach a user to an experiment group
      description: Manually assigns a user to a specific experiment group. The assignment
        persists; raising traffic later does not re-admit previously rejected users,
        and finishing the experiment releases all users. It also invalidates the
        SDK's in-memory config cache.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      - name: user_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: User identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ExperimentAttachRequest'
      responses:
        '204':
          description: User attached to experiment group
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment, group, or user not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: User already attached to experiment
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity (e.g. experiment is finished)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DetachUserFromExperiment
      summary: Detach a user from an experiment
      description: Removes a user's assignment from an experiment, invalidates the
        SDK's in-memory config cache, and makes the user eligible for automatic
        experiment assignment on subsequent requests.
      tags:
      - Experiments
      security:
      - secretAuth: []
      parameters:
      - name: experiment_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: Experiment identifier.
      - name: user_id
        in: path
        required: true
        schema:
          type: string
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 256
        description: User identifier.
      responses:
        '204':
          description: User detached from experiment
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Experiment or user not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Too many requests
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /users/{user_id}/purchases:
    get:
      operationId: v4ListUserPurchases
      summary: List purchases for a user
      description: 'Returns a paginated list of purchases for the specified user.

        Purchases are ordered by purchase date (newest first).

        Supports cursor-based pagination and optional platform filtering.

        '
      tags:
      - Purchases
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        description: The user identifier.
        schema:
          type: string
          maxLength: 256
        example: user_abc123
      - name: limit
        in: query
        description: Maximum number of purchases to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: 'Cursor for pagination. Pass the `id` of the last purchase from the previous page
          to fetch the next page.

          '
        required: false
        schema:
          type: string
      - name: filter[platform]
        in: query
        description: 'Filter purchases by platform. Repeat the query parameter to
          match multiple platforms (OR logic). Example: `?filter[platform]=app_store&filter[platform]=stripe`.

          '
        required: false
        explode: true
        schema:
          type: array
          maxItems: 3
          items:
            type: string
            x-extensible-enum:
            - app_store
            - play_store
            - stripe
      responses:
        '200':
          description: A paginated list of purchases.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4PurchaseList'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /users/{user_id}/properties:
    get:
      operationId: v4ListUserProperties
      summary: List properties for a user
      description: |
        Returns all stored properties for the specified user (up to 100 per user).
        The response is always a single page — there is no cursor pagination, so
        `has_more` is always `false` and `next_cursor` is always `null`.
        Qonversion-defined keys are prefixed with `_q_` (e.g., `_q_email`).
      tags:
      - User Properties
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        description: Qonversion User ID. SDK-generated IDs are prefixed with `QON_`.
        schema:
          type: string
          maxLength: 256
        example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      responses:
        '200':
          description: A list of user properties.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4UserPropertyList'
              examples:
                with_properties:
                  summary: User with custom and system properties
                  value:
                    object: list
                    url: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/properties
                    data:
                    - object: user_property
                      key: _q_email
                      value: test@email.com
                    - object: user_property
                      key: client_source
                      value: google_ads
                    - object: user_property
                      key: color
                      value: blue
                    has_more: false
                empty:
                  summary: User with no properties
                  value:
                    object: list
                    url: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/properties
                    data: []
                    has_more: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4SetUserProperties
      summary: Set (upsert) properties for a user
      description: |
        Upserts one or more properties for the specified user (1-100 items per call).
        Each property is identified by a key; existing values are overwritten.
        Supports partial success: as long as **at least one** property passes
        validation, the response is 200 with successfully saved properties under
        `saved_properties` and per-key failures under `property_errors`.

        **Effective validation** (applied per-item):
        - `key` — 1-80 characters, matching `^[-a-zA-Z0-9_.:]+$` and containing
          at least one letter. Keys starting with `_` are reserved for Qonversion
          system properties; only pre-registered keys prefixed with `_q_` (e.g.
          `_q_email`, `_q_name`) are accepted.
        - `value` — up to 120 bytes, must not contain `\n`, `\r`, `"`, or `'`.

        **400 behaviour** — returned without a per-key breakdown when:
        - the request itself is malformed (empty array, more than 100 items, or
          key/value exceeding the gateway's 256/1024-character limits), or
        - every property in the request fails validation (there is nothing to
          save). In that case retry with the offending keys removed to see
          per-key reasons in the 200 response.
      tags:
      - User Properties
      security:
      - secretAuth: []
      parameters:
      - name: user_id
        in: path
        required: true
        description: Qonversion User ID. SDK-generated IDs are prefixed with `QON_`.
        schema:
          type: string
          maxLength: 256
        example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      - name: Idempotency-Key
        in: header
        required: false
        description: Idempotency key for safe retries. Same key returns the original response.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4SetUserPropertiesRequest'
            examples:
              valid_and_invalid:
                summary: Mix of a valid and an invalid key (partial success)
                value:
                  properties:
                  - key: color
                    value: blue
                  - key: invalid key
                    value: oops
              single_custom:
                summary: Single custom property
                value:
                  properties:
                  - key: client_source
                    value: google_ads
      responses:
        '200':
          description: Properties processed (check property_errors for per-key failures).
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4UserPropertiesSetResult'
              examples:
                partial_success:
                  summary: Partial success — one saved, one rejected
                  value:
                    object: user_properties_set_result
                    url: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/properties
                    saved_properties:
                    - object: user_property
                      key: color
                      value: blue
                    property_errors:
                    - key: invalid key
                      error: 'property key: invalid key. Error: invalid key format'
                full_success:
                  summary: All properties saved
                  value:
                    object: user_properties_set_result
                    url: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/properties
                    saved_properties:
                    - object: user_property
                      key: client_source
                      value: google_ads
                    property_errors: []
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported media type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /identities/{identity_id}:
    get:
      operationId: v4GetIdentity
      summary: Get an identity by external ID
      description: 'Returns the identity linked to the specified external ID.

        An identity represents the association between a Qonversion anonymous user

        and an external user identifier from your system.

        '
      tags:
      - Identities
      security:
      - secretAuth: []
      parameters:
      - name: identity_id
        in: path
        required: true
        description: The external identity identifier.
        schema:
          type: string
          maxLength: 255
          pattern: ^[a-zA-Z0-9._-]+$
        example: ext-user-123
      responses:
        '200':
          description: The identity object.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Identity'
              example:
                object: identity
                id: ext-user-123
                url: /v4/identities/ext-user-123
                user_id: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Identity not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /identities:
    post:
      operationId: v4CreateIdentity
      summary: Create an identity link
      description: 'Links a Qonversion anonymous user to an external identity ID.

        If `user_id` is null, a new user is created and linked.

        This is the mechanism for matching Qonversion anonymous users with your own user IDs.

        '
      tags:
      - Identities
      security:
      - secretAuth: []
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        description: Idempotency key for safe retries. Same key returns the original response.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4IdentityCreateRequest'
            example:
              identity_id: ext-user-123
              user_id: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
      responses:
        '201':
          description: Identity created successfully.
          headers:
            Location:
              description: URL of the created identity.
              schema:
                type: string
                example: /v4/identities/ext-user-123
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Identity'
              example:
                object: identity
                id: ext-user-123
                url: /v4/identities/ext-user-123
                user_id: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: User not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: Identity already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported media type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Logical error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /exports:
    post:
      operationId: v4CreateExport
      summary: Create export (async)
      description: 'Creates a new data export task. Returns 202 Accepted with a Location

        header pointing to the status endpoint. Exports are project-scoped

        and require the RAW_DATA_ACCESS feature.

        '
      tags:
      - Exports
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                from_timestamp:
                  type: integer
                  description: Unix timestamp for export start.
                to_timestamp:
                  type: integer
                  description: Unix timestamp for export end.
                platform:
                  type: string
                  description: Platform filter (e.g. iOS, Android).
      responses:
        '202':
          description: Export task accepted.
          headers:
            Location:
              description: URL to poll for export status.
              schema:
                type: string
                example: /v4/exports/abc-123
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: export
                  id:
                    type: string
                  url:
                    type: string
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /exports/history:
    get:
      operationId: v4ListExportsHistory
      summary: List past exports
      description: Returns a list of past exports for the authenticated project.
      tags:
      - Exports
      security:
      - secretAuth: []
      responses:
        '200':
          description: A list of past exports.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: list
                  url:
                    type: string
                    example: /v4/exports/history
                  data:
                    type: array
                    items:
                      type: object
                  has_more:
                    type: boolean
                    example: false
              example:
                object: list
                url: /v4/exports/history
                data:
                  - object: export
                    id: XWyYEsHIJqRPpgtNuR_rASh5LhSxq5gi
                    url: /v4/exports/XWyYEsHIJqRPpgtNuR_rASh5LhSxq5gi
                    status: done
                    platform: iOS
                    from_timestamp: '2026-04-23T10:16:12Z'
                    to_timestamp: '2026-04-24T10:16:12Z'
                    created_at: '2026-04-24T08:16:12Z'
                    expires_at: '2026-05-01T08:16:15Z'
                    file_url: https://cloud.qonversion.io/report/XWyYEsHIJqRPpgtNuR_rASh5LhSxq5gi
                  - object: export
                    id: ZTS9okN4hZefx_XegtLLpvM0UfMVULQk
                    url: /v4/exports/ZTS9okN4hZefx_XegtLLpvM0UfMVULQk
                    status: done
                    platform: iOS
                    from_timestamp: '2026-04-23T02:00:00Z'
                    to_timestamp: '2026-04-24T02:00:00Z'
                    created_at: '2026-04-24T02:01:07Z'
                    expires_at: '2026-05-01T17:31:16Z'
                    file_url: https://cloud.qonversion.io/report/ZTS9okN4hZefx_XegtLLpvM0UfMVULQk
                has_more: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /exports/{export_id}:
    get:
      operationId: v4GetExport
      summary: Get export status
      description: Check the status of an export or download the result.
      tags:
      - Exports
      security:
      - secretAuth: []
      parameters:
      - name: export_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
      responses:
        '200':
          description: Export status.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: export
                  id:
                    type: string
                  url:
                    type: string
        '400':
          description: Invalid export_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Export not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /events:
    get:
      operationId: v4ListEvents
      summary: List events
      description: Returns a list of event definitions (track events) for the authenticated project. Events
        are emitted by the SDK and represent subscription lifecycle and user behavior.
      tags:
      - Events
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 40
          default: 20
        description: Maximum number of events to return.
      - name: offset
        in: query
        required: false
        schema:
          type: integer
          minimum: 0
          maximum: 100000
          default: 0
        description: Number of events to skip.
      - name: sort_order
        in: query
        required: false
        schema:
          type: string
          enum:
          - asc
          - desc
          default: desc
        description: Sort direction by event time.
      responses:
        '200':
          description: A list of events.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: list
                  url:
                    type: string
                    example: /v4/events
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/V4Event'
                  has_more:
                    type: boolean
                    example: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /scheduled-reports:
    get:
      operationId: v4ListScheduledReports
      summary: List scheduled reports
      description: Returns all scheduled reports for the authenticated project.
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: offset
        in: query
        required: false
        schema:
          type: integer
          minimum: 0
          default: 0
      responses:
        '200':
          description: A list of scheduled reports.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: list
                  url:
                    type: string
                    example: /v4/scheduled-reports
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/V4ScheduledReport'
                  has_more:
                    type: boolean
                    example: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateScheduledReport
      summary: Create scheduled report
      description: Creates a new scheduled report.
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ScheduledReportCreateRequest'
      responses:
        '201':
          description: Scheduled report created.
          headers:
            Location:
              description: URL of the created report.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ScheduledReport'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /scheduled-reports/destinations:
    get:
      operationId: v4ListScheduledReportDestinations
      summary: List available destinations
      description: Returns all available report destinations (email, S3, GCS, etc.).
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      responses:
        '200':
          description: A list of available destinations.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                properties:
                  object:
                    type: string
                    example: list
                  url:
                    type: string
                    example: /v4/scheduled-reports/destinations
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/V4ScheduledReportDestination'
                  has_more:
                    type: boolean
                    example: false
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /scheduled-reports/{report_id}:
    get:
      operationId: v4GetScheduledReport
      summary: Get scheduled report
      description: Returns details for a single scheduled report.
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      parameters:
      - name: report_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 64
          pattern: ^[a-zA-Z0-9._-]+$
      responses:
        '200':
          description: Scheduled report details.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ScheduledReport'
        '400':
          description: Invalid report_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Report not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    put:
      operationId: v4UpdateScheduledReport
      summary: Update scheduled report
      description: Partially update a scheduled report. Omit any field to keep its current value; at least one field must be supplied.
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      parameters:
      - name: report_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 64
          pattern: ^[a-zA-Z0-9._-]+$
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ScheduledReportUpdateRequest'
      responses:
        '200':
          description: Updated scheduled report.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ScheduledReport'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Report not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteScheduledReport
      summary: Delete scheduled report
      description: Deletes a scheduled report.
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      parameters:
      - name: report_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 64
          pattern: ^[a-zA-Z0-9._-]+$
      responses:
        '204':
          description: Report deleted.
        '400':
          description: Invalid report_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Report not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /scheduled-reports/{report_id}/send-test:
    post:
      operationId: v4SendTestScheduledReport
      summary: Send test report
      description: Triggers a test send for a scheduled report. Returns 202 Accepted.
      tags:
      - Scheduled Reports
      security:
      - secretAuth: []
      parameters:
      - name: report_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 64
          pattern: ^[a-zA-Z0-9._-]+$
      responses:
        '202':
          description: Test send accepted; delivery runs asynchronously.
          headers:
            Location:
              description: URL of the operation resource.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                required: [object, url, message]
                properties:
                  object:
                    type: string
                    example: operation
                  url:
                    type: string
                  message:
                    type: string
                    example: Test report queued for delivery
        '400':
          description: Invalid report_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Report not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: "Rate limited. The send-test endpoint is capped at one call per minute per report; the response includes a Retry-After header of 60 seconds."
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /integrations/meta:
    get:
      operationId: v4GetIntegrationsMeta
      summary: Get integrations metadata
      description: |
        Returns the catalog of supported integration providers grouped by category.
        Each item exposes its `slug` (use as `integration` in `POST /v4/integrations`)
        and `allowedStores` (the subset of `target_platform` values the provider supports).
        Per-provider credential schemas are **not** returned — credentials are configured
        out-of-band after the integration record is created.
      tags:
      - Integrations
      security:
      - secretAuth: []
      responses:
        '200':
          description: Integrations metadata.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4IntegrationsMetaResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /integrations:
    get:
      operationId: v4ListIntegrations
      summary: List integrations
      description: |
        Returns every integration configured for the project. There is no cursor
        or offset pagination: the full set is returned in a single call and
        `has_more` is always `false`.
      tags:
      - Integrations
      security:
      - secretAuth: []
      responses:
        '200':
          description: List of integrations.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4IntegrationListResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateIntegration
      summary: Create integration
      description: Creates a new integration for the project.
      tags:
      - Integrations
      security:
      - secretAuth: []
      parameters:
      - name: Idempotency-Key
        in: header
        required: false
        description: Unique key to ensure idempotent creation. Same key returns original response.
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4IntegrationCreateRequest'
      responses:
        '201':
          description: Integration created.
          headers:
            Location:
              description: URL of the created integration resource.
              schema:
                type: string
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Integration'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '409':
          description: Idempotency conflict — same key with different body
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported media type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /integrations/{integration_id}/status:
    post:
      operationId: v4UpdateIntegrationStatus
      summary: Update integration status
      description: Enables or disables an integration.
      tags:
      - Integrations
      security:
      - secretAuth: []
      parameters:
      - name: integration_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4IntegrationStatusRequest'
      responses:
        '200':
          description: Integration status updated.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Integration'
        '400':
          description: Invalid integration_id or request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Integration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported media type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /integrations/{integration_id}:
    delete:
      operationId: v4DeleteIntegration
      summary: Delete integration
      description: Permanently deletes an integration.
      tags:
      - Integrations
      security:
      - secretAuth: []
      parameters:
      - name: integration_id
        in: path
        required: true
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
      responses:
        '204':
          description: Integration deleted successfully.
        '400':
          description: Invalid integration_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Integration not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Storage error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /automations:
    get:
      operationId: v4ListAutomations
      summary: List automations
      deprecated: true
      description: 'Deprecated — the Automations product surface has been removed; this API remains available for existing integrations only. Returns a paginated list of automations for the authenticated project.

        Automations are ordered by ID (descending).

        Supports cursor-based pagination via `limit` and `starting_after`.

        '
      tags:
      - Automations
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        description: Maximum number of automations to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: 'Cursor for pagination. Pass the `id` of the last automation from the previous page
          to fetch the next page.

          '
        required: false
        schema:
          type: string
          maxLength: 256
      responses:
        '200':
          description: A paginated list of automations.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AutomationList'
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/automations
                    data:
                    - object: automation
                      id: auto-abc123
                      url: /v4/automations/auto-abc123
                      name: Welcome Flow
                      caption: Onboarding automation
                      status: active
                      data:
                        type: event
                        platform: iOS
                        initiators:
                        - uid: "2"
                          type: event
                        actions:
                          push: nCRUE7SW
                          screen: null
                        segments: null
                    has_more: false
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/automations
                    data: []
                    has_more: false
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateAutomation
      summary: Create an automation
      deprecated: true
      description: Deprecated — the Automations product surface has been removed; this API remains available for existing integrations only. Creates a new automation for the authenticated project.
      tags:
      - Automations
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4AutomationCreate'
            example:
              name: Welcome Flow
              caption: Sends a welcome message to new users
              status: active
              data:
                platform: iOS
                initiators:
                - uid: "2"
                  type: event
                actions:
                  push: nCRUE7SW
                  screen: qUY7JXgF
                segments: null
      responses:
        '201':
          description: Automation created successfully.
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the created automation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Automation'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /automations/{automation_id}:
    get:
      operationId: v4GetAutomation
      summary: Get an automation
      deprecated: true
      description: Deprecated — the Automations product surface has been removed; this API remains available for existing integrations only. Returns a single automation by ID.
      tags:
      - Automations
      security:
      - secretAuth: []
      parameters:
      - name: automation_id
        in: path
        required: true
        description: Automation identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: auto-abc123
      responses:
        '200':
          description: Automation details.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Automation'
        '400':
          description: Invalid automation_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Automation not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    put:
      operationId: v4UpdateAutomation
      summary: Update an automation
      deprecated: true
      description: Deprecated — the Automations product surface has been removed; this API remains available for existing integrations only. Fully replaces an automation's mutable fields. All mutable fields must be provided.
      tags:
      - Automations
      security:
      - secretAuth: []
      parameters:
      - name: automation_id
        in: path
        required: true
        description: Automation identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: auto-abc123
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4AutomationUpdate'
            example:
              name: Updated Welcome Flow
              caption: Updated description
              status: inactive
              data:
                platform: iOS
                initiators:
                - uid: "2"
                  type: event
                actions:
                  push: nCRUE7SW
                  screen: qUY7JXgF
                segments: A0SzRbM2vmmwixbpQxtI
      responses:
        '200':
          description: Updated automation.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Automation'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Automation not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteAutomation
      summary: Delete an automation
      deprecated: true
      description: Deprecated — the Automations product surface has been removed; this API remains available for existing integrations only. Permanently deletes an automation by ID.
      tags:
      - Automations
      security:
      - secretAuth: []
      parameters:
      - name: automation_id
        in: path
        required: true
        description: Automation identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: auto-abc123
      responses:
        '204':
          description: Automation deleted successfully. No response body.
        '400':
          description: Invalid automation_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Automation not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /automations/{automation_id}/status:
    patch:
      operationId: v4PatchAutomationStatus
      summary: Update automation status
      deprecated: true
      description: Deprecated — the Automations product surface has been removed; this API remains available for existing integrations only. Toggles the status of an automation between `active` and `inactive`.
      tags:
      - Automations
      security:
      - secretAuth: []
      parameters:
      - name: automation_id
        in: path
        required: true
        description: Automation identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: auto-abc123
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4AutomationStatusPatch'
            example:
              status: inactive
      responses:
        '204':
          description: Status updated successfully. No response body.
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Feature not available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait before retrying
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Automation not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  # ── v4 analytics ────────────────────────────────────────────────────────────

  /analytics/charts/{chart_code}:
    get:
      operationId: v4GetAnalyticsChart
      summary: Get analytics chart data
      description: |
        Returns time-series data for a chart. `chart_code` selects the metric; pass query
        parameters to constrain the time range and segmentation.

        Public chart codes (25 total) — see `enum` for the full machine-readable list:

        - **Revenue**: `proceeds` (net), `sales` (gross), `refunds`, `refund-rate`, `arpu`, `arppu`.
        - **Recurring revenue**: `mrr`, `arr`, `mrr-movement`, `arr-movement` (new / expansion / contraction / churn).
        - **Subscriptions**: `active-subscriptions`, `new-subscriptions`, `paid-subscriptions-movement`, `subscriptions-overview`, `subscription-cancellation`.
        - **Trials**: `free-trials`, `active-trials`, `trials-movement`, `trial-cancellation`, `trial-to-paid`.
        - **Acquisition / conversion**: `users-overview`, `user-to-trial`, `user-to-paid`.
        - **Back-compat aliases** (factory maps to canonical executor): `user-to-trial-conversion` = `user-to-trial`, `subscription-cancellation-rate` = `subscription-cancellation`.

        Codes deferred to v4 api 2.0 (currently return 404): `cohort-revenue`,
        `cohort-active-subscriptions`, `experiment-new-users`, `experiment-users-to-trials`,
        `experiment-users-to-paid`, `refund-keeper`, `events`.

        Segmentation codes (pass via `segmentation`) and filter attribute codes
        (pass via `filter[<attribute>][]`) are discoverable from
        `GET /v4/analytics/charts/{chart_code}/meta`.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: chart_code
          in: path
          required: true
          description: Chart code. Only the codes listed in the endpoint description are exposed publicly; others return 404.
          schema:
            type: string
            enum:
              - proceeds
              - active-subscriptions
              - paid-subscriptions-movement
              - users-overview
              - free-trials
              - active-trials
              - trials-movement
              - user-to-trial
              - trial-to-paid
              - user-to-paid
              - sales
              - refunds
              - refund-rate
              - arppu
              - arpu
              - trial-cancellation
              - subscription-cancellation
              - subscriptions-overview
              - new-subscriptions
              - mrr
              - arr
              - mrr-movement
              - arr-movement
              - user-to-trial-conversion
              - subscription-cancellation-rate
            maxLength: 64
          example: proceeds
        - name: from
          in: query
          required: false
          description: Start of the time range (Unix timestamp, seconds). Default is 7 days before `to`.
          schema: { type: integer, format: int64 }
          example: 1776171456
        - name: to
          in: query
          required: false
          description: End of the time range (Unix timestamp, seconds). Default is the current time.
          schema: { type: integer, format: int64 }
          example: 1776776256
        - name: unit
          in: query
          required: false
          description: Time bucket size. `hour` requires a short range; `month` is used for long-range trends.
          schema:
            type: string
            enum: [hour, day, week, month]
            default: day
        - name: environment
          in: query
          required: false
          description: "Environment: `0` = sandbox, `1` = production."
          schema:
            type: integer
            enum: [0, 1]
            default: 1
        - name: max_series
          in: query
          required: false
          description: Upper bound on the number of segmentation series returned. Clamped to 0..500 on the upstream.
          schema:
            type: integer
            minimum: 0
            maximum: 500
            default: 50
        - name: segmentation
          in: query
          required: false
          description: |
            Attribute to split the chart into segments (e.g. `country`, `target_platform`,
            `product_id`). Not all charts support every segmentation — see `*/meta`.
          schema:
            type: string
          example: target_platform
        - name: currency
          in: query
          required: false
          description: Three-letter ISO 4217 currency code for monetary charts. Defaults to `USD`. The list of supported codes is `GET /v4/analytics/currencies`.
          schema:
            type: string
            pattern: '^[A-Z]{3}$'
            default: USD
        - name: "filter[<attribute>][]"
          in: query
          required: false
          description: |
            Attribute-scoped filter (repeat the parameter once per value). Each attribute
            is **AND**ed with every other attribute; values within the same attribute are
            **OR**ed.

            Examples:
              * `filter[country][]=US&filter[country][]=GB` — US **or** UK
              * `filter[country][]=US&filter[target_platform][]=iOS` — US **and** iOS
              * `filter[product_id][]=premium_monthly&filter[product_id][]=premium_yearly`

            Attribute codes are stable across projects; their **value lists are
            project-scoped** and discoverable from the chart's `*/meta` response
            (`filter_conditions[].attribute` / `filter_conditions[].values[]`). Common
            attribute codes:

            | Group | Attribute codes |
            |-------|-----------------|
            | Product / store | `target_platform`, `country`, `product_id`, `purchase_currency` |
            | Device | `locale`, `model`, `os_version`, `app_version`, `sdk_version`, `device_id` |
            | Customer / ID | `user_id`, `q_user_id` |
            | Attribution | `media_source_name`, `campaign_name`, `ad_set_name`, `ad_name` |
            | Experiment | `experiment_uid`, `experiment_group_uid` |
            | Screen (chart-specific) | `screen_uid` |

            Scalar attributes (`user_id`, `q_user_id`, `device_id`) accept a single value;
            list attributes accept many. Up to 50 distinct attributes and 100 values per
            attribute are accepted; the rest are silently dropped.
          schema:
            type: array
            items: { type: string }
          style: form
          explode: true
      responses:
        '200':
          description: Chart data.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsChart'
              example:
                object: analytics_chart
                url: /v4/analytics/charts/proceeds
                code: proceeds
                from: 1776171456
                to: 1776776256
                unit: day
                environment: 1
                currency: USD
                measure: usd
                totalType: sum
                seriesRelation: partsOfWhole
                maxSeries: 50
                series:
                  - label: After refunds
                    total: 380276.24
                    totalPrev: 326882.25
                    data:
                      - { start_time: 1776171456, value: 6163.49 }
                      - { start_time: 1776257856, value: 5821.11 }
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Chart not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/charts/{chart_code}/meta:
    get:
      operationId: v4GetAnalyticsChartMeta
      summary: Get analytics chart metadata
      description: |
        Returns the chart's display metadata: available filter attributes and their
        concrete values (pre-scoped to the project), available segmentation dimensions,
        supported time units, and chart types. Use this to build a UI / discover the
        `filter[<attribute>][]` and `segmentation` values for
        `GET /v4/analytics/charts/{chart_code}`.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: chart_code
          in: path
          required: true
          description: Chart code. Must be a publicly exposed chart (see `GET /v4/analytics/charts/{chart_code}`).
          schema:
            type: string
            enum:
              - proceeds
              - active-subscriptions
              - paid-subscriptions-movement
              - users-overview
              - free-trials
              - active-trials
              - trials-movement
              - user-to-trial
              - trial-to-paid
              - user-to-paid
              - sales
              - refunds
              - refund-rate
              - arppu
              - arpu
              - trial-cancellation
              - subscription-cancellation
              - subscriptions-overview
              - new-subscriptions
              - mrr
              - arr
              - mrr-movement
              - arr-movement
              - user-to-trial-conversion
              - subscription-cancellation-rate
            maxLength: 64
          example: proceeds
        - name: from
          in: query
          required: false
          description: Time range start (Unix timestamp, seconds). Used to scope filter value enumeration.
          schema: { type: integer, format: int64 }
        - name: to
          in: query
          required: false
          description: Time range end (Unix timestamp, seconds). Used to scope filter value enumeration.
          schema: { type: integer, format: int64 }
        - name: environment
          in: query
          required: false
          description: "Environment: `0` = sandbox, `1` = production."
          schema: { type: integer, enum: [0, 1], default: 1 }
      responses:
        '200':
          description: Chart metadata.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsChartMeta'
              example:
                object: analytics_chart_meta
                url: /v4/analytics/charts/proceeds/meta
                code: proceeds
                title: Proceeds
                description: Shows net revenue (after refunds), with App Stores' commission already deducted.
                docUrl: https://documentation.qonversion.io/docs/revenue#proceeds
                isAvailable: true
                availabilityMessage: ""
                type_default: column
                types: [line, column, area]
                units_available: [hour, day, week, month]
                segmentations:
                  - { code: target_platform, label: Store }
                  - { code: country, label: Country }
                  - { code: product_id, label: Product }
                filter_conditions:
                  - attribute: target_platform
                    label: Store
                    multiple: true
                    type: list
                    values:
                      - { code: iOS, label: Apple App Store }
                      - { code: Android, label: Google Play }
                      - { code: Stripe, label: Stripe }
                  - attribute: country
                    label: Country
                    multiple: true
                    type: list
                    values:
                      - { code: US, label: United States of America }
                      - { code: GB, label: United Kingdom }
                  - { attribute: device_id, category: Device, label: Device ID, type: text }
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Chart not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/cards/{card_code}:
    get:
      operationId: v4GetAnalyticsCard
      summary: Get analytics card data
      description: |
        Returns the current value of a scalar dashboard card. Cards bundle several
        related metrics (e.g. `realtime` returns today's trials, subscriptions,
        in-app purchases and tracked revenue as a four-row table).

        Valid public card codes:
          * `realtime` — today-so-far vs. yesterday counters
            (`trials_count`, `subscriptions_count`, `inapp_count`, `tracked_revenue`).

        Additional codes are internal-only and return 404 when requested publicly.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: card_code
          in: path
          required: true
          description: Card code. Only codes listed in the endpoint description are exposed publicly.
          schema:
            type: string
            enum: [realtime]
            maxLength: 64
          example: realtime
        - name: from
          in: query
          required: false
          description: Start of the time range (Unix timestamp, seconds). Ignored by cards that report fixed windows (e.g. `realtime`).
          schema: { type: integer, format: int64 }
        - name: to
          in: query
          required: false
          description: End of the time range (Unix timestamp, seconds). Ignored by cards that report fixed windows.
          schema: { type: integer, format: int64 }
        - name: unit
          in: query
          required: false
          schema: { type: string, enum: [hour, day, week, month] }
        - name: environment
          in: query
          required: false
          description: "Environment: `0` = sandbox, `1` = production."
          schema: { type: integer, enum: [0, 1], default: 1 }
        - name: max_series
          in: query
          required: false
          schema: { type: integer, minimum: 0, maximum: 500 }
        - name: segmentation
          in: query
          required: false
          schema: { type: string }
        - name: currency
          in: query
          required: false
          description: Three-letter ISO 4217 currency code. Affects monetary values like `tracked_revenue`.
          schema: { type: string, pattern: '^[A-Z]{3}$', default: USD }
        - name: "filter[<attribute>][]"
          in: query
          required: false
          description: Same schema as the charts endpoint.
          schema:
            type: array
            items: { type: string }
          style: form
          explode: true
      responses:
        '200':
          description: Card data. `realtime` returns an array of one row per sub-metric.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsCard'
              example:
                - { code: trials_count,        value: 12,   valuePrev: 7 }
                - { code: subscriptions_count, value: 4,    valuePrev: 3 }
                - { code: inapp_count,         value: 0,    valuePrev: 1 }
                - { code: tracked_revenue,     value: 43.8, valuePrev: 21.99 }
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Card not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/currencies:
    get:
      operationId: v4GetAnalyticsCurrencies
      summary: Get supported analytics currencies
      description: |
        Returns the list of three-letter ISO 4217 currency codes accepted by the
        `currency` query parameter across analytics endpoints. `USD` is always first
        and is the implicit default when `currency` is omitted.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: from
          in: query
          required: false
          description: Accepted for forward-compatibility; currently ignored — the currency list does not depend on the time range.
          schema: { type: integer, format: int64 }
        - name: to
          in: query
          required: false
          schema: { type: integer, format: int64 }
        - name: environment
          in: query
          required: false
          schema: { type: integer, enum: [0, 1], default: 1 }
      responses:
        '200':
          description: List of supported currency codes.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsCurrencies'
              example:
                object: analytics_currencies
                url: /v4/analytics/currencies
                currencies: [USD, EUR, GBP, JPY, CNY, AED, AUD, BRL, CAD, CHF, HKD, INR, KRW, MXN, NOK, NZD, RUB, SEK, SGD, TRY, ZAR]
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/cohorts:
    get:
      operationId: v4GetAnalyticsCohorts
      summary: Get cohort analytics data
      description: |
        Returns cohort-over-time tables for the project. A cohort is a group of users
        sharing an acquisition event (see `cohort_definition`). Rows are cohorts,
        columns are time offsets (see `grouping`). Cells are the `metric` (revenue,
        subscriptions, payers, ARPU, ARPPU).

        Use `GET /v4/analytics/cohorts/meta` to discover valid filter attributes and
        their concrete values for the project.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: cohort_from
          in: query
          required: false
          description: Cohort-range start (Unix timestamp, seconds). Defaults to `now - 90 days`.
          schema: { type: integer, format: int64 }
        - name: cohort_to
          in: query
          required: false
          description: Cohort-range end (Unix timestamp, seconds). Defaults to the current time. Normalised to the next day's 00:00 UTC on the server.
          schema: { type: integer, format: int64 }
        - name: mode
          in: query
          required: false
          description: |
            * `by_renewals` — columns are subscription renewal indexes (P1, P2, …).
            * `by_days` — columns are calendar offsets from the cohort start.
          schema: { type: string, enum: [by_renewals, by_days], default: by_renewals }
        - name: grouping
          in: query
          required: false
          description: Column (period) granularity.
          schema: { type: string, enum: [day, week, month, quarter, year], default: week }
        - name: environment
          in: query
          required: false
          description: "Environment: `0` = sandbox, `1` = production."
          schema: { type: integer, enum: [0, 1], default: 1 }
        - name: cohort_definition
          in: query
          required: false
          description: |
            What event defines cohort membership.
              * `new_customers` — first app install / user creation.
              * `initial_conversions` — first trial or paid conversion.
              * `new_paying` — first paid transaction.
          schema: { type: string, enum: [new_customers, initial_conversions, new_paying], default: new_customers }
        - name: revenue_type
          in: query
          required: false
          description: |
            * `gross` — raw transaction values.
            * `net` — after refunds and store commission.
          schema: { type: string, enum: [gross, net], default: gross }
        - name: currency
          in: query
          required: false
          description: ISO 4217 currency code for monetary cells. Non-USD values are converted at the transaction's historical rate.
          schema: { type: string, pattern: '^[A-Z]{3}$', default: USD }
        - name: group_by
          in: query
          required: false
          description: |
            Optional segmentation attribute — when set, response includes a `segments` array,
            one entry per attribute value. Allowed values match `filter_conditions[].attribute`
            from cohorts/meta.
          schema: { type: string }
          example: target_platform
        - name: "filter[<attribute>][]"
          in: query
          required: false
          description: Same attribute-scoped filter schema as the charts endpoint.
          schema:
            type: array
            items: { type: string }
          style: form
          explode: true
      responses:
        '200':
          description: Cohort table.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsCohorts'
              example:
                object: analytics_cohorts
                url: /v4/analytics/cohorts
                mode: by_renewals
                grouping: week
                cohort_from: 1768780800
                cohort_to: 1776816000
                currency: USD
                period_labels: [P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12]
                cohorts: []
                total: null
                max_values:
                  arpas: 0
                  arppu: 0
                  arpu: 0
                  payers: 0
                  revenue: 0
                  subscriptions: 0
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/cohorts/meta:
    get:
      operationId: v4GetAnalyticsCohortsMeta
      summary: Get cohort analytics metadata
      description: |
        Returns the discrete value sets needed to build a cohort query: available
        `mode`s, `grouping`s, `metric`s, `cohort_definition`s, and filter attributes
        with their concrete values (pre-scoped to the project).
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: from
          in: query
          required: false
          schema: { type: integer, format: int64 }
        - name: to
          in: query
          required: false
          schema: { type: integer, format: int64 }
        - name: environment
          in: query
          required: false
          schema: { type: integer, enum: [0, 1], default: 1 }
      responses:
        '200':
          description: Cohort metadata.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsCohortsMeta'
              example:
                object: analytics_cohorts_meta
                url: /v4/analytics/cohorts/meta
                modes:
                  - { code: by_renewals, label: By Renewals }
                  - { code: by_days,     label: By Days }
                groupings:
                  - { code: day,     label: Day }
                  - { code: week,    label: Week }
                  - { code: month,   label: Month }
                  - { code: quarter, label: Quarter }
                  - { code: year,    label: Year }
                metrics:
                  - { code: revenue,       label: Revenue }
                  - { code: subscriptions, label: Subscriptions }
                  - { code: payers,        label: Payers }
                  - { code: arpu,          label: ARPU }
                  - { code: arppu,         label: ARPPU }
                definitions:
                  - { code: new_customers,        label: New Customers }
                  - { code: initial_conversions,  label: Initial Conversions }
                  - { code: new_paying,           label: New Paying Customers }
                filter_conditions:
                  - attribute: target_platform
                    label: Store
                    persistent: true
                    type: list
                    values:
                      - { code: iOS,     label: Apple App Store }
                      - { code: Android, label: Google Play }
                      - { code: Stripe,  label: Stripe }
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/ltv:
    get:
      operationId: v4GetAnalyticsLtv
      summary: Get LTV analytics data
      description: |
        Returns lifetime-value curves for cohorts in the requested range. `series`
        is a list of time-indexed revenue (or ARPU / ARPPU) points; `segment` +
        `segments` let you split the curve by an attribute.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: cohort_from
          in: query
          required: false
          description: Cohort-range start (Unix timestamp, seconds). Defaults to `now - 90 days`.
          schema: { type: integer, format: int64 }
        - name: cohort_to
          in: query
          required: false
          description: Cohort-range end (Unix timestamp, seconds). Defaults to the current time.
          schema: { type: integer, format: int64 }
        - name: mode
          in: query
          required: false
          schema: { type: string, enum: [by_days, by_renewals], default: by_days }
        - name: environment
          in: query
          required: false
          schema: { type: integer, enum: [0, 1], default: 1 }
        - name: segment
          in: query
          required: false
          description: |
            Optional attribute to split the LTV curve into per-value series.
            Allowed values come from `GET /v4/analytics/ltv/meta` (`segmentations[].code`).
          schema: { type: string }
          example: target_platform
        - name: revenue_type
          in: query
          required: false
          schema: { type: string, enum: [gross, net], default: gross }
        - name: currency
          in: query
          required: false
          description: ISO 4217 currency code. Defaults to `USD`.
          schema: { type: string, pattern: '^[A-Z]{3}$', default: USD }
        - name: "filter[<attribute>][]"
          in: query
          required: false
          description: Attribute-scoped filter. Allowed attribute codes come from `GET /v4/analytics/ltv/meta` (`filter_conditions[].attribute`).
          schema:
            type: array
            items: { type: string }
          style: form
          explode: true
      responses:
        '200':
          description: LTV curves.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsLtv'
              example:
                object: analytics_ltv
                url: /v4/analytics/ltv
                mode: by_days
                cohort_from: 1769000695
                cohort_to: 1776816000
                cohort_users: 4542
                paying_users: 0
                revenue_type: gross
                currency: USD
                measure: usd
                segment: null
                segments: []
                series: []
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/ltv/meta:
    get:
      operationId: v4GetAnalyticsLtvMeta
      summary: Get LTV analytics metadata
      description: |
        Returns available `mode`s, `segmentation` attributes, and project-scoped
        filter attribute values for the LTV endpoint.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: from
          in: query
          required: false
          schema: { type: integer, format: int64 }
        - name: to
          in: query
          required: false
          schema: { type: integer, format: int64 }
        - name: environment
          in: query
          required: false
          schema: { type: integer, enum: [0, 1], default: 1 }
      responses:
        '200':
          description: LTV metadata.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsLtvMeta'
              example:
                object: analytics_ltv_meta
                url: /v4/analytics/ltv/meta
                modes:
                  - { code: by_days,     label: By Days }
                  - { code: by_renewals, label: By Renewals }
                segmentations:
                  - { code: target_platform,    label: Store }
                  - { code: product_id,         label: Product }
                  - { code: country,            label: Country }
                  - { code: media_source_name,  label: Media Source }
                  - { code: campaign_name,      label: Campaign }
                filter_conditions:
                  - attribute: target_platform
                    label: Store
                    persistent: true
                    type: list
                    values:
                      - { code: iOS,     label: Apple App Store }
                      - { code: Android, label: Google Play }
                      - { code: Stripe,  label: Stripe }
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/ltv/trial-conversion:
    get:
      operationId: v4GetAnalyticsLtvTrialConversion
      summary: Get LTV trial-conversion analytics data
      description: |
        Returns the trial→paid conversion rate for the requested cohort range — number of
        trials started, number that converted, and the conversion rate as a decimal
        (0.0–1.0). Accepts the same filter and `mode`/`revenue_type` shape as the LTV
        chart endpoint.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: cohort_from
          in: query
          required: false
          description: Cohort-range start (Unix timestamp, seconds). Defaults to `now - 90 days`.
          schema: { type: integer, format: int64 }
        - name: cohort_to
          in: query
          required: false
          schema: { type: integer, format: int64 }
        - name: mode
          in: query
          required: false
          schema: { type: string, enum: [by_days, by_renewals], default: by_days }
        - name: environment
          in: query
          required: false
          schema: { type: integer, enum: [0, 1], default: 1 }
        - name: segment
          in: query
          required: false
          schema: { type: string }
        - name: revenue_type
          in: query
          required: false
          schema: { type: string, enum: [gross, net], default: gross }
        - name: currency
          in: query
          required: false
          schema: { type: string, pattern: '^[A-Z]{3}$', default: USD }
        - name: "filter[<attribute>][]"
          in: query
          required: false
          schema:
            type: array
            items: { type: string }
          style: form
          explode: true
      responses:
        '200':
          description: Trial→paid conversion summary.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsLtvTrialConversion'
              example:
                object: analytics_ltv_trial_conversion
                url: /v4/analytics/ltv/trial-conversion
                trials_started: 1254
                trials_converted: 217
                conversion_rate: 0.173
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /analytics/insights:
    get:
      operationId: v4GetAnalyticsInsights
      summary: Get analytics insights
      description: |
        Returns AI-generated insights for the project over the last `period` days.
        Responses are cached on the upstream; pass `force=true` to regenerate.
        The `insights[]` array groups observations by type (`critical`, `positive`,
        `tip`, `info`) — each item has a short `title`, a longer `body`, and a
        suggested `action`.
      tags:
      - Analytics
      security:
        - secretAuth: []
      parameters:
        - name: period
          in: query
          required: false
          description: Look-back window in days. Must be between 1 and 365.
          schema:
            type: integer
            minimum: 1
            maximum: 365
            default: 30
        - name: force
          in: query
          required: false
          description: Bypass the server-side cache and regenerate insights. Expensive — avoid polling.
          schema: { type: boolean, default: false }
        - name: cached_only
          in: query
          required: false
          description: Return only already-cached results; never trigger a fresh generation. Use for fast UI reads.
          schema: { type: boolean, default: false }
        - name: environment
          in: query
          required: false
          description: "Environment: `0` = sandbox, `1` = production."
          schema: { type: integer, enum: [0, 1], default: 1 }
      responses:
        '200':
          description: Insights payload.
          headers:
            Cache-Control: { schema: { type: string, example: "no-cache" } }
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4AnalyticsInsights'
              example:
                object: analytics_insights
                url: /v4/analytics/insights
                generated_at: "2026-04-21T13:05:05+00:00"
                period_days: 30
                health: critical
                health_score: 8
                is_cached: true
                is_stale: false
                summary: >-
                  The app is acquiring users at a modest pace (1,745 this period, +4.4%),
                  but there is a complete absence of monetization activity.
                insights:
                  - type: critical
                    metric: mrr
                    title: Zero Revenue Across Both Periods
                    body: MRR, Sales and Proceeds are $0 in both the current and previous 30-day periods.
                    action: Audit your in-app purchase configuration in the App Store / Google Play console.
                  - type: positive
                    metric: new_users
                    title: New User Acquisition Growing Steadily
                    body: New users grew from 1,672 to 1,745 (+4.4%) period-over-period.
                    action: Preserve and document current acquisition channels so this momentum is not disrupted.
        '400': {description: Invalid request parameters, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '401': {description: Unauthorized, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '403': {description: Insufficient permissions, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '404': {description: Not found, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '429': {description: Too many requests, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '500': {description: Internal error, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '502': {description: Upstream service failure, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}
        '504': {description: Upstream timeout, content: {application/json: {schema: {$ref: '#/components/schemas/V4Error'}}}}

  /screens:
    get:
      operationId: v4ListScreens
      summary: List screens
      deprecated: true
      description: "Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Returns a paginated list of screens for the authenticated project.\n\
        Screens are ordered by creation date (newest first) and include every screen\
        \ visible in the Qonversion dashboard (statuses `draft`, `published`, `modified`,\
        \ and historical `legacy`).\n\
        Supports cursor-based pagination via `limit` and `starting_after`.\n\n\
        "
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: limit
        in: query
        description: Maximum number of screens to return. Min 1, max 100.
        required: false
        schema:
          type: integer
          minimum: 1
          maximum: 100
          default: 20
      - name: starting_after
        in: query
        description: "Cursor for pagination. Pass the `id` of the last screen from\
          \ the previous page to fetch the next page.\n\n\
          If the cursor does not match a known screen id (for example the screen\
          \ was deleted between calls), pagination restarts from the top of the list\
          \ and the response carries an `X-Qon-Pagination-Restarted: true` header\
          \ so clients can detect the restart and decide whether to deduplicate.\n\n\
          "
        required: false
        schema:
          type: string
          maxLength: 256
      responses:
        '200':
          description: A paginated list of screens.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
            X-Qon-Pagination-Restarted:
              description: "Present with value `true` only when `starting_after` did\
                \ not match a known screen id and pagination silently restarted from\
                \ the top of the list."
              schema:
                type: string
                example: 'true'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ScreenList'
              examples:
                with_results:
                  summary: Page with results
                  value:
                    object: list
                    url: /v4/screens
                    data:
                    - object: screen
                      id: scr_abc123
                      url: /v4/screens/scr_abc123
                      name: Onboarding Paywall
                      status: published
                      type: paywall
                      context_key: onboarding_main
                      is_web: false
                      created_at: '2025-09-15T12:30:00Z'
                      updated_at: '2025-11-03T10:26:40Z'
                    has_more: false
                empty:
                  summary: Empty collection
                  value:
                    object: list
                    url: /v4/screens
                    data: []
                    has_more: false
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4CreateScreen
      summary: Create a screen
      deprecated: true
      description: "Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Creates a new screen skeleton for the authenticated project.\n\n\
        The created screen has no visual content yet — it is a placeholder you then\
        \ open in the Qonversion dashboard to lay out components, upload media, and\
        \ add localisations. Render-time fields (`background`, `default_lang`, `configs`,\
        \ `content`, `prod_key`, `sandbox_key`) are populated by the dashboard editor,\
        \ not by this endpoint.\n\n\
        Returns `201 Created` with the newly created `V4Screen` and a `Location`\
        \ header pointing at `GET /v4/screens/{screen_id}`.\n\n\
        "
      tags:
      - Screens
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ScreenCreate'
            example:
              name: Summer Paywall
      responses:
        '201':
          description: Screen created successfully.
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the created screen.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Screen'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /screens/analytics/overview:
    get:
      operationId: v4GetScreensAnalyticsOverview
      summary: Get screens analytics overview
      deprecated: true
      description: 'Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Returns aggregated analytics metrics across all screens for the authenticated project.

        Supports optional time-range, environment, currency, and unit filters.

        '
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: from
        in: query
        description: Start of the analytics period (ISO 8601 date or datetime).
        required: false
        schema:
          type: string
          example: '2025-01-01'
      - name: to
        in: query
        description: End of the analytics period (ISO 8601 date or datetime).
        required: false
        schema:
          type: string
          example: '2025-12-31'
      - name: environment
        in: query
        description: Filter by environment.
        required: false
        schema:
          type: string
          x-extensible-enum:
          - production
          - sandbox
      - name: currency
        in: query
        description: Currency code for revenue metrics (ISO 4217).
        required: false
        schema:
          type: string
          example: USD
      - name: unit
        in: query
        description: Time unit for grouping analytics data.
        required: false
        schema:
          type: string
          x-extensible-enum:
          - day
          - week
          - month
      responses:
        '200':
          description: Aggregated analytics overview across all screens.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Analytics overview object wrapped in the standard v4 envelope (object, url, data). KPI values are scalars with previous-period comparison and sparkline arrays.
                additionalProperties: true
              example:
                object: screens_analytics_overview
                url: /v4/screens/analytics/overview
                data:
                  kpis:
                    views:
                      value: 12540
                      prev: 11820
                      sparkline: [1500, 1620, 1710, 1840, 1900, 1950, 2020]
                    impressions:
                      value: 12540
                      prev: 11820
                      sparkline: [1500, 1620, 1710, 1840, 1900, 1950, 2020]
                    trials:
                      value: 820
                      prev: 760
                      sparkline: [95, 104, 112, 118, 125, 130, 136]
                    purchases:
                      value: 215
                      prev: 198
                      sparkline: [24, 27, 29, 31, 33, 35, 36]
                    revenue:
                      value: 4320.50
                      prev: 3980.10
                      sparkline: [480, 520, 560, 610, 640, 680, 830.50]
                    conversion:
                      value: 0.0171
                      prev: 0.0168
                      sparkline: [0.016, 0.016, 0.017, 0.017, 0.017, 0.018, 0.018]
                  period:
                    from: 1776413711
                    to: 1777018511
                    unit: day
        '400':
          description: Invalid request parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /screens/{screen_id}:
    get:
      operationId: v4GetScreen
      summary: Get a screen
      deprecated: true
      description: "Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Returns a single screen by ID.\n\n\
        By default the response is the full `V4Screen`, including the render-time\
        \ fields (`background`, `default_lang`, `configs`, `content`, `prod_key`,\
        \ `sandbox_key`, `used`) an SDK needs to display a paywall.\n\n\
        Pass `render=false` to receive the lean `V4ScreenSummary` instead — the\
        \ same shape returned on `GET /v4/screens`. Useful when you only need\
        \ metadata and want to avoid fetching the render payload, which can be\
        \ several kilobytes per screen.\n"
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: screen_id
        in: path
        required: true
        description: Screen identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: scr_abc123
      - name: render
        in: query
        required: false
        description: "Whether to include render-time fields (`background`, `default_lang`,\
          \ `configs`, `content`, `prod_key`, `sandbox_key`, `used`) in the response.\n\
          * `true` (default) — return the full `V4Screen`.\n\
          * `false` — return the lean `V4ScreenSummary`.\n"
        schema:
          type: boolean
          default: true
        example: false
      responses:
        '200':
          description: "Screen details. The response is a `V4Screen` when `render=true`\
            \ (default) or a `V4ScreenSummary` when `render=false`."
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                oneOf:
                - $ref: '#/components/schemas/V4Screen'
                - $ref: '#/components/schemas/V4ScreenSummary'
        '400':
          description: Invalid screen_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Screen not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    put:
      operationId: v4UpdateScreen
      summary: Update a screen
      deprecated: true
      description: Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Updates a screen's name. All mutable fields must be provided.
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: screen_id
        in: path
        required: true
        description: Screen identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: scr_abc123
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ScreenUpdate'
            example:
              name: Updated Paywall Name
      responses:
        '200':
          description: Updated screen.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Screen'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Screen not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '422':
          description: Unprocessable entity
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    delete:
      operationId: v4DeleteScreen
      summary: Delete a screen
      deprecated: true
      description: Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Permanently deletes a screen by ID.
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: screen_id
        in: path
        required: true
        description: Screen identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: scr_abc123
      responses:
        '204':
          description: Screen deleted successfully. No response body.
        '400':
          description: Invalid screen_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Screen not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /screens/{screen_id}/publish:
    post:
      operationId: v4PublishScreen
      summary: Publish a screen
      deprecated: true
      description: 'Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Publishes a screen, setting its status to `published`.

        No request body is required.

        '
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: screen_id
        in: path
        required: true
        description: Screen identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: scr_abc123
      responses:
        '200':
          description: Published screen.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Screen'
        '400':
          description: Invalid screen_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Screen not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /screens/{screen_id}/copy:
    post:
      operationId: v4CopyScreen
      summary: Duplicate a screen
      deprecated: true
      description: 'Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Creates a copy (duplicate) of an existing screen.

        The duplicated screen is returned with a new `id` and status `draft`.

        No request body is required.

        '
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: screen_id
        in: path
        required: true
        description: Screen identifier to duplicate.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: scr_abc123
      responses:
        '201':
          description: Duplicated screen created successfully.
          headers:
            Location:
              schema:
                type: string
              description: Canonical URL of the newly created duplicate screen.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Screen'
        '400':
          description: Invalid screen_id
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Screen not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /screens/{screen_id}/analytics:
    get:
      operationId: v4GetScreenAnalytics
      summary: Get per-screen analytics
      deprecated: true
      description: 'Deprecated — the Screens product surface has been removed; this API remains available for existing integrations only. Returns analytics metrics for a single screen.

        Supports optional time-range, environment, currency, and unit filters.

        '
      tags:
      - Screens
      security:
      - secretAuth: []
      parameters:
      - name: screen_id
        in: path
        required: true
        description: Screen identifier.
        schema:
          type: string
          maxLength: 256
          pattern: ^[a-zA-Z0-9._-]+$
        example: scr_abc123
      - name: from
        in: query
        description: Start of the analytics period (ISO 8601 date or datetime).
        required: false
        schema:
          type: string
          example: '2025-01-01'
      - name: to
        in: query
        description: End of the analytics period (ISO 8601 date or datetime).
        required: false
        schema:
          type: string
          example: '2025-12-31'
      - name: environment
        in: query
        description: Filter by environment.
        required: false
        schema:
          type: string
          x-extensible-enum:
          - production
          - sandbox
      - name: currency
        in: query
        description: Currency code for revenue metrics (ISO 4217).
        required: false
        schema:
          type: string
          example: USD
      - name: unit
        in: query
        description: Time unit for grouping analytics data.
        required: false
        schema:
          type: string
          x-extensible-enum:
          - day
          - week
          - month
      responses:
        '200':
          description: Analytics data for the specified screen.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-cache
          content:
            application/json:
              schema:
                type: object
                description: Analytics object wrapped in the standard v4 envelope (object, url, data). `data.kpis` uses snake_case keys (conversion_rate, cancel_rate) and each KPI carries value, previous-period value, and a sparkline.
                additionalProperties: true
              example:
                object: screen_analytics
                url: /v4/screens/scr_abc123/analytics
                data:
                  kpis:
                    purchases:
                      value: 42
                      prev: 38
                      sparkline: [5, 6, 5, 7, 6, 6, 7]
                    trials:
                      value: 215
                      prev: 198
                      sparkline: [28, 31, 30, 32, 31, 31, 32]
                    revenue:
                      value: 840.15
                      prev: 760.40
                      sparkline: [105, 118, 112, 128, 120, 122, 135.15]
                    refunds:
                      value: 2
                      prev: 1
                      sparkline: [0, 0, 1, 0, 0, 0, 1]
                    conversion_rate:
                      value: 0.195
                      prev: 0.192
                      sparkline: [0.18, 0.19, 0.20, 0.19, 0.20, 0.20, 0.21]
                    cancel_rate:
                      value: 0.045
                      prev: 0.052
                      sparkline: [0.06, 0.05, 0.05, 0.04, 0.04, 0.04, 0.04]
                  period:
                    from: 1776447033
                    to: 1777051833
                    unit: day
                  screen:
                    uid: scr_abc123
                    name: Premium paywall
                    status: published
                    type: paywall
        '400':
          description: Invalid screen_id or parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Screen not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /project-settings:
    get:
      operationId: v4GetProjectSettings
      summary: Get project settings
      description: 'Returns the settings for the authenticated project, including API keys,

        proxy URLs, and project name.

        '
      tags:
      - Project Settings
      security:
      - secretAuth: []
      responses:
        '200':
          description: Project settings.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ProjectSettings'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Project not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded.
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    patch:
      operationId: v4UpdateProjectSettings
      summary: Update project settings
      description: 'Partially updates the project settings. Only provided fields are changed.

        '
      tags:
      - Project Settings
      security:
      - secretAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/V4ProjectSettingsUpdate'
      responses:
        '200':
          description: Updated project settings.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4ProjectSettings'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Project not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded.
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /project-settings/regenerate-secret:
    post:
      operationId: v4RegenerateProjectSecret
      summary: Regenerate project secret key
      description: 'Regenerates the project''s secret key. The old key is revoked; clients
        may see a short grace period (seconds) while internal caches expire.

        This is a destructive operation.


        Idempotency is intentionally NOT supported: caching a newly generated

        secret in a shared replay cache would leak credentials. Each call

        produces a fresh secret — clients must treat every request as unique.

        '
      tags:
      - Project Settings
      security:
      - secretAuth: []
      responses:
        '200':
          description: Regenerated secret key.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4RegenerateSecretResponse'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Project not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded.
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
  /project-settings/stores/{platform}:
    get:
      operationId: v4GetProjectStoreConfig
      summary: Get store configuration
      description: 'Returns the store configuration for the specified platform.

        Sensitive fields (private keys, service account credentials) are masked

        with boolean flags (has_connect_private_key, has_service_account_key, etc.).

        '
      tags:
      - Project Settings
      security:
      - secretAuth: []
      parameters:
      - name: platform
        in: path
        required: true
        description: Store platform identifier.
        schema:
          type: string
          enum:
          - apple
          - google
      responses:
        '200':
          description: Store configuration for the platform.
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/json:
              schema:
                oneOf:
                - $ref: '#/components/schemas/V4AppleStoreConfig'
                - $ref: '#/components/schemas/V4GoogleStoreConfig'
                discriminator:
                  propertyName: platform
                  mapping:
                    apple: '#/components/schemas/V4AppleStoreConfig'
                    google: '#/components/schemas/V4GoogleStoreConfig'
        '400':
          description: Invalid platform
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Store config not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded.
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
    post:
      operationId: v4UpdateProjectStoreConfig
      summary: Update store configuration
      description: 'Updates the store configuration for the specified platform.

        For Apple: if private keys are not provided, existing values are preserved.

        For Google: if service account key is not provided, existing value is preserved.

        '
      tags:
      - Project Settings
      security:
      - secretAuth: []
      parameters:
      - name: platform
        in: path
        required: true
        description: Store platform identifier.
        schema:
          type: string
          enum:
          - apple
          - google
      - name: Idempotency-Key
        in: header
        description: Unique key to ensure idempotent execution.
        required: false
        schema:
          type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
              - $ref: '#/components/schemas/V4AppleStoreConfigUpdate'
              - $ref: '#/components/schemas/V4GoogleStoreConfigUpdate'
      responses:
        '200':
          description: Updated store configuration (with sensitive fields masked).
          headers:
            Cache-Control:
              schema:
                type: string
                example: no-store
          content:
            application/json:
              schema:
                oneOf:
                - $ref: '#/components/schemas/V4AppleStoreConfig'
                - $ref: '#/components/schemas/V4GoogleStoreConfig'
        '400':
          description: Validation error or invalid platform
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '403':
          description: Insufficient permissions
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '404':
          description: Store config not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '415':
          description: Unsupported Content-Type
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '429':
          description: Rate limit exceeded.
          headers:
            Retry-After:
              schema:
                type: integer
                example: 60
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '502':
          description: Upstream service failure
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
        '504':
          description: Upstream timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/V4Error'
components:
  securitySchemes:
    secretAuth:
      type: http
      scheme: bearer
      bearerFormat: sk_…
      description: Bearer authentication using the project **Secret Key** (prefixed with `sk_`, or `test_sk_`
        for sandbox). All v4 public endpoints require the Secret Key — see [Authentication](/reference/v4/authentication).
        Never expose the Secret Key in client-side code.
  responses:
    TooManyRequests:
      description: Too many requests, rate limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ResponseError'
  schemas:
    V4ProjectSettings:
      type: object
      required:
      - object
      - url
      - project_name
      - access_token
      - api_key
      - secret_key
      properties:
        object:
          type: string
          enum:
          - project_settings
        url:
          type: string
          example: /v4/project-settings
        project_name:
          type: string
          description: Project display name.
          example: My App
        access_token:
          type: string
          description: Project access token.
        api_key:
          type: string
          description: Project API key.
        secret_key:
          type: string
          description: Project secret key.
        proxy_url:
          type: string
          nullable: true
          description: Custom proxy URL.
        rtdn_proxy_url:
          type: string
          nullable: true
          description: RTDN proxy URL.
    V4ProjectSettingsUpdate:
      type: object
      properties:
        project_name:
          type: string
          description: New project display name.
        proxy_url:
          type: string
          nullable: true
          description: Custom proxy URL. Set to null to clear.
        rtdn_proxy_url:
          type: string
          nullable: true
          description: RTDN proxy URL. Set to null to clear.
    V4RegenerateSecretResponse:
      type: object
      required:
      - object
      - url
      - secret_key
      properties:
        object:
          type: string
          enum:
          - project_settings
        url:
          type: string
          example: /v4/project-settings
        secret_key:
          type: string
          description: Newly regenerated secret key.
    V4AppleStoreConfig:
      type: object
      required:
      - object
      - url
      - platform
      - has_shared_secret
      - has_connect_private_key
      - has_iap_private_key
      properties:
        object:
          type: string
          enum:
          - store_config
        url:
          type: string
          example: /v4/project-settings/stores/apple
        platform:
          type: string
          enum:
          - apple
        has_shared_secret:
          type: boolean
          description: Whether the App-Specific Shared Secret is set. The value itself is never returned.
        app_id:
          type: string
          nullable: true
          description: App Store app ID.
        bundle_id:
          type: string
          nullable: true
          description: iOS bundle identifier.
        connect_key_identifier:
          type: string
          nullable: true
          description: App Store Connect API key identifier.
        has_connect_private_key:
          type: boolean
          description: Whether the ASC private key is set.
        connect_issuer_id:
          type: string
          nullable: true
          description: App Store Connect API issuer ID.
        iap_key_identifier:
          type: string
          nullable: true
          description: In-App Purchase API key identifier.
        has_iap_private_key:
          type: boolean
          description: Whether the IAP private key is set.
        iap_issuer_id:
          type: string
          nullable: true
          description: In-App Purchase API issuer ID.
    V4GoogleStoreConfig:
      type: object
      required:
      - object
      - url
      - platform
      - has_service_account_key
      - is_rtdn_validated
      properties:
        object:
          type: string
          enum:
          - store_config
        url:
          type: string
          example: /v4/project-settings/stores/google
        platform:
          type: string
          enum:
          - google
        package_name:
          type: string
          nullable: true
          description: Google Play package name.
        has_service_account_key:
          type: boolean
          description: Whether the Google service account key is set.
        bundle_id:
          type: string
          nullable: true
          description: Android bundle identifier.
        rtdn_topic:
          type: string
          nullable: true
          description: RTDN subscription topic.
        is_rtdn_validated:
          type: boolean
          description: Whether RTDN is validated.
        rtdn_last_message_at:
          type: string
          nullable: true
          description: ISO 8601 timestamp of last RTDN message. Null if never received.
          example: '2026-01-15T10:00:00Z'
    V4AppleStoreConfigUpdate:
      type: object
      properties:
        shared_secret:
          type: string
          description: App-Specific Shared Secret.
        app_id:
          type: string
          description: App Store app ID.
        bundle_id:
          type: string
          description: iOS bundle identifier.
        connect_key_identifier:
          type: string
          description: App Store Connect API key identifier.
        connect_private_key:
          type: string
          description: ASC private key (PEM format). Omit to preserve existing value.
        connect_issuer_id:
          type: string
          description: App Store Connect API issuer ID.
        iap_key_identifier:
          type: string
          description: In-App Purchase API key identifier.
        iap_private_key:
          type: string
          description: IAP private key (PEM format). Omit to preserve existing value.
        iap_issuer_id:
          type: string
          description: In-App Purchase API issuer ID.
    V4GoogleStoreConfigUpdate:
      type: object
      properties:
        package_name:
          type: string
          description: Google Play package name.
        service_account_key:
          type: string
          description: Google service account key JSON. Omit to preserve existing value.
        bundle_id:
          type: string
          description: Android bundle identifier.
    V4ScreenSummary:
      type: object
      required:
      - object
      - id
      - url
      - name
      - status
      - is_web
      - created_at
      - updated_at
      description: |
        Lean screen representation used on list endpoints. Omits render-time
        fields (`configs`, `content`, `prod_key`, `sandbox_key`, `used`,
        etc.) to keep paginated walks cheap. Fetch `V4Screen` via
        `GET /v4/screens/{screen_id}` for the full render payload.
      properties:
        object:
          type: string
          enum:
          - screen
        id:
          type: string
          example: scr_abc123
        url:
          type: string
          example: /v4/screens/scr_abc123
        name:
          type: string
          example: Onboarding Paywall
        status:
          type: string
          x-extensible-enum:
          - legacy
          - draft
          - published
          - modified
          example: published
        type:
          type: string
          nullable: true
          x-extensible-enum:
          - paywall
          - web_flow
          - onboarding
        context_key:
          type: string
          nullable: true
        is_web:
          type: boolean
          default: false
        created_at:
          type: string
          format: date-time
          example: '2025-09-15T12:30:00Z'
        updated_at:
          type: string
          format: date-time
          example: '2025-11-03T10:26:40Z'
    V4Screen:
      description: |
        Full screen representation returned by `GET /v4/screens/{screen_id}`.
        Extends `V4ScreenSummary` with the render-time fields an SDK needs
        to initialise and display a paywall (DEV-777).
      allOf:
      - $ref: '#/components/schemas/V4ScreenSummary'
      - type: object
        required:
        - background
        - default_lang
        - configs
        - prod_key
        - sandbox_key
        - content
        - used
        properties:
          background:
            type: string
            nullable: true
            description: CSS background for the paywall root element.
          default_lang:
            type: string
            nullable: true
            description: |
              Default localisation key. When the SDK can't match the user's
              locale it falls back to this language.
            example: en
          configs:
            description: |
              Base screen configuration. Opaque JSON blob consumed by the
              Qonversion SDK — shape is defined by the no-code editor and
              MAY evolve without a version bump.
          prod_key:
            type: string
            nullable: true
            description: |
              SDK integration key used in production builds. Load-bearing —
              the SDK cannot render the screen without it.
          sandbox_key:
            type: string
            nullable: true
            description: SDK integration key for sandbox / test builds.
          content:
            description: |
              Localised screen content keyed by language code
              (e.g. `{ "en": {...}, "ru": {...} }`). Each value is an
              opaque JSON blob consumed by the SDK renderer.
          used:
            type: array
            items:
              type: string
            description: UIDs of triggers currently targeting this screen.
    V4ScreenList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/screens
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4ScreenSummary'
        has_more:
          type: boolean
          description: Whether more pages are available.
        next_cursor:
          type: string
          nullable: true
          description: Present only when has_more is true. Pass as starting_after for the next page.
    V4ScreenCreate:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Human-readable name for the new screen. Must be 1–256 characters.
          minLength: 1
          maxLength: 256
          example: Summer Paywall
    V4ScreenUpdate:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: New name for the screen. Must be 1–256 characters.
          minLength: 1
          maxLength: 256
          example: Updated Paywall Name
    V4ProductList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/products
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4Product'
        has_more:
          type: boolean
        next_cursor:
          type: string
          description: Present only when has_more is true.
    V4Product:
      type: object
      required:
      - object
      - id
      - url
      - created_at
      - updated_at
      properties:
        object:
          type: string
          enum:
          - product
        id:
          type: string
          description: Unique product identifier.
          maxLength: 255
          example: premium_monthly
        url:
          type: string
          description: Canonical API path.
          example: /v4/products/premium_monthly
        type:
          type: string
          nullable: true
          description: 'Product type (open enum). Values mirror the Qonversion dashboard
            labels: `subscription_with_promo` (Subscription With Promo Period),
            `subscription` (Regular Subscription), `consumable`, `lifetime`.'
          x-extensible-enum:
          - subscription_with_promo
          - subscription
          - consumable
          - lifetime
        duration:
          type: string
          nullable: true
          description: 'Subscription duration in ISO 8601 period format (open enum).
            Only products of type `subscription_with_promo` or `subscription` may
            have a duration; `consumable` and `lifetime` are always null.'
          x-extensible-enum:
          - P1W
          - P1M
          - P3M
          - P6M
          - P1Y
        apple_product_id:
          type: string
          nullable: true
          description: Apple App Store product identifier.
        google_product_id:
          type: string
          nullable: true
          description: Google Play product identifier.
        google_base_plan_id:
          type: string
          nullable: true
          description: Google Play base plan identifier.
        stripe_product_id:
          type: string
          nullable: true
          description: Stripe product identifier.
        created_at:
          type: string
          format: date-time
          description: Creation timestamp (ISO 8601 UTC).
          example: '2025-09-15T12:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp (ISO 8601 UTC).
          example: '2025-11-03T10:26:40Z'
    V4ProductCreate:
      type: object
      required:
      - id
      properties:
        id:
          type: string
          description: Unique product identifier.
          maxLength: 255
          example: premium_monthly
        type:
          type: string
          nullable: true
          description: 'Product type. Mirrors dashboard labels.'
          x-extensible-enum:
          - subscription_with_promo
          - subscription
          - consumable
          - lifetime
        duration:
          type: string
          nullable: true
          description: 'Subscription duration in ISO 8601 format. Allowed only for
            `subscription_with_promo` or `subscription`.'
          x-extensible-enum:
          - P1W
          - P1M
          - P3M
          - P6M
          - P1Y
        apple_product_id:
          type: string
          nullable: true
        google_product_id:
          type: string
          nullable: true
        google_base_plan_id:
          type: string
          nullable: true
        stripe_product_id:
          type: string
          nullable: true
    V4Automation:
      type: object
      required:
      - object
      - id
      - url
      - name
      - caption
      - status
      - data
      properties:
        object:
          type: string
          enum:
          - automation
          description: Always "automation".
        id:
          type: string
          description: Unique automation identifier.
          example: auto-abc123
        url:
          type: string
          description: Canonical API path for this automation.
          example: /v4/automations/auto-abc123
        name:
          type: string
          description: Human-readable name of the automation.
          example: Welcome Flow
        caption:
          type: string
          description: Optional description of the automation.
          example: Sends a welcome message to new users
        status:
          type: string
          description: |
            Lifecycle status of the automation. `paused` is set via
            `PATCH /automations/{id}/status` to temporarily stop an active
            automation without deleting it. `unknown` is returned as a
            forward-compatibility fallback and should not be written.
          x-extensible-enum:
          - active
          - inactive
          - paused
          - unknown
          example: active
        data:
          $ref: '#/components/schemas/V4AutomationData'
    V4AutomationData:
      type: object
      required:
      - initiators
      - actions
      - segments
      description: |
        Automation configuration. Push and event resources are dashboard-only;
        this object references them by uid.
      properties:
        type:
          type: string
          nullable: true
          description: Derived on read from initiator types. Ignored on write.
          x-extensible-enum:
          - event
          example: event
        platform:
          type: string
          nullable: true
          description: Platform filter for the automation. `null` for all platforms.
          enum:
          - iOS
          - Android
          - null
          example: iOS
        initiators:
          type: array
          minItems: 1
          description: One or more event initiators that trigger the automation.
          items:
            type: object
            required:
            - uid
            - type
            properties:
              uid:
                type: string
                description: Dashboard event id (numeric string).
                example: "2"
              type:
                type: string
                enum:
                - event
                example: event
        actions:
          type: object
          description: Actions to perform when the automation fires. At least one of `push` or `screen` must be present.
          properties:
            push:
              type: string
              nullable: true
              description: Push notification uid (created in the dashboard).
              example: nCRUE7SW
            screen:
              type: string
              nullable: true
              description: Screen uid (see `/v4/screens`).
              example: qUY7JXgF
        segments:
          type: string
          nullable: true
          description: Segment uid to target; `null` runs for all users.
          example: A0SzRbM2vmmwixbpQxtI
    V4AutomationList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/automations
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4Automation'
        has_more:
          type: boolean
          description: Whether more pages are available.
        next_cursor:
          type: string
          nullable: true
          description: Present only when has_more is true. Pass as starting_after for the next page.
    V4AutomationCreate:
      type: object
      required:
      - name
      - status
      - data
      properties:
        name:
          type: string
          description: Human-readable name for the automation. Must be 1–255 characters.
          minLength: 1
          maxLength: 255
          example: Welcome Flow
        caption:
          type: string
          description: Optional description. Maximum 1024 characters.
          maxLength: 1024
          example: Sends a welcome message to new users
        status:
          type: string
          description: Initial status of the automation.
          enum:
          - active
          - inactive
          - paused
          example: active
        data:
          $ref: '#/components/schemas/V4AutomationData'
    V4AutomationUpdate:
      type: object
      required:
      - name
      - status
      - data
      properties:
        name:
          type: string
          description: Human-readable name for the automation. Must be 1–255 characters.
          minLength: 1
          maxLength: 255
          example: Updated Welcome Flow
        caption:
          type: string
          description: Optional description. Maximum 1024 characters.
          maxLength: 1024
          example: Updated description
        status:
          type: string
          description: Status of the automation.
          enum:
          - active
          - inactive
          - paused
          example: inactive
        data:
          $ref: '#/components/schemas/V4AutomationData'
    V4AutomationStatusPatch:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          description: Desired status for the automation.
          enum:
          - active
          - inactive
          - paused
          example: paused
    V4ProductPatch:
      type: object
      properties:
        type:
          type: string
          nullable: true
          description: 'Product type. Mirrors dashboard labels.'
          x-extensible-enum:
          - subscription_with_promo
          - subscription
          - consumable
          - lifetime
        duration:
          type: string
          nullable: true
          description: 'Subscription duration in ISO 8601 format. Allowed only for
            `subscription_with_promo` or `subscription`.'
          x-extensible-enum:
          - P1W
          - P1M
          - P3M
          - P6M
          - P1Y
        apple_product_id:
          type: string
          nullable: true
        google_product_id:
          type: string
          nullable: true
        google_base_plan_id:
          type: string
          nullable: true
        stripe_product_id:
          type: string
          nullable: true
    V4EntitlementDefinition:
      type: object
      required:
      - object
      - id
      - url
      - created_at
      - updated_at
      properties:
        object:
          type: string
          enum:
          - entitlement
        id:
          type: string
          description: Unique entitlement identifier.
          example: premium
        url:
          type: string
          description: Canonical API path.
          example: /v4/entitlements/premium
        description:
          type: string
          nullable: true
          description: Human-readable description of the entitlement.
          example: Premium access entitlement
        product_ids:
          type: array
          nullable: true
          description: List of product IDs associated with this entitlement.
          items:
            type: string
          example:
          - premium_monthly
          - premium_annual
        created_at:
          type: string
          format: date-time
          description: Creation timestamp (ISO 8601 UTC).
          example: '2025-09-15T12:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp (ISO 8601 UTC).
          example: '2025-11-03T10:26:40Z'
    V4EntitlementDefinitionCreate:
      type: object
      required:
      - id
      properties:
        id:
          type: string
          description: Unique entitlement identifier.
          example: premium
        description:
          type: string
          nullable: true
          description: Human-readable description of the entitlement.
          example: Premium access entitlement
        product_ids:
          type: array
          nullable: true
          description: List of product IDs to associate with this entitlement.
          items:
            type: string
          example:
          - premium_monthly
          - premium_annual
    V4EntitlementDefinitionList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/entitlements
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4EntitlementDefinition'
        has_more:
          type: boolean
        next_cursor:
          type: string
          description: Present only when has_more is true.
    V4EntitlementDefinitionPatch:
      type: object
      properties:
        description:
          type: string
          nullable: true
          description: Human-readable description of the entitlement.
          example: Updated premium access entitlement
        product_ids:
          type: array
          nullable: true
          description: List of product IDs to associate with this entitlement.
          items:
            type: string
          example:
          - premium_monthly
          - premium_annual
    V4GrantEntitlementRequest:
      type: object
      required:
      - entitlement_id
      properties:
        entitlement_id:
          type: string
          description: Identifier of the entitlement definition to grant.
          example: premium
        expires_at:
          type: integer
          format: int64
          description: 'Unix timestamp (seconds) when the entitlement expires. Use
            `0` (or omit the field) to grant the entitlement with no expiry. Negative
            values and past timestamps are rejected with 400.'
          default: 0
          example: 1767225600
    V4UserEntitlement:
      type: object
      required:
      - object
      - id
      - url
      - is_active
      - source
      properties:
        object:
          type: string
          enum:
          - user_entitlement
        id:
          type: string
          description: Unique entitlement identifier.
          example: premium
        url:
          type: string
          description: Canonical API path.
          example: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/entitlements/premium
        is_active:
          type: boolean
          description: Whether the entitlement is currently active.
        source:
          type: string
          description: Source of the entitlement grant (open enum).
          x-extensible-enum:
          - appstore
          - playstore
          - stripe
          - manual
          - unknown
        started_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the entitlement became active (ISO 8601 UTC).
          example: '2025-09-15T12:30:00Z'
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: Timestamp when the entitlement expires (ISO 8601 UTC). Null if no expiry.
          example: '2026-09-15T12:30:00Z'
        product:
          nullable: true
          description: Product associated with this entitlement, if any.
          $ref: '#/components/schemas/V4UserEntitlementProduct'
    V4UserEntitlementList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/entitlements
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4UserEntitlement'
        has_more:
          type: boolean
        next_cursor:
          type: string
          description: Present only when has_more is true.
    V4UserEntitlementProduct:
      type: object
      required:
      - product_id
      properties:
        product_id:
          type: string
          description: Product identifier.
          example: premium_monthly
        subscription:
          nullable: true
          description: Subscription details, if the product is a subscription.
          $ref: '#/components/schemas/V4UserEntitlementSubscription'
    V4UserEntitlementSubscription:
      type: object
      required:
      - renew_state
      - current_period_type
      properties:
        renew_state:
          type: string
          description: 'Current renewal state. Subscription is omitted entirely for
            non-renewable products.'
          enum:
          - will_renew
          - canceled
          - billing_issue
        current_period_type:
          type: string
          description: Current billing period type.
          enum:
          - normal
          - trial
          - intro
    V4Integration:
      type: object
      description: A single integration record. Credentials (API keys, webhook secrets) are configured out-of-band after creation and are not exposed in this shape.
      required:
      - object
      - id
      - url
      - title
      - integration
      - target_platform
      - active
      - created_at
      - updated_at
      - last_delivery_at
      - last_error_at
      - last_error_message
      - delivery_error_count
      properties:
        object:
          type: string
          example: integration
        id:
          type: string
          description: Integration identifier. Stable for the lifetime of the record (soft-deleted records keep their ID).
          example: gNl6hyM6
        url:
          type: string
          description: Canonical API path.
          example: /v4/integrations/gNl6hyM6
        title:
          type: string
          description: Caller-supplied display title.
          example: Amplitude — Production iOS
        integration:
          type: string
          description: Provider display title (not the lowercase slug used on create). Use for UI; for references in other requests use `id`.
          example: Amplitude
        target_platform:
          type: string
          description: Store the integration forwards events for. Case-sensitive.
          enum:
          - iOS
          - Android
          - Stripe
        active:
          type: integer
          description: |
            Integration state.
            - `0` — paused / draft (no events forwarded).
            - `1` — active (events forwarded).
            - `2` — error (delivery worker suspended the pipeline; inspect `last_error_message`/`last_error_at`). Cannot be set by callers.
          enum:
          - 0
          - 1
          - 2
        created_at:
          type: string
          format: date-time
          description: ISO 8601 creation timestamp.
          example: '2026-02-26T16:03:09Z'
        updated_at:
          type: string
          format: date-time
          description: ISO 8601 last-update timestamp.
          example: '2026-02-26T16:03:09Z'
        last_delivery_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 timestamp of the most recent successful delivery, or `null` if never delivered.
          example: '2026-04-22T10:12:33Z'
        last_error_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 timestamp of the most recent delivery failure, or `null`.
        last_error_message:
          type: string
          nullable: true
          description: Human-readable description of the most recent delivery failure, or `null`.
        delivery_error_count:
          type: integer
          description: Running count of delivery failures since the last successful delivery.
          minimum: 0
    V4IntegrationListResponse:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          example: list
        url:
          type: string
          example: /v4/integrations
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4Integration'
        has_more:
          type: boolean
          description: Always `false` — integrations are not paginated.
          example: false
    V4IntegrationCreateRequest:
      type: object
      required:
      - title
      - integration
      - target_platform
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 255
          description: Display title visible in the dashboard (1-255 chars).
          example: Amplitude — Production iOS
        integration:
          type: string
          description: |
            Provider slug. Call `GET /v4/integrations/meta` for the canonical catalog; the typical set includes
            `amplitude`, `appmetrica`, `facebook`, `firebase`, `mixpanel`, `posthog`, `segment`, `searchads`,
            `adjust`, `appsflyer`, `branch`, `kochava`, `singular`, `split_metrics`, `asapty`, `tenjin`,
            `amazon_s3`, `google_cloud_storage`, `slack`, `webhooks`, `braze`, `clevertap`, `mailchimp`,
            `onesignal`, `pushwoosh`.
          example: amplitude
        target_platform:
          type: string
          description: Store to forward events for. Case-sensitive.
          enum:
          - iOS
          - Android
          - Stripe
    V4ScheduledReport:
      type: object
      description: |
        A scheduled report configuration. Delivers an analytics snapshot to the
        listed destinations once per day at `send_at` UTC, covering the prior
        `included_range_days` days of data.
      required:
      - object
      - id
      - url
      - report_name
      - send_at
      - included_range_days
      - status
      - environment
      - runs
      - destinations
      - created_at
      - updated_at
      properties:
        object:
          type: string
          example: scheduled_report
        id:
          type: string
          description: Report identifier.
          example: wbRlfw1x
        url:
          type: string
          example: /v4/scheduled-reports/wbRlfw1x
        report_name:
          type: string
          description: Human-readable name, 1-255 chars.
          example: Daily Revenue
        send_at:
          type: string
          description: |
            UTC time-of-day for the daily delivery, `HH:MM` format, aligned to
            30-minute slots. Valid values range from `"00:00"` to `"23:30"`.
          example: "09:00"
        included_range_days:
          type: integer
          description: Coverage window in whole days — one of 1, 3, 7.
          enum: [1, 3, 7]
          example: 1
        status:
          type: string
          description: |
            `draft` — paused, no deliveries. `active` — enqueued for delivery
            at each `send_at`.
          enum: [draft, active]
          example: active
        environment:
          type: string
          enum: [sandbox, production]
          example: production
        runs:
          type: integer
          description: Number of deliveries completed so far.
          example: 14
        destinations:
          type: array
          items:
            $ref: '#/components/schemas/V4ScheduledReportDestination'
        created_at:
          type: string
          format: date-time
          example: "2026-04-23T11:44:36Z"
        updated_at:
          type: string
          format: date-time
          example: "2026-04-23T11:44:36Z"
    V4ScheduledReportDestination:
      type: object
      description: |
        Pointer to a pre-existing destination (created via the Integrations API).
        Use `GET /v4/scheduled-reports/destinations` to enumerate valid
        `{type, id}` pairs for a project.
      required:
      - type
      - id
      properties:
        type:
          type: string
          description: Destination kind. Currently always `target_integration`.
          example: target_integration
        id:
          type: string
          description: Destination identifier within the given type.
          example: int-wh-01
        label:
          type: string
          description: Human-readable label — present on read, ignored on write.
          example: "Webhooks: Release alerts"
    V4ScheduledReportCreateRequest:
      type: object
      required:
      - report_name
      - send_at
      - included_range_days
      - status
      - environment
      - destinations
      properties:
        report_name:
          type: string
          minLength: 1
          maxLength: 255
          example: Daily Revenue
        send_at:
          type: string
          description: UTC `HH:MM`, aligned to 30-min slots, `"00:00"` to `"23:30"`.
          example: "09:00"
        included_range_days:
          type: integer
          enum: [1, 3, 7]
          example: 1
        status:
          type: string
          enum: [draft, active]
          example: active
        environment:
          type: string
          enum: [sandbox, production]
          example: production
        destinations:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/V4ScheduledReportDestination'
    V4ScheduledReportUpdateRequest:
      type: object
      description: |
        Partial update — omit any field to keep its current value. At least one
        field must be supplied; an empty body returns `400 invalid_data`.
      properties:
        report_name:
          type: string
          minLength: 1
          maxLength: 255
        send_at:
          type: string
        included_range_days:
          type: integer
          enum: [1, 3, 7]
        status:
          type: string
          enum: [draft, active]
        environment:
          type: string
          enum: [sandbox, production]
        destinations:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/V4ScheduledReportDestination'
    V4IntegrationStatusRequest:
      type: object
      required:
      - status
      properties:
        status:
          type: integer
          description: |
            Desired state. Only `0` (paused) and `1` (active) are accepted; `2` (error) is set exclusively
            by the delivery worker. To remove an integration, use `DELETE /v4/integrations/{integration_id}`.
          enum:
          - 0
          - 1
          example: 1
    V4IntegrationsMetaResponse:
      type: object
      description: Catalog of supported provider slugs grouped by category.
      required:
      - object
      - url
      - data
      properties:
        object:
          type: string
          example: integrations_meta
        url:
          type: string
          example: /v4/integrations/meta
        data:
          type: array
          description: Provider categories (Analytics & Marketing, Attributions, Server, Email & Push Notifications).
          items:
            $ref: '#/components/schemas/V4IntegrationsMetaCategory'
    V4IntegrationsMetaCategory:
      type: object
      required:
      - title
      - items
      properties:
        title:
          type: string
          example: Analytics & Marketing
        items:
          type: array
          items:
            $ref: '#/components/schemas/V4IntegrationsMetaItem'
    V4IntegrationsMetaItem:
      type: object
      required:
      - title
      - slug
      - allowedStores
      properties:
        title:
          type: string
          description: Provider display title.
          example: Amplitude
        slug:
          type: string
          description: Provider slug. Use as `integration` in `POST /v4/integrations`.
          example: amplitude
        allowedStores:
          type: array
          description: Target platforms this provider supports. Subset of `iOS`, `Android`, `Stripe`.
          items:
            type: string
            enum:
            - iOS
            - Android
            - Stripe
    V4SegmentList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          example: list
        url:
          type: string
          example: /v4/segments
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4Segment'
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
    V4Offering:
      type: object
      required: [object, id, url, tag, product_ids, created_at, updated_at]
      properties:
        object: {type: string, enum: [offering], readOnly: true}
        id: {type: string, maxLength: 64, pattern: '^[a-zA-Z0-9._:\- ]+$', example: premium_monthly}
        url: {type: string, example: /v4/offerings/premium_monthly, readOnly: true}
        tag:
          type: integer
          format: int16
          nullable: true
          description: |
            Offering role within the project. `1` = main offering (`TAG_MAIN`)
            — exactly one offering per project has tag=1 at any time; promote
            via `POST /v4/offerings/{offering_id}/set-main`. `0` = regular
            offering that was demoted from main. `null` = regular offering
            that has never been tagged. Treat `0` and `null` as equivalent on
            read. The Offerings endpoints filter out experiment-variant
            offerings, but legacy rows could carry historical values other
            than `0`, `1`, or `null`, so the response field is intentionally
            not enum-restricted. Write schemas restrict accepted values
            server-side.
        product_ids:
          type: array
          items: {type: string, maxLength: 255, pattern: '^[a-zA-Z0-9._:\- ]+$'}
          description: Product UIDs that belong to this offering, in display order.
        created_at: {type: string, format: date-time, example: '2025-09-15T12:30:00Z', readOnly: true}
        updated_at: {type: string, format: date-time, example: '2025-11-03T10:26:40Z', readOnly: true}
    V4OfferingList:
      type: object
      required: [object, url, data, has_more]
      properties:
        object: {type: string, enum: [list]}
        url: {type: string, example: /v4/offerings}
        data:
          type: array
          items: {$ref: '#/components/schemas/V4Offering'}
        has_more: {type: boolean}
        next_cursor: {type: string, nullable: true, maxLength: 64, pattern: '^[a-zA-Z0-9._:\- ]+$'}
    V4OfferingCreate:
      type: object
      required: [id]
      properties:
        id:
          type: string
          maxLength: 64
          pattern: '^[a-zA-Z0-9._:\- ]+$'
          example: premium_monthly
          description: "1–64 chars of [a-zA-Z0-9._:\\- ]. Spaces and colons are accepted for parity with dashboard-created offerings. Immutable after create."
        tag:
          type: integer
          format: int16
          nullable: true
          enum: [0, null]
          description: |
            Only `0` and `null` (or omitting the field) are accepted on create.
            `tag=1` is rejected with 400 `cannot_set_main_directly` — promote
            via `POST /v4/offerings/{offering_id}/set-main` (atomic). The very
            first offering in a project is auto-promoted to main even if `tag`
            is omitted.
        product_ids:
          type: array
          maxItems: 100
          items: {type: string, maxLength: 255, pattern: '^[a-zA-Z0-9._:\- ]+$'}
          description: Product UIDs in display order. Each must already exist in this project, otherwise the request fails with 400 `product_not_in_project`. Up to 100 entries per request (`maxItems`).
    V4OfferingPatch:
      type: object
      description: |
        Partial update — only supplied fields are changed. `tag` is read-only
        via `PATCH`; promote an offering with `POST /offerings/{id}/set-main`
        (which atomically demotes the previous main in the same transaction).
      properties:
        product_ids:
          type: array
          maxItems: 100
          items: {type: string, maxLength: 255, pattern: '^[a-zA-Z0-9._:\- ]+$'}
          description: |
            Replaces the full list in the given order. Pass `[]` to clear all
            product associations. Omit the field entirely to leave existing
            associations unchanged. Each entry must already exist in this
            project, otherwise the request fails with 400 `product_not_in_project`.
            Up to 100 entries per request (`maxItems`).
    V4RemoteConfiguration:
      type: object
      description: |
        A named server-driven configuration. The read view returned by the list,
        create, update, and status endpoints. Only the single-configuration GET
        additionally embeds the inline `payload` values (see
        `V4RemoteConfigurationDetail`); these endpoints do not.
      required:
      - object
      - id
      - url
      - name
      - status
      - segment_percent
      - segmentation_conditions
      - priority
      - created_at
      - updated_at
      properties:
        object:
          type: string
          example: remote_configuration
        id:
          type: string
          description: Remote configuration identifier (UUID).
          example: 82a42dc2-76f6-46c2-b883-846acaf2070a
        url:
          type: string
          description: Canonical API path.
          example: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a
        name:
          type: string
          description: Display name.
          example: Onboarding copy
        status:
          type: string
          x-extensible-enum:
          - draft
          - active
          - archived
          description: |
            Lifecycle status. Only `active` configurations are served to the SDK.
            `archived` is terminal. Change via `PATCH /remote-configurations/{config_id}/status`.
          example: active
        context_key:
          type: string
          nullable: true
          description: Optional stable key the SDK uses to look up this configuration.
          example: onboarding_copy_v1
        segment_percent:
          type: number
          minimum: 0
          maximum: 100
          description: |
            Percentage (0–100) of the targeted audience that receives this
            configuration. `100` targets the whole audience.
          example: 100
        segmentation_conditions:
          type: array
          description: |
            Targeting rules that narrow the audience. Always present on read; `[]`
            when no conditions are set.
          items:
            $ref: '#/components/schemas/V4RemoteConfigurationSegmentationCondition'
        priority:
          type: integer
          nullable: true
          description: |
            Resolution priority when a user matches multiple configurations
            (read-only). `null` until the configuration is first activated.
          example: 1
        started_at:
          type: string
          format: date-time
          nullable: true
          description: When the configuration was activated. `null` while in `draft`.
          example: '2025-11-03T10:26:40Z'
        finished_at:
          type: string
          format: date-time
          nullable: true
          description: When the configuration was archived. `null` while not archived.
        last_applied_at:
          type: string
          format: date-time
          nullable: true
          description: When the configuration was last served to a user.
        created_at:
          type: string
          format: date-time
          description: ISO 8601 creation timestamp.
          example: '2025-09-15T12:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: ISO 8601 last update timestamp.
          example: '2025-11-03T10:26:40Z'
    V4RemoteConfigurationDetail:
      description: |
        Single remote configuration as returned by the single-configuration GET
        endpoint. Extends the base read object with the read-only inline `payload`
        values. Create, update, and status responses use the base
        `V4RemoteConfiguration` and do not include `payload`.
      allOf:
      - $ref: '#/components/schemas/V4RemoteConfiguration'
      - type: object
        properties:
          payload:
            type: object
            additionalProperties: true
            description: |
              Read-only copy of the JSON payload values delivered to the SDK
              (`{}` when unset). Edit via the payload endpoint, not this field.
            example:
              button_color: '#FF0000'
              max_items: 5
    V4RemoteConfigurationList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          example: list
        url:
          type: string
          example: /v4/remote-configurations
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4RemoteConfiguration'
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
    V4RemoteConfigurationCreate:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Display name (max 256 characters).
          example: Onboarding copy
        context_key:
          type: string
          nullable: true
          description: Optional stable key the SDK uses to look up this configuration.
          example: onboarding_copy_v1
        segment_percent:
          type: number
          minimum: 0
          maximum: 100
          description: |
            Optional. Percentage (0–100) of the targeted audience that receives this
            configuration. Defaults to `100` when omitted.
          example: 100
        segmentation_conditions:
          type: array
          description: |
            Optional targeting rules that narrow the audience. Omit or pass `[]` to
            target the whole audience.
          items:
            $ref: '#/components/schemas/V4RemoteConfigurationSegmentationCondition'
          example:
          - code: platform
            comparator: in
            type: string
            values:
            - ios
            - android
    V4RemoteConfigurationUpdate:
      type: object
      description: |
        Full replace of the configuration's editable fields. `name` is required;
        omitted optional fields are reset to their defaults (`segmentation_conditions`
        cleared, `segment_percent` back to `100`).
      required:
      - name
      properties:
        name:
          type: string
          description: Display name (max 256 characters).
          example: Onboarding copy
        context_key:
          type: string
          nullable: true
          description: Optional stable key the SDK uses to look up this configuration.
        segment_percent:
          type: number
          minimum: 0
          maximum: 100
          description: Percentage (0–100) of the targeted audience that receives this configuration.
          example: 100
        segmentation_conditions:
          type: array
          description: Targeting rules that narrow the audience. Pass `[]` to clear all rules.
          items:
            $ref: '#/components/schemas/V4RemoteConfigurationSegmentationCondition'
    V4RemoteConfigurationStatusRequest:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          enum:
          - draft
          - active
          - archived
          description: |
            New status. Allowed transitions: `draft` → `active`, `draft` → `archived`,
            `active` → `archived`. `archived` is terminal.
    V4RemoteConfigurationSegmentationCondition:
      type: object
      description: |
        A single targeting rule. Rules narrow which users the configuration is
        served to; all rules must match.
      required:
      - code
      - comparator
      - type
      - values
      properties:
        code:
          type: string
          description: Identifier of the user attribute or metric the rule tests.
          example: platform
        comparator:
          type: string
          description: Comparison operator applied between the attribute and `values`.
          example: in
        type:
          type: string
          description: Value type of the attribute being compared.
          example: string
        values:
          type: array
          description: Scalar values the rule compares against.
          items:
            type: string
          example:
          - ios
          - android
        object_values:
          type: array
          nullable: true
          description: |
            Optional structured values for comparators that match against objects
            rather than scalars.
          items:
            type: object
            additionalProperties: true
    V4RemoteConfigurationPayloadMapping:
      type: object
      description: |
        The payload **mapping**: the key → type schema describing how the SDK should
        interpret each payload key. This is the schema — not the delivered values
        (see `V4RemoteConfigurationPayload`).
      required:
      - object
      - url
      - config_id
      - data
      properties:
        object:
          type: string
          example: payload_mapping
        url:
          type: string
          example: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a/payload-mapping
        config_id:
          type: string
          example: 82a42dc2-76f6-46c2-b883-846acaf2070a
        data:
          type: object
          description: Flat map of payload key to its SDK-side type.
          additionalProperties:
            type: string
            x-extensible-enum:
            - String
            - Number
            - Bool
            - Json
            - Color
            - Products
            - Screens
          example:
            button_color: Color
            max_items: Number
    V4RemoteConfigurationPayloadMappingRequest:
      type: object
      required:
      - data
      properties:
        data:
          type: object
          description: |
            Full replacement mapping of payload key to SDK-side type. Allowed types:
            `String`, `Number`, `Bool`, `Json`, `Color`, `Products`, `Screens`.
          additionalProperties:
            type: string
            x-extensible-enum:
            - String
            - Number
            - Bool
            - Json
            - Color
            - Products
            - Screens
          example:
            button_color: Color
            max_items: Number
    V4RemoteConfigurationPayload:
      type: object
      description: |
        The payload **values**: the actual JSON object delivered to the SDK for this
        configuration. Distinct from the payload mapping, which is the key → type schema.
      required:
      - object
      - url
      - config_id
      - data
      properties:
        object:
          type: string
          example: remote_config_payload
        url:
          type: string
          example: /v4/remote-configurations/82a42dc2-76f6-46c2-b883-846acaf2070a/payload
        config_id:
          type: string
          example: 82a42dc2-76f6-46c2-b883-846acaf2070a
        data:
          type: object
          additionalProperties: true
          description: |
            The JSON values served to the SDK. Always a JSON object — `{}` when
            unset, never an array.
          example:
            button_color: '#FF0000'
            max_items: 5
    V4RemoteConfigurationPayloadRequest:
      type: object
      required:
      - data
      properties:
        data:
          type: object
          additionalProperties: true
          description: |
            Full replacement of the payload values. Must be a JSON object. An empty
            object `{}` clears the payload. Replaces the stored payload in full — to
            change one key, read the current payload, modify it, and send the whole
            object back. Limited to 64 KiB.
          example:
            button_color: '#FF0000'
            max_items: 5
    V4Segment:
      type: object
      required:
      - object
      - id
      - url
      - name
      - is_system
      - conditions
      - created_at
      - updated_at
      properties:
        object:
          type: string
          example: segment
        id:
          type: string
          description: Segment identifier.
          example: premium-users
        url:
          type: string
          description: Canonical API path.
          example: /v4/segments/premium-users
        name:
          type: string
          description: Display name.
          example: Premium Users
        is_system:
          type: boolean
          description: Whether this is a predefined system segment (read-only).
        conditions:
          type: array
          description: |
            Targeting rules. Every rule must match for a user to fall into the segment
            (logical AND). Omit on update to leave existing conditions untouched; pass
            an empty array to clear.
          items:
            $ref: '#/components/schemas/V4SegmentCondition'
        created_at:
          type: string
          format: date-time
          description: ISO 8601 creation timestamp.
          example: '2025-09-15T12:30:00Z'
        updated_at:
          type: string
          format: date-time
          description: ISO 8601 last update timestamp.
          example: '2025-11-03T10:26:40Z'
    V4SegmentCreate:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Segment name (max 256 characters).
          example: Premium Users
        conditions:
          type: array
          description: |
            Targeting rules. Every rule must match (logical AND). Optional;
            omit to create a segment with no rules.
          items:
            $ref: '#/components/schemas/V4SegmentCondition'
          example:
          - metric: environment
            comparator: eq
            value: prod
            negate: false
    V4SegmentUpdate:
      type: object
      required:
      - name
      properties:
        name:
          type: string
          description: Segment name (max 256 characters).
          example: Premium Users Updated
        conditions:
          type: array
          description: |
            Targeting rules. PUT is a full replace: pass the complete set you
            want to keep, or an empty array to clear all conditions. Omit the
            field to leave existing conditions untouched.
          items:
            $ref: '#/components/schemas/V4SegmentCondition'
    V4SegmentCondition:
      type: object
      description: |
        A single targeting rule. Rules are joined with logical AND within a
        segment.
      required:
      - metric
      - comparator
      - value
      properties:
        metric:
          type: string
          description: |
            Metric identifier. Corresponds to a configured `SegmentMetric`
            (`ref_table_field`). Common values: `environment`, `client_uid`,
            `custom_uid`, `client_advertiser_id`, `renewable`,
            `target_platform`.
          example: environment
        comparator:
          type: string
          x-extensible-enum:
          - eq
          - ne
          - gt
          - gte
          - lt
          - lte
          - contains
          - not_contains
          description: |
            Comparison operator applied between the metric and `value`.
            `contains` / `not_contains` map to SQL LIKE semantics on string
            metrics; numeric comparators (`gt`/`gte`/`lt`/`lte`) require a
            numeric metric.
          example: eq
        value:
          type: string
          description: |
            String-encoded value to compare against. Cast to the metric's
            underlying type (e.g. int, string) on the server.
          example: prod
        negate:
          type: boolean
          description: |
            If `true`, the rule matches when the comparison is false
            (logical NOT applied to the individual rule). Defaults to `false`.
          default: false
    V4Experiment:
      type: object
      properties:
        object:
          type: string
          example: experiment
        id:
          type: string
          description: Experiment identifier (server-generated UID).
        url:
          type: string
          description: Canonical API path.
        name:
          type: string
          description: Experiment display name.
        alias_id:
          type: string
          description: |
            User-facing stable identifier (supplied on POST, immutable after).
            Added in the DEV-777 response audit; was missing from the public
            envelope despite being accepted on create.
          example: paywall_ab_test_v3
        description:
          type: string
          description: Experiment description.
        status:
          type: string
          x-extensible-enum:
          - draft
          - active
          - paused
          - finished
          description: Current experiment status.
        started_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 timestamp when the experiment was started.
        finished_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 timestamp when the experiment was finished.
        segment_percent:
          type: number
          nullable: true
          description: Percentage of users included in the experiment.
        primary_metric:
          type: string
          nullable: true
          x-extensible-enum:
          - free_trials
          - trial_to_paid
          - trial_cancellation
          - new_subscriptions
          - subscription_cancellation
          - sales
          - proceeds
          - refunds
          - users
          - user_to_trial
          - user_to_paid
          description: 'Primary success metric. Legacy experiments created before the
            underscore naming may return hyphenated variants (e.g. `user-to-trial`,
            `subscription-cancellation`); treat them as read-only and migrate to the
            underscore form before sending them back on PATCH.'
        goal_value:
          type: number
          nullable: true
          description: Target value for the primary metric.
        goal_direction:
          type: string
          nullable: true
          x-extensible-enum:
          - increase
          - decrease
          description: Desired direction of change for the primary metric.
        context_key:
          type: string
          description: Context key for context-specific experiments.
        is_context_specific:
          type: boolean
          description: Whether this experiment is restricted to a specific context.
        created_at:
          type: string
          format: date-time
          description: ISO 8601 creation timestamp.
        updated_at:
          type: string
          format: date-time
          description: ISO 8601 last update timestamp.
    V4ExperimentGroup:
      type: object
      properties:
        object:
          type: string
          example: experiment_group
        id:
          type: string
          description: Group identifier.
        url:
          type: string
          description: Canonical API path.
        name:
          type: string
          nullable: true
          description: Group display name.
        is_control:
          type: boolean
          description: Whether this is the control group.
        weight:
          type: number
          description: Relative traffic weight for this group.
        remote_config_uid:
          type: string
          nullable: true
          description: |
            Remote config UID associated with this group. Mutually exclusive
            with `offering_uid` — a group carries at most one payload linkage.
        offering_uid:
          type: string
          nullable: true
          description: |
            Offering UID associated with this group (price-split experiments).
            Mutually exclusive with `remote_config_uid`.
        offering_tag:
          type: integer
          format: int16
          nullable: true
          description: |
            Tag of the attached offering (0 = default, 1 = variant).
            Populated only when `offering_uid` is set.
        created_at:
          type: string
          format: date-time
          description: ISO 8601 creation timestamp.
        updated_at:
          type: string
          format: date-time
          description: ISO 8601 last update timestamp.
    V4ExperimentCreateRequest:
      type: object
      required:
      - name
      - alias_id
      properties:
        name:
          type: string
          description: Experiment display name.
        alias_id:
          type: string
          description: Stable identifier for the experiment. Alphanumeric, hyphens, underscores, dots.
            Max 64 characters.
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 64
        description:
          type: string
          description: Optional experiment description.
        segment_percent:
          type: number
          nullable: true
          description: Percentage of users to include in the experiment.
        primary_metric:
          type: string
          nullable: true
          x-extensible-enum:
          - free_trials
          - trial_to_paid
          - trial_cancellation
          - new_subscriptions
          - subscription_cancellation
          - sales
          - proceeds
          - refunds
          - users
          - user_to_trial
          - user_to_paid
          description: Primary success metric.
        goal_value:
          type: number
          nullable: true
          description: Target value for the primary metric.
        goal_direction:
          type: string
          nullable: true
          x-extensible-enum:
          - increase
          - decrease
          description: Desired direction of change.
        context_key:
          type: string
          description: Context key for context-specific experiments.
        is_context_specific:
          type: boolean
          description: Whether this experiment is restricted to a specific context.
    V4ExperimentPatchRequest:
      type: object
      description: All fields optional. Only provided fields are updated.
      properties:
        name:
          type: string
          description: Experiment display name.
        alias_id:
          type: string
          description: Stable identifier for the experiment. Max 64 characters.
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 64
        description:
          type: string
          nullable: true
          description: Experiment description.
        segment_percent:
          type: number
          nullable: true
          description: Percentage of users to include.
        primary_metric:
          type: string
          nullable: true
          x-extensible-enum:
          - free_trials
          - trial_to_paid
          - trial_cancellation
          - new_subscriptions
          - subscription_cancellation
          - sales
          - proceeds
          - refunds
          - users
          - user_to_trial
          - user_to_paid
        goal_value:
          type: number
          nullable: true
        goal_direction:
          type: string
          nullable: true
          x-extensible-enum:
          - increase
          - decrease
        context_key:
          type: string
          nullable: true
        is_context_specific:
          type: boolean
          nullable: true
    V4ExperimentStatusRequest:
      type: object
      required:
      - status
      properties:
        status:
          type: string
          enum:
          - draft
          - active
          - paused
          - finished
          description: New experiment status.
    V4ExperimentGroupCreateRequest:
      type: object
      required:
      - weight
      properties:
        name:
          type: string
          nullable: true
          description: Group display name.
        is_control:
          type: boolean
          description: Whether this is the control group.
        weight:
          type: number
          description: Relative traffic weight for this group.
        remote_config_uid:
          type: string
          nullable: true
          description: Remote config UID to associate with this group.
    V4ExperimentAttachRequest:
      type: object
      required:
      - group_id
      properties:
        group_id:
          type: string
          description: ID of the experiment group to assign the user to.
          pattern: ^[a-zA-Z0-9._-]+$
          maxLength: 64
    V4Event:
      type: object
      properties:
        object:
          type: string
          enum:
          - event
        id:
          type: string
          description: Event ID.
          example: '12345'
        url:
          type: string
          description: Canonical API path.
          example: /v4/events/12345
        event_name:
          type: string
          nullable: true
          description: Name of the event (e.g. trial_started, subscription_renewed).
          example: trial_started
        customer_uid:
          type: string
          nullable: true
          description: Customer UID associated with the event.
          example: abc-123-def
        happened_at:
          type: string
          format: date-time
          description: When the event occurred (ISO 8601).
          example: '2026-04-01T12:00:00Z'
    # only injects the envelope fields `object` and `url`; it does not
    # transform the remaining fields. Shapes below reflect live production
    # responses as of DEV-806.

    V4AnalyticsSeriesDataPoint:
      type: object
      required: [start_time, value]
      properties:
        start_time:
          type: integer
          format: int64
          description: Bucket start (Unix seconds).
        value:
          type: number
          format: double
          description: Metric value in the chart's `measure` unit.

    V4AnalyticsSeries:
      type: object
      required: [label, data]
      properties:
        label:
          type: string
          description: Series label (e.g. `"After refunds"` or a segment value).
        total:
          type: number
          format: double
          nullable: true
          description: Total across `data` for the current range.
        totalPrev:
          type: number
          format: double
          nullable: true
          description: Total across the previous equal-length range (for comparisons).
        totalWeight:
          type: number
          format: double
          nullable: true
          description: Weight of `total` — used for weighted-average totals.
        totalPrevWeight:
          type: number
          format: double
          nullable: true
        totalIgnoreInFinal:
          type: boolean
          nullable: true
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4AnalyticsSeriesDataPoint'

    V4AnalyticsChart:
      type: object
      required: [object, url, code, from, to, unit, environment, measure, totalType, seriesRelation, maxSeries, series]
      properties:
        object:
          type: string
          enum: [analytics_chart]
        url:
          type: string
          description: Canonical URL for this chart query.
        code:
          type: string
          description: Chart code, echoed from the request.
        from:
          type: integer
          format: int64
        to:
          type: integer
          format: int64
        unit:
          type: string
          enum: [hour, day, week, month]
        environment:
          type: integer
          enum: [0, 1]
        currency:
          type: string
          description: ISO 4217 currency code used for monetary values.
        measure:
          type: string
          enum: [usd, count, percent]
          description: Physical unit of `series[].data[].value`.
        totalType:
          type: string
          enum: [sum, wavg]
          description: How `series[].total` is computed.
        seriesRelation:
          type: string
          enum: [partsOfWhole, independent]
          description: |
            * `partsOfWhole` — series add up to a meaningful total (e.g. revenue by country).
            * `independent` — series are not directly comparable in sum.
        maxSeries:
          type: integer
          description: Max number of series the server may emit.
        horizontalLabelType:
          type: string
          description: Hint for the UI on how to format X-axis labels.
        segmentation:
          type: string
          nullable: true
          description: Segmentation dimension used, if any.
        summarySeries:
          $ref: '#/components/schemas/V4AnalyticsSeries'
          nullable: true
        series:
          type: array
          items:
            $ref: '#/components/schemas/V4AnalyticsSeries'

    V4AnalyticsFilterCondition:
      type: object
      required: [attribute, label, type]
      properties:
        attribute:
          type: string
          description: Filter attribute code — use as `filter[<attribute>][]` query key.
        category:
          type: string
          description: Optional UI grouping (`Device`, `Customer / ID`, `Experiment`, `Attribution`).
        label:
          type: string
        type:
          type: string
          enum: [list, text]
          description: |
            * `list` — value must be one of `values[].code`; supports multi-select when `multiple=true`.
            * `text` — free-form single value (e.g. `user_id`, `device_id`, `q_user_id`).
        multiple:
          type: boolean
        persistent:
          type: boolean
          description: Hint to the UI that this filter should always be visible.
        values:
          type: array
          description: Allowed values for `list`-type filters.
          items:
            type: object
            required: [code, label]
            properties:
              code: { type: string }
              label: { type: string }

    V4AnalyticsSegmentation:
      type: object
      required: [code, label]
      properties:
        code: { type: string }
        label: { type: string }
        category: { type: string }

    V4AnalyticsChartMeta:
      type: object
      required: [object, url, code, title, isAvailable, segmentations, filter_conditions, units_available]
      properties:
        object: { type: string, enum: [analytics_chart_meta] }
        url:   { type: string }
        code:  { type: string }
        title: { type: string }
        description: { type: string }
        docUrl:
          type: string
          description: Link to the narrative documentation for this chart.
        isAvailable:
          type: boolean
          description: False when the chart is blocked by the project's plan or feature flag.
        availabilityMessage:
          type: string
          description: Human-readable reason the chart is unavailable. Empty when `isAvailable=true`.
        type_default:
          type: string
          description: Recommended visual type (e.g. `column`).
        types:
          type: array
          items: { type: string, enum: [line, column, area, bar, pie] }
        units_available:
          type: array
          items: { type: string, enum: [hour, day, week, month] }
        segmentations:
          type: array
          items: { $ref: '#/components/schemas/V4AnalyticsSegmentation' }
        filter_conditions:
          type: array
          items: { $ref: '#/components/schemas/V4AnalyticsFilterCondition' }

    V4AnalyticsCardRow:
      type: object
      required: [code, value]
      properties:
        code:
          type: string
          description: Sub-metric code (e.g. `trials_count`, `subscriptions_count`, `inapp_count`, `tracked_revenue`).
        value:
          type: number
          description: Value for the current window (integer for count metrics, decimal for revenue).
        valuePrev:
          type: number
          description: Value for the previous comparison window.

    V4AnalyticsCard:
      type: array
      description: |
        Array of per-metric rows. Unlike chart/cohort endpoints, the card payload is
        an array rather than an `{object, url, ...}` envelope.
      items:
        $ref: '#/components/schemas/V4AnalyticsCardRow'

    V4AnalyticsCurrencies:
      type: object
      required: [object, url, currencies]
      properties:
        object: { type: string, enum: [analytics_currencies] }
        url:    { type: string }
        currencies:
          type: array
          description: Three-letter ISO 4217 codes, `USD` first.
          items:
            type: string
            pattern: '^[A-Z]{3}$'

    V4AnalyticsCohorts:
      type: object
      required: [object, url, mode, grouping, cohort_from, cohort_to, currency, period_labels, cohorts, max_values]
      properties:
        object:      { type: string, enum: [analytics_cohorts] }
        url:         { type: string }
        mode:        { type: string, enum: [by_renewals, by_days] }
        grouping:    { type: string, enum: [day, week, month, quarter, year] }
        cohort_from: { type: integer, format: int64 }
        cohort_to:   { type: integer, format: int64 }
        currency:    { type: string }
        period_labels:
          type: array
          description: Column labels — `P1`, `P2`, … for `by_renewals`, date strings for `by_days`.
          items: { type: string }
        cohorts:
          type: array
          description: One row per cohort window. Empty when the project has no qualifying cohorts in the range.
          items:
            type: object
            additionalProperties: true
        total:
          type: object
          nullable: true
          additionalProperties: true
          description: Aggregated totals row. Null when the table is empty.
        max_values:
          type: object
          description: Maximum per-metric value across the table — used for heatmap coloring in the UI.
          additionalProperties:
            type: number
        group_by:
          type: string
          description: Present only when `group_by` was supplied on the request.
        segments:
          type: array
          description: Present only when `group_by` was supplied. One entry per segmentation value.
          items:
            type: object
            additionalProperties: true

    V4AnalyticsCohortsMeta:
      type: object
      required: [object, url, modes, groupings, metrics, definitions, filter_conditions]
      properties:
        object:    { type: string, enum: [analytics_cohorts_meta] }
        url:       { type: string }
        modes:
          type: array
          items:
            type: object
            properties:
              code:  { type: string, enum: [by_renewals, by_days] }
              label: { type: string }
        groupings:
          type: array
          items:
            type: object
            properties:
              code:  { type: string, enum: [day, week, month, quarter, year] }
              label: { type: string }
        metrics:
          type: array
          description: Allowed `metric` values. (Metric selection is chosen client-side — the endpoint returns all five.)
          items:
            type: object
            properties:
              code:  { type: string, enum: [revenue, subscriptions, payers, arpu, arppu] }
              label: { type: string }
        definitions:
          type: array
          items:
            type: object
            properties:
              code:  { type: string, enum: [new_customers, initial_conversions, new_paying] }
              label: { type: string }
        filter_conditions:
          type: array
          items: { $ref: '#/components/schemas/V4AnalyticsFilterCondition' }

    V4AnalyticsLtv:
      type: object
      required: [object, url, mode, cohort_from, cohort_to, cohort_users, paying_users, revenue_type, currency, measure, series]
      properties:
        object:       { type: string, enum: [analytics_ltv] }
        url:          { type: string }
        mode:         { type: string, enum: [by_days, by_renewals] }
        cohort_from:  { type: integer, format: int64 }
        cohort_to:    { type: integer, format: int64 }
        cohort_users:
          type: integer
          description: Total users in the selected cohort range.
        paying_users:
          type: integer
          description: Subset of `cohort_users` that made at least one paid transaction.
        revenue_type: { type: string, enum: [gross, net] }
        currency:     { type: string }
        measure:      { type: string, enum: [usd] }
        segment:
          type: string
          nullable: true
          description: Segmentation attribute used, if any.
        segments:
          type: array
          description: Per-segmentation-value series breakdown. Empty when `segment` is null.
          items:
            type: object
            additionalProperties: true
        series:
          type: array
          items:
            $ref: '#/components/schemas/V4AnalyticsSeriesDataPoint'

    V4AnalyticsLtvMeta:
      type: object
      required: [object, url, modes, segmentations, filter_conditions]
      properties:
        object:       { type: string, enum: [analytics_ltv_meta] }
        url:          { type: string }
        modes:
          type: array
          items:
            type: object
            properties:
              code:  { type: string, enum: [by_days, by_renewals] }
              label: { type: string }
        segmentations:
          type: array
          items: { $ref: '#/components/schemas/V4AnalyticsSegmentation' }
        filter_conditions:
          type: array
          items: { $ref: '#/components/schemas/V4AnalyticsFilterCondition' }

    V4AnalyticsLtvTrialConversion:
      type: object
      required: [object, url, trials_started, trials_converted, conversion_rate]
      properties:
        object:           { type: string, enum: [analytics_ltv_trial_conversion] }
        url:              { type: string }
        trials_started:
          type: integer
          description: Number of trials started in the cohort range.
        trials_converted:
          type: integer
          description: Subset of `trials_started` that became paid.
        conversion_rate:
          type: number
          format: double
          minimum: 0
          maximum: 1
          description: Decimal fraction — multiply by 100 for a percentage.

    V4AnalyticsInsight:
      type: object
      required: [type, metric, title, body, action]
      properties:
        type:
          type: string
          enum: [critical, positive, tip, info]
          description: Severity / category — drives UI coloring.
        metric:
          type: string
          description: Metric the insight is about (e.g. `mrr`, `new_users`, `user_to_paid_conversion`).
        title:
          type: string
        body:
          type: string
          description: Longer-form observation, 1–3 sentences.
        action:
          type: string
          description: Suggested next step for the operator.

    V4AnalyticsInsights:
      type: object
      required: [object, url, generated_at, period_days, health, summary, insights]
      properties:
        object:       { type: string, enum: [analytics_insights] }
        url:          { type: string }
        generated_at:
          type: string
          format: date-time
          nullable: true
          description: ISO 8601 timestamp of when the insights were generated.
        period_days:
          type: integer
          minimum: 1
          maximum: 365
          description: Window the insights cover, echoed from the `period` query param.
        health:
          type: string
          nullable: true
          enum: [healthy, watch, critical, null]
          description: One-word project health label.
        health_score:
          type: integer
          minimum: 0
          maximum: 10
          description: Integer score — lower is worse.
        summary:
          type: string
          description: One-paragraph plain-English synthesis.
        insights:
          type: array
          items:
            $ref: '#/components/schemas/V4AnalyticsInsight'
        is_cached:
          type: boolean
          description: True when the payload came from the upstream cache.
        is_stale:
          type: boolean
          description: True when a background refresh is in progress and the returned data is an older snapshot.
        is_empty:
          type: boolean
          description: True when the project has insufficient data to generate insights.


    V4Error:
      type: object
      required:
      - error
      properties:
        error:
          type: object
          required:
          - type
          - code
          - message
          properties:
            type:
              type: string
              enum:
              - request
              - resource
              - logical
              - internal
            code:
              type: string
              description: |
                Machine-readable snake_case error code. Examples include
                `invalid_data`, `invalid_request`, `invalid_product_id`,
                `not_found`, `already_exists`, `offering_already_exists`,
                `product_not_in_project`, `cannot_set_main_directly`,
                `cannot_demote_main`, `cannot_patch_experiment_variant`,
                `cannot_delete_experiment_variant`, and
                `cannot_setmain_experiment_variant`. Resource-specific codes
                are documented on the corresponding reference page.
            message:
              type: string
              description: Human-readable description. May change; do not parse.
            details:
              type: array
              nullable: true
              description: Per-field validation errors, present on 400 validation failures.
              items:
                type: object
                properties:
                  field:
                    type: string
                  message:
                    type: string
    V4Identity:
      type: object
      required:
      - object
      - id
      - url
      - user_id
      properties:
        object:
          type: string
          enum:
          - identity
        id:
          type: string
          description: External identity identifier.
          example: ext-user-123
        url:
          type: string
          description: Canonical API path.
          example: /v4/identities/ext-user-123
        user_id:
          type: string
          description: Qonversion user identifier linked to this identity.
          example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
    V4IdentityCreateRequest:
      type: object
      required:
      - identity_id
      properties:
        identity_id:
          type: string
          description: External identity ID to assign. Identities are append-only — posting the same identity_id twice returns 409.
          maxLength: 255
          pattern: ^[a-zA-Z0-9._-]+$
          example: ext-user-123
        user_id:
          type: string
          nullable: true
          description: Qonversion user ID to bind. If null, a new anonymous user is created and linked.
          maxLength: 255
          pattern: ^[a-zA-Z0-9._-]+$
          example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
    V4User:
      type: object
      required:
      - object
      - id
      - url
      - environment
      - created_at
      properties:
        object:
          type: string
          enum:
          - user
        id:
          type: string
          description: Qonversion User ID. SDK-generated IDs are prefixed with `QON_`.
          example: QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
        url:
          type: string
          description: Canonical API path.
          example: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e
        environment:
          type: string
          enum:
          - prod
          - sandbox
          description: Environment the user belongs to.
          example: prod
        identity_id:
          type: string
          nullable: true
          description: External identity identifier, if set. Null when not linked to an identity.
          example: awesome_user
        created_at:
          type: string
          format: date-time
          description: Creation timestamp (ISO 8601 UTC).
          example: '2025-09-15T12:30:00Z'
    V4UserCreate:
      type: object
      required:
      - environment
      properties:
        environment:
          type: string
          enum:
          - prod
          - sandbox
          description: Environment the user belongs to.
          example: prod
    V4CustomerList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/customers
        data:
          type: array
          items:
            type: object
            description: Customer data (shape determined by the analytics service).
        has_more:
          type: boolean
        next_cursor:
          type: string
          description: Present only when has_more is true.
    V4PermissionList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/customers/customer_abc123/permissions
        data:
          type: array
          items:
            type: object
            description: Permission record. `started_at` and `expires_at` are Unix epoch
              seconds. `source` indicates how the permission was granted.
            properties:
              id:
                type: string
                description: Permission identifier (matches the entitlement ID).
                example: premium_access
              source:
                type: string
                description: How the permission was granted.
                x-extensible-enum:
                - apple
                - google
                - by_hand
                - unknown
                example: apple
              active:
                type: boolean
                example: true
              started_at:
                type: integer
                format: int64
                description: Unix epoch seconds when the permission started.
                example: 1729600000
              expires_at:
                type: integer
                format: int64
                description: Unix epoch seconds when the permission expires.
                example: 1761136000
              product_id:
                type: string
                nullable: true
                description: Identifier of the product that issued the permission, when
                  applicable.
                example: monthly_premium
        has_more:
          type: boolean
        next_cursor:
          type: string
          description: Present only when has_more is true.
      example:
        object: list
        url: /v4/customers/customer_abc123/permissions
        data:
          - id: premium_access
            source: apple
            active: true
            started_at: 1729600000
            expires_at: 1761136000
            product_id: monthly_premium
        has_more: false
        next_cursor: null
    V4CustomerPropertiesRequest:
      type: object
      required:
      - properties
      properties:
        properties:
          type: array
          description: List of key/value property pairs to set on the customer. 1–100 items.
          minItems: 1
          maxItems: 100
          items:
            type: object
            required:
            - key
            - value
            properties:
              key:
                type: string
                description: Property key. 1–256 characters.
                minLength: 1
                maxLength: 256
                example: plan_tier
              value:
                type: string
                description: Property value. At most 1024 characters.
                maxLength: 1024
                example: premium
    V4CustomerPermissionRequest:
      type: object
      required:
      - permission_id
      properties:
        permission_id:
          type: string
          description: Permission identifier to grant. Must be alphanumeric, hyphens, underscores, or
            dots. Max 256 characters.
          maxLength: 256
          example: premium_access
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: Optional expiration timestamp in RFC 3339 / ISO 8601 format. Omit for a non-expiring
            permission.
          example: '2026-01-01T00:00:00Z'
    V4PurchaseList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/users/user_abc123/purchases
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4Purchase'
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
          description: 'ID to pass as `starting_after` on the next request. Present
            only when `has_more` is `true`; otherwise `null`.'
      example:
        object: list
        url: /v4/users/user_abc123/purchases
        has_more: false
        next_cursor: null
        data:
        - object: purchase
          id: '12345'
          url: /v4/users/user_abc123/purchases/12345
          user_id: user_abc123
          platform: app_store
          product_id: com.example.monthly
          currency: USD
          price: '9.99'
          purchased_at: '2025-04-01T10:30:00Z'
          expires_at: '2025-05-01T10:30:00Z'
          is_auto_renewing: true
          store_data:
            transaction_id: '2000000123456789'
            original_transaction_id: '2000000123456789'
            product_id: com.example.monthly
          created_at: '2025-04-01T10:30:00Z'
    V4Purchase:
      type: object
      required:
      - object
      - id
      - url
      - user_id
      - platform
      - product_id
      - currency
      - price
      - purchased_at
      - is_auto_renewing
      - store_data
      - created_at
      properties:
        object:
          type: string
          enum:
          - purchase
        id:
          type: string
          example: '12345'
        url:
          type: string
          example: /v4/users/user_abc123/purchases/12345
        user_id:
          type: string
          example: user_abc123
        platform:
          type: string
          description: 'Store that originated the transaction. Determines the shape
            of `store_data`.'
          x-extensible-enum:
          - app_store
          - play_store
          - stripe
        product_id:
          type: string
          description: 'Qonversion product identifier. For Play Store subscriptions
            with a base plan, the value is `{product_id}:{base_plan_id}`.'
        currency:
          type: string
          description: Three-letter ISO 4217 currency code. May be empty when the
            source transaction lacks currency (e.g. legacy imports).
          example: USD
        price:
          type: string
          description: Monetary amount as a decimal string. May be empty when the
            source transaction lacks a price.
          example: '9.99'
        purchased_at:
          type: string
          format: date-time
          description: Time the store reported the transaction (RFC 3339 / ISO 8601).
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: 'Subscription expiry time, or `null` for non-expiring purchases
            and consumables.'
        is_auto_renewing:
          type: boolean
          description: 'Whether the subscription is set to auto-renew. `false` for
            one-time purchases and cancelled subscriptions.'
        store_data:
          description: 'Platform-specific identifiers. The `platform` field on the
            enclosing purchase selects which shape is returned: `app_store` →
            `V4PurchaseAppStoreData`, `play_store` → `V4PurchasePlayStoreData`,
            `stripe` → `V4PurchaseStripeStoreData`. A native OpenAPI
            `discriminator` is not declared because the selector lives on the
            parent object, not on `store_data` itself.'
          oneOf:
          - $ref: '#/components/schemas/V4PurchaseAppStoreData'
          - $ref: '#/components/schemas/V4PurchasePlayStoreData'
          - $ref: '#/components/schemas/V4PurchaseStripeStoreData'
        created_at:
          type: string
          format: date-time
          description: 'Time Qonversion first recorded the purchase. For history imported
            from the store this currently mirrors `purchased_at`.'
    V4PurchaseAppStoreData:
      type: object
      description: '`store_data` shape when `platform` is `app_store`.'
      required:
      - transaction_id
      - original_transaction_id
      - product_id
      properties:
        transaction_id:
          type: string
          description: App Store transaction identifier for this specific purchase.
          example: '2000000123456789'
        original_transaction_id:
          type: string
          description: App Store original transaction identifier (shared across renewals).
          example: '2000000123456789'
        product_id:
          type: string
          description: App Store product identifier.
          example: com.example.monthly
    V4PurchasePlayStoreData:
      type: object
      description: '`store_data` shape when `platform` is `play_store`. For
        subscriptions with a base plan, the enclosing purchase''s `product_id`
        is `{product_id}:{base_plan_id}` (e.g. `com.example.yearly:monthly-base`),
        while the `product_id` here stays the bare Google Play product id.'
      required:
      - order_id
      - purchase_token
      - product_id
      properties:
        order_id:
          type: string
          description: Google Play order identifier.
          example: GPA.1234-5678-9012-34567
        purchase_token:
          type: string
          description: Google Play purchase token.
          example: abcdefg.AO-J1Ox...
        product_id:
          type: string
          description: Google Play product identifier.
          example: com.example.yearly
    V4PurchaseStripeStoreData:
      type: object
      description: '`store_data` shape when `platform` is `stripe`.'
      required:
      - subscription_id
      - product_id
      properties:
        subscription_id:
          type: string
          description: Stripe subscription identifier.
          example: sub_123e4567
        product_id:
          type: string
          description: Stripe product identifier.
          example: prod_123e4567
    ResponseError:
      type: object
      properties:
        meta:
          type: object
        error:
          $ref: '#/components/schemas/Error'
    Error:
      type: object
      required:
      - type
      - code
      - message
      properties:
        type:
          type: string
          enum:
          - internal
          - logical
          - request
          - resource
        code:
          type: string
          example:
          - unknown_error
          - relation_not_found
        message:
          type: string
    NoCodeScreen:
      type: object
      required:
      - id
      - body
      - type
      properties:
        id:
          type: string
        body:
          type: string
        context_key:
          type: string
        type:
          type: integer
          enum:
          - 0
          - 1
          - 2
          description: Screen type (0=MOBILE_PAYWALL, 1=WEB_FLOW, 2=MOBILE_ONBOARDING)
          example: 0
        is_web:
          type: boolean
          description: Legacy field for backward compatibility. Use 'type' field instead.
          example: false
        preload:
          type: boolean
          description: Flag indicating if the screen should be preloaded
          example: true
        prod_key:
          type: string
        sandbox_key:
          type: string
    RemoteConfigResponse:
      type: object
      required:
      - payload
      properties:
        payload:
          type: object
        experiment:
          $ref: '#/components/schemas/Experiment'
        source:
          $ref: '#/components/schemas/RemoteConfigurationSource'
    RemoteConfigurationSource:
      type: object
      required:
      - uid
      - name
      - type
      - assignment_type
      - context_key
      properties:
        uid:
          type: string
        name:
          type: string
        type:
          type: string
          enum:
          - remote_configuration
          - experiment_control_group
          - experiment_treatment_group
          - unknown
        assignment_type:
          type: string
          enum:
          - auto
          - manual
          - unknown
        context_key:
          type: string
    Experiment:
      type: object
      required:
      - uid
      - name
      - group
      properties:
        uid:
          type: string
        name:
          type: string
        group:
          $ref: '#/components/schemas/ExperimentGroup'
    ExperimentGroup:
      type: object
      required:
      - uid
      - name
      - type
      properties:
        uid:
          type: string
        name:
          type: string
        type:
          type: string
          enum:
          - control
          - treatment
          - unknown
    ListUserPurchasesResponse:
      type: object
      properties:
        object:
          enum:
          - list
        data:
          type: array
          items:
            $ref: '#/components/schemas/UserPurchase'
    UserPurchase:
      type: object
      required:
      - user_id
      properties:
        user_id:
          type: string
          example: 123e4567
        currency:
          type: string
          example: USD
          description: Currency code by ISO 4217 standard
        price:
          type: string
          example: 12.99
        app_store_data:
          $ref: '#/components/schemas/AppStoreData'
        play_store_data:
          $ref: '#/components/schemas/PlayStoreData'
        stripe_store_data:
          $ref: '#/components/schemas/StripeStoreData'
        purchased:
          type: integer
          format: int64
          minimum: 0
          description: The UNIX time, in seconds
    CreateUserEntitlementRequest:
      type: object
      required:
      - id
      - expires
      properties:
        id:
          type: string
          example: 123e4567
          description: The ID of the permission to grant
        expires:
          type: integer
          format: int64
          description: The UNIX time, in seconds
    CreateUserPropertiesRequest:
      type: array
      items:
        $ref: '#/components/schemas/UserProperty'
    CreateUserPropertiesResponse:
      type: object
      description: Response object containing both saved properties and failed ones with errors
      required:
      - savedProperties
      - propertyErrors
      properties:
        savedProperties:
          $ref: '#/components/schemas/UserPropertiesList'
        propertyErrors:
          $ref: '#/components/schemas/UserPropertyErrorList'
    GetUserPropertiesResponse:
      type: array
      items:
        $ref: '#/components/schemas/UserProperty'
    CreateUserPurchaseRequest:
      type: object
      required:
      - currency
      - price
      - purchased
      properties:
        currency:
          type: string
          example: USD
          description: Currency code by ISO 4217 standard
        price:
          type: string
          example: 12.99
        app_store_data:
          $ref: '#/components/schemas/AppStoreData'
        play_store_data:
          $ref: '#/components/schemas/PlayStoreData'
        stripe_store_data:
          $ref: '#/components/schemas/StripeStoreData'
        purchased:
          type: integer
          format: int64
          minimum: 0
          description: The UNIX time, in seconds
    AppStoreData:
      type: object
      required:
      - receipt
      - transaction_id
      - original_transaction_id
      - product_id
      properties:
        receipt:
          type: string
          example: MIIULgYJKoZIhvcNAQcCoIIUHzCC...
        transaction_id:
          type: string
          example: 140001248850668
        original_transaction_id:
          type: string
          example: 140001248850668
        product_id:
          type: string
          example: com.foo.bar
        period_length:
          $ref: '#/components/schemas/AppStorePeriodLength'
    PlayStoreData:
      type: object
      required:
      - type
      - order_id
      - purchase_token
      - product_id
      properties:
        type:
          $ref: '#/components/schemas/UserPurchaseProductType'
        order_id:
          type: string
          example: GPA.3363-8534-0769-40369
        purchase_token:
          type: string
          example: appegepebjochlocmjhdnimf.AO-J1Ow...
        product_id:
          type: string
          example: com.foo.bar
        subscription_period:
          type: string
          example: P6M
          description: Subscription period, specified in ISO 8601 format. For example, P1W equates to
            one week, P1M equates to one month, and P1Y equates to one year
        free_trial_period:
          type: string
          example: P1W
          description: Trial period configured in Google Play Console, specified in ISO 8601 format
    StripeStoreData:
      type: object
      required:
      - subscription_id
      - product_id
      properties:
        subscription_id:
          type: string
          example: sub_123e4567...
        product_id:
          type: string
          example: prod_123e4567...
    AppStorePeriodLength:
      type: object
      required:
      - unit
      - number_of_units
      properties:
        unit:
          $ref: '#/components/schemas/PeriodUnit'
        number_of_units:
          type: integer
          format: int64
          description: The number of units per subscription period
    PeriodUnit:
      type: string
      enum:
      - day
      - week
      - month
      - year
    User:
      type: object
      required:
      - id
      properties:
        id:
          type: string
          example: 123e4567
        identity_id:
          type: string
          example: my-own-id-01
        environment:
          type: string
          enum:
          - prod
          - sandbox
        created:
          type: integer
          format: int64
          minimum: 0
          description: The UNIX time, in seconds
    CreateUserRequest:
      type: object
      required:
      - environment
      properties:
        environment:
          type: string
          enum:
          - prod
          - sandbox
    Identity:
      type: object
      required:
      - id
      properties:
        id:
          type: string
          example: my-own-id-01
        user_id:
          type: string
          example: 123e4567
    CreateIdentityRequest:
      type: object
      properties:
        user_id:
          type: string
          example: 123e4567
    ProductType:
      type: integer
      format: int16
      description: 'Type of the product:

        - 0: Non-recurring (one-time purchase)

        - 1: Regular subscription

        - 2: Subscription with promotional offer

        '
      enum:
      - 0
      - 1
      - 2
      example: 1
    ProductDuration:
      type: integer
      format: int64
      description: Duration of the product
      enum:
      - 0
      - 1
      - 2
      - 3
      - 4
      - 5
    ProductCreate:
      type: object
      required:
      - uid
      properties:
        uid:
          type: string
          description: Unique identifier of the product
        type:
          $ref: '#/components/schemas/ProductType'
        apple_product_id:
          type: string
          description: Apple Store product ID
        google_product_id:
          type: string
          description: Google Play product ID
        google_base_plan_id:
          type: string
          description: Google Play product base plan ID
        stripe_product_id:
          type: string
          description: Stripe product ID
        duration:
          $ref: '#/components/schemas/ProductDuration'
    ProductUpdate:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/ProductType'
        apple_product_id:
          type: string
          description: Apple Store product ID
        google_product_id:
          type: string
          description: Google Play product ID
        google_base_plan_id:
          type: string
          description: Google Play product base plan ID
        stripe_product_id:
          type: string
          description: Stripe product ID
        duration:
          $ref: '#/components/schemas/ProductDuration'
    ProductPatch:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/ProductType'
        apple_product_id:
          type: string
          description: Apple Store product ID
        google_product_id:
          type: string
          description: Google Play product ID
        google_base_plan_id:
          type: string
          description: Google Play product base plan ID
        stripe_product_id:
          type: string
          description: Stripe product ID
        duration:
          $ref: '#/components/schemas/ProductDuration'
    Product:
      type: object
      required:
      - uid
      - project_id
      - created_at
      - updated_at
      properties:
        uid:
          type: string
        project_id:
          type: integer
          format: int64
        type:
          $ref: '#/components/schemas/ProductType'
        duration:
          $ref: '#/components/schemas/ProductDuration'
        apple_product_id:
          type: string
        google_product_id:
          type: string
        google_base_plan_id:
          type: string
        created_at:
          type: integer
          format: int64
        updated_at:
          type: integer
          format: int64
        stripe_product_id:
          type: string
        subscription_duration:
          type: string
          enum:
          - P1W
          - P1M
          - P3M
          - P6M
          - P1Y
    ListUserEntitlementsResponse:
      type: object
      properties:
        object:
          enum:
          - list
        data:
          type: array
          items:
            $ref: '#/components/schemas/UserEntitlement'
    UserEntitlement:
      type: object
      required:
      - id
      - active
      - expires
      - started
      - user_id
      - source
      properties:
        id:
          type: string
          example: premium
          description: The entitlement ID
        active:
          type: boolean
          description: '`true` means a user has active entitlement.


            Please note, active = `true` does not mean that a subscription will be renewed.

            A user can have active entitlement, while auto-renewal for the subscription was switched off.

            '
        expires:
          type: integer
          format: int64
          description: Time at which the entitlement expires and is no longer available. Measured in seconds
            since the Unix epoch.
        started:
          type: integer
          format: int64
          minimum: 0
          description: Time at which the entitlement was started. Measured in seconds since the Unix epoch.
        source:
          type: string
          enum:
          - appstore
          - playstore
          - stripe
          - manual
          - unknown
          description: Entitlement source
        product:
          $ref: '#/components/schemas/UserPurchaseProduct'
    UserPurchaseProduct:
      type: object
      required:
      - product_id
      properties:
        product_id:
          type: string
          description: Product ID that granted the entitlement
        subscription:
          $ref: '#/components/schemas/UserPurchaseProductSubscription'
    UserPurchaseProductSubscription:
      type: object
      required:
      - renew_state
      - current_period_type
      properties:
        renew_state:
          type: string
          enum:
          - will_renew
          - canceled
          - billing_issue
        current_period_type:
          type: string
          enum:
          - normal
          - trial
          - intro
    UserPurchaseProductType:
      type: string
      enum:
      - non_recurring
      - subscription
    V4UserPropertyList:
      type: object
      required:
      - object
      - url
      - data
      - has_more
      properties:
        object:
          type: string
          enum:
          - list
        url:
          type: string
          example: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/properties
        data:
          type: array
          items:
            $ref: '#/components/schemas/V4UserPropertyItem'
        has_more:
          type: boolean
        next_cursor:
          type: string
          nullable: true
    V4UserPropertyItem:
      type: object
      required:
      - object
      - key
      - value
      properties:
        object:
          type: string
          enum:
          - user_property
        key:
          type: string
          example: color
        value:
          type: string
          example: blue
    V4UserPropertyError:
      type: object
      required:
      - key
      - error
      properties:
        key:
          type: string
          description: Property key that failed to save.
          example: bad_key
        error:
          type: string
          description: Human-readable error message.
          example: invalid key
    V4UserPropertiesSetResult:
      type: object
      required:
      - object
      - url
      - saved_properties
      - property_errors
      properties:
        object:
          type: string
          enum:
          - user_properties_set_result
        url:
          type: string
          example: /v4/users/QON_3af4c5b8a4d24f21b72e9d0c8aef9d4e/properties
        saved_properties:
          type: array
          items:
            $ref: '#/components/schemas/V4UserPropertyItem'
        property_errors:
          type: array
          items:
            $ref: '#/components/schemas/V4UserPropertyError'
    V4SetUserPropertiesRequest:
      type: object
      required:
      - properties
      properties:
        properties:
          type: array
          minItems: 1
          maxItems: 100
          items:
            $ref: '#/components/schemas/V4SetUserPropertyItem'
    V4SetUserPropertyItem:
      type: object
      required:
      - key
      - value
      properties:
        key:
          type: string
          minLength: 1
          maxLength: 256
          description: |
            Property key. The request is rejected with 400 only if the key is
            empty or longer than 256 characters. Effective validation (applied
            per-item and reported via `property_errors`) additionally requires
            the key to be at most 80 characters, match `^[-a-zA-Z0-9_.:]+$`, and
            contain at least one letter. Keys starting with `_` are reserved;
            only pre-registered keys prefixed with `_q_` are accepted.
          example: color
        value:
          type: string
          maxLength: 1024
          description: |
            Property value. The request is rejected with 400 only if the value
            is longer than 1024 characters. Effective validation (applied
            per-item and reported via `property_errors`) additionally requires
            the value to be at most 120 bytes and to contain no `\n`, `\r`, `"`
            or `'` characters.
          example: blue
    UserPropertiesList:
      description: Array of property objects to get or set
      type: array
      items:
        $ref: '#/components/schemas/UserProperty'
    UserPropertyErrorList:
      description: Array of property keys with saving errors
      type: array
      items:
        $ref: '#/components/schemas/UserPropertyError'
    UserProperty:
      type: object
      required:
      - key
      - value
      properties:
        key:
          type: string
          example: my_property
        value:
          type: string
          example: my_value
    UserPropertyError:
      type: object
      description: One user property error info
      required:
      - key
      - error
      properties:
        key:
          type: string
          description: Property name (key)
        error:
          type: string
          description: Property error
    UserProperties:
      type: object
      required:
      - access_token
      - properties
      properties:
        access_token:
          type: string
        client_uid:
          type: string
          deprecated: true
        q_uid:
          type: string
        properties:
          type: object
          description: string-to-string map
          additionalProperties:
            type: string
            example:
              key: value
    SuccessResponseV1:
      type: object
      description: Success response for api v1
      required:
      - success
      - data
      properties:
        success:
          type: boolean
        data:
          type: object
    ErrorResponseV1:
      type: object
      description: Error for api v1
      required:
      - success
      - data
      properties:
        success:
          type: boolean
        data:
          $ref: '#/components/schemas/ErrorV1'
    ErrorV1:
      type: object
      required:
      - message
      - code
      properties:
        message:
          type: string
        code:
          type: integer
    Request.BaseUserRequest:
      type: object
      required:
      - access_token
      - q_uid
      - device
      properties:
        access_token:
          type: string
        q_uid:
          type: string
          example: QON_54f7a18750974b578560a21b7d79f203
        custom_uid:
          type: string
          example: partner_systems_client_uid
        device:
          $ref: '#/components/schemas/Request.UserRequest.Device'
        receipt:
          type: string
        debug_mode:
          description: Use "1", 1 or true for "sandbox"
        install_date:
          description: Use "123456" or 123456
        version:
          description: SDK version
          type: string
    Request.UserRequest:
      type: object
      allOf:
      - $ref: '#/components/schemas/Request.BaseUserRequest'
      - properties:
          purchases:
            type: array
            items:
              $ref: '#/components/schemas/Request.PurchaseMain'
    Request.UserRequest.Device:
      type: object
      required:
      - device_id
      - os
      properties:
        device_id:
          type: string
        os:
          type: string
        os_version:
          type: string
        app_version:
          type: string
        advertiser_id:
          type: string
        locale:
          description: Device language in ISO 639-1 standard language codes, like "en-US" [More](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
          type: string
        country:
          description: Device country name in ISO 3166-1 alpha-2 format [More](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2)
          type: string
        model:
          type: string
    Request.RestoreRequest:
      type: object
      allOf:
      - $ref: '#/components/schemas/Request.UserRequest'
      - required:
        - history
        properties:
          history:
            type: array
            items:
              $ref: '#/components/schemas/Request.RestoreRequest.HistoryItem'
    Request.RestoreRequest.HistoryItem:
      type: object
      required:
      - product
      - purchase_token
      - purchase_time
      properties:
        product:
          type: string
        purchase_token:
          type: string
        purchase_time:
          type: integer
          format: int64
    Request.IdentityRequest:
      type: object
      required:
      - anon_id
      - identity_id
      properties:
        anon_id:
          type: string
          example: QON_54f7a18750974b578560a21b7d79f203
        identity_id:
          type: string
          example: my-unique-user-1234
    Request.PurchaseRequest:
      type: object
      allOf:
      - $ref: '#/components/schemas/Request.UserRequest'
      - required:
        - purchase
        properties:
          purchase:
            $ref: '#/components/schemas/Request.PurchaseRequest.Purchase'
          introductory_offer:
            $ref: '#/components/schemas/Request.PurchaseRequest.IntroductoryOffer'
    Request.PurchaseMain:
      type: object
      required:
      - purchase
      properties:
        purchase:
          $ref: '#/components/schemas/Request.PurchaseRequest.Purchase'
        introductory_offer:
          $ref: '#/components/schemas/Request.PurchaseRequest.IntroductoryOffer'
    Request.PurchaseRequest.Purchase:
      type: object
      required:
      - product
      - purchase_time
      - transaction_id
      - original_transaction_id
      properties:
        product:
          type: string
          description: Store product id
          example: my_product_monthly
        product_id:
          type: string
          description: Qonversion product id
          example: my_product_monthly
        purchase_token:
          type: string
          description: Purchase token, required for Android
        purchase_time:
          description: Purchase timestamp
        currency:
          type: string
          description: Currency code according to [ISO4217 specification](https://en.wikipedia.org/wiki/ISO_4217)
          example: USD
        value:
          type: string
          example: '9.99'
        transaction_id:
          type: string
          example: GPA.1234-1234-1234-12345
        original_transaction_id:
          type: string
          example: GPA.1234-1234-1234-12345
        period_unit:
          description: '`0` for ''day''; `1` for ''week''; `2` for ''month''; `3` for ''year'''
        period_number_of_units:
          description: Period number of units
        context_keys:
          type: array
          items:
            type: string
          description: List of context keys to associate with the purchase
        screen_uid:
          type: string
          description: Identifier of the screen that the user is on when the purchase is made
    Request.PurchaseRequest.IntroductoryOffer:
      type: object
      description: Introductory offer or trial data
      required:
      - period_unit
      - period_number_of_units
      - number_of_periods
      - payment_mode
      properties:
        value:
          type: string
          example: '9.99'
          description: Introductory offer price or '0.0' for free trial
        period_unit:
          description: '`0` for ''day''; `1` for ''week''; `2` for ''month''; `3` for ''year'''
        period_number_of_units:
          description: Period number of units
        number_of_periods:
          description: Number of units
        payment_mode:
          description: '`0` for ''recurring''; `1` for ''single''; `2` for ''free trial'''
    Request.AttributionRequest:
      type: object
      required:
      - access_token
      - client_uid
      - provider_data
      properties:
        access_token:
          type: string
        client_uid:
          type: string
          example: QON_54f7a18750974b578560a21b7d79f203
        provider_data:
          type: object
          required:
          - provider
          properties:
            provider:
              type: string
              enum:
              - apple_adservices_token
            d:
              $ref: '#/components/schemas/Request.AttributionRequest.AppleAdservicesTokenData'
            uid:
              type: string
              description: Appsflyer ID (required when provider is `appsflyer`)
        version:
          type: string
          description: SDK version
    Request.AttributionRequest.AppleAdservicesTokenData:
      type: object
      required:
      - token
      - requested_at
      properties:
        token:
          type: string
        requested_at:
          type: number
          format: double
          example: 1679511962.196883
    UserResponse:
      type: object
      required:
      - timestamp
      - uid
      - products
      - user_products
      - permissions
      - offerings
      - products_permissions
      properties:
        timestamp:
          type: integer
          format: int64
        uid:
          type: string
          example: QON_54f7a18750974b578560a21b7d79f203
        products:
          type: array
          items:
            $ref: '#/components/schemas/UserResponse.Product'
        user_products:
          type: array
          items:
            $ref: '#/components/schemas/UserResponse.Product'
        permissions:
          type: array
          items:
            $ref: '#/components/schemas/UserResponse.Permission'
        offerings:
          type: array
          items:
            $ref: '#/components/schemas/UserResponse.Offering'
        products_permissions:
          type: object
          description: AKA project permissions
          additionalProperties:
            type: array
            items:
              type: string
          example:
            my.pro.monthly:
            - my.pro
            my.pro.yearly:
            - my.pro
            my.pro.max.monthly:
            - my.pro
            - my.max
        apple_extra:
          type: object
          required:
          - original_application_version
          properties:
            original_application_version:
              type: string
    UserResponse.Product:
      type: object
      required:
      - id
      - store_id
      - type
      - duration
      properties:
        id:
          type: string
        store_id:
          type: string
          nullable: true
        type:
          type: integer
          enum:
          - 0
          - 1
          - 2
          description: '`0` for subscription with trial; `1` for direct subscription; `2` for one-time
            purchase'
        duration:
          type: integer
          enum:
          - 0
          - 1
          - 2
          - 3
          - 4
          nullable: true
          description: '`0` for ''weekly''; `1` for ''monthly''; `2` for ''every 3 months''; `3` for ''every
            6 months''; `4` for ''annually'''
        base_plan_id:
          description: Available only for Google products
          type: string
          nullable: true
    UserResponse.Transaction:
      type: object
      required:
      - original_transaction_id
      - transaction_id
      - transaction_timestamp
      - type
      - ownership_type
      - environment
      properties:
        original_transaction_id:
          type: string
        transaction_id:
          type: string
        transaction_timestamp:
          type: integer
          format: int64
        expiration_timestamp:
          type: integer
          format: int64
          nullable: true
        environment:
          type: string
          enum:
          - sandbox
          - production
        type:
          type: string
          enum:
          - subscription_started
          - subscription_renewed
          - trial_started
          - intro_started
          - intro_renewed
          - non_consumable_purchase
        offer_code:
          type: string
          nullable: true
        ownership_type:
          type: string
          enum:
          - owner
          - family_shared
        transaction_revoke_timestamp:
          description: transaction revocation date. Refund or revoked from family sharing.
          type: integer
          format: int64
          nullable: true
        base_plan_id:
          type: string
          nullable: true
        promo_offer_id:
          type: string
          nullable: true
        offer_id:
          type: string
          nullable: true
    UserResponse.Permission:
      type: object
      required:
      - id
      - active
      - renew_state
      - associated_product
      - started_timestamp
      - expiration_timestamp
      - current_period_type
      - renews_count
      - store_transactions
      properties:
        id:
          type: string
        active:
          type: integer
          enum:
          - 0
          - 1
        renew_state:
          type: integer
          enum:
          - -1
          - 0
          - 1
          - 2
          - 3
          description: '`-1` for ''non-renewable''; `0` for ''unknown''; `1` for ''will renew''; `2` for
            ''canceled''; `3` for ''billing issue'''
        associated_product:
          type: string
        started_timestamp:
          type: integer
          format: int64
        expiration_timestamp:
          type: integer
          format: int64
          nullable: true
        current_period_type:
          type: string
          enum:
          - regular
          - trial
          - intro
          nullable: true
        renews_count:
          description: Renew is the second paid event. For example, 20 transactions, 1 trial, 1 trial
            converted. Renews count = 18.
          type: integer
        trial_start_timestamp:
          type: integer
          format: int64
          nullable: true
        first_purchase_timestamp:
          type: integer
          format: int64
          nullable: true
        last_purchase_timestamp:
          type: integer
          format: int64
          nullable: true
        last_activated_offer_code:
          type: string
          nullable: true
        grant_type:
          description: The reason the user received the current entitlement. Because of purchase, family
            sharing, offer code, or entitlement is given manually.
          type: string
          enum:
          - purchase
          - family_sharing
          - offer_code
          - manual
        auto_renew_disable_timestamp:
          type: integer
          format: int64
          nullable: true
        store_transactions:
          type: array
          items:
            $ref: '#/components/schemas/UserResponse.Transaction'
    UserResponse.Offering:
      type: object
      required:
      - id
      - tag
      - products
      properties:
        id:
          type: string
        tag:
          type: integer
          nullable: true
        products:
          type: array
          items:
            $ref: '#/components/schemas/UserResponse.Product'
        experiment:
          type: object
          required:
          - uid
          - attached
          properties:
            uid:
              type: string
            attached:
              type: boolean
    IdentityResponse:
      type: object
      required:
      - anon_id
      - identity_id
      properties:
        anon_id:
          type: string
          example: QON_54f7a18750974b578560a21b7d79f203
        identity_id:
          type: string
          example: my-unique-user-1234
    UserExperiment:
      type: object
      required:
      - group_id
      properties:
        group_id:
          type: string
    OfferSignatureRequest:
      type: object
      required:
      - app_bundle_id
      - product
      - app_account_token
      properties:
        app_bundle_id:
          type: string
          example: com.example.app
        product:
          type: string
          example: com.example.product
        app_account_token:
          type: string
    OfferSignatureResponse:
      type: object
      required:
      - signature
      - nonce
      - timestamp
      - key_identifier
      properties:
        signature:
          type: string
        nonce:
          type: string
        timestamp:
          type: integer
          format: int64
        key_identifier:
          type: string
    ChartData:
      type: object
      required:
      - code
      - from
      - to
      - unit
      - environment
      - seriesRelation
      - maxSeries
      - totalType
      - measure
      - horizontalLabelType
      - series
      properties:
        code:
          type: string
          description: Chart type identifier
          example: proceeds
        from:
          type: integer
          format: int64
          description: Start of time range (Unix timestamp)
          example: 1699000000
        to:
          type: integer
          format: int64
          description: End of time range (Unix timestamp)
          example: 1701000000
        unit:
          type: string
          enum:
          - hour
          - day
          - week
          - month
          description: Time grouping unit
          example: day
        environment:
          type: integer
          enum:
          - 0
          - 1
          description: Environment (0=Sandbox, 1=Production)
          example: 1
        seriesRelation:
          type: string
          enum:
          - partsOfWhole
          - independent
          description: '- partsOfWhole: Series sum to total

            - independent: Series are independent

            '
          example: partsOfWhole
        maxSeries:
          type: integer
          description: Maximum number of series
          example: 50
        totalType:
          type: string
          enum:
          - sum
          - wavg
          description: '- sum: Simple sum

            - wavg: Weighted average

            '
          example: sum
        measure:
          type: string
          enum:
          - usd
          - count
          - percent
          description: Unit of measurement
          example: usd
        horizontalLabelType:
          type: string
          description: Type of horizontal axis labels
          example: default
        segmentation:
          type: string
          nullable: true
          description: Dimension used for segmentation
          example: country
        summarySeries:
          $ref: '#/components/schemas/ChartSeries'
          nullable: true
        series:
          type: array
          description: Array of data series
          items:
            $ref: '#/components/schemas/ChartSeries'
    ChartSeries:
      type: object
      required:
      - label
      - data
      properties:
        label:
          type: string
          description: Series label
          example: After refunds
        total:
          type: number
          format: double
          nullable: true
          description: Total value for the series
          example: 380276.24
        totalPrev:
          type: number
          format: double
          nullable: true
          description: Previous period total
          example: 326882.25
        totalWeight:
          type: number
          format: double
          nullable: true
          description: Weight for weighted average calculation
        totalPrevWeight:
          type: number
          format: double
          nullable: true
          description: Previous period weight
        totalIgnoreInFinal:
          type: boolean
          nullable: true
          description: Whether to ignore this series in final calculations
          example: false
        data:
          type: array
          description: Array of data points
          items:
            $ref: '#/components/schemas/ChartDataPoint'
    ChartDataPoint:
      type: object
      required:
      - start_time
      - value
      properties:
        start_time:
          type: integer
          format: int64
          description: Start time of the data point (Unix timestamp)
          example: 1699000000
        value:
          type: number
          format: double
          description: Value at this data point
          example: 6163.49
  parameters:
    user_id:
      name: user_id
      in: path
      required: true
      description: User id
      example: 123e4567
      schema:
        type: string
    identity_id:
      name: identity_id
      in: path
      required: true
      description: Identity id
      example: my-own-id-01
      schema:
        type: string
    offer_id:
      name: offer_id
      in: path
      description: unique identifier of the offer
      required: true
      schema:
        type: string
    screen_id:
      name: screen_id
      in: path
      required: true
      description: Screen id
      example: rJer42wO
      schema:
        type: string
    context_key:
      name: context_key
      in: path
      required: true
      description: Context key
      example: my-context-key
      schema:
        type: string
tags:
- name: Users
  description: Retrieve Qonversion users
- name: User Properties
  description: Manage user-level attributes
- name: Identities
  description: Link Qonversion users to your own auth IDs
- name: Entitlements
  description: Entitlement definitions and user grants
- name: Purchases
  description: A user's purchase history
- name: Products
  description: Products configured in the Qonversion dashboard
- name: Remote Configurations
  description: Server-driven configuration payloads and targeting delivered to the SDK
- name: Customers
  description: Aggregated customer records, properties, permissions, and metrics
- name: Segments
  description: Dynamic and system segments of users
- name: Experiments
  description: Paywall and offering A/B experiments
- name: Screens
  description: No-code paywall screens — CRUD, publish, analytics
- name: Analytics
  description: Charts, cards, cohorts, LTV, and insights
- name: Exports
  description: Asynchronous data exports
- name: Events
  description: Event catalog
- name: Scheduled Reports
  description: Recurring reports delivered to external destinations
- name: Integrations
  description: Third-party integrations configuration
- name: Automations
  description: Event-driven automations
- name: Project Settings
  description: Project-level configuration, secret, and store credentials
