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

# Get customers list

> Retrieve a paginated list of customers with optional filters and search.

Example:
```bash
curl "https://api.qonversion.io/v1/analytics/JFPATc4VaaWYsfurml3qZ4zsmNw0VfWH/customers?page=1&limit=20&sort_by=since&sort_order=desc&environment=1"
```

**Pagination:** Pages are 1-based at the public boundary. `page=1` returns the first page. Compute `total_pages` from the response as `ceil(total_count / limit)`; the response itself does not contain a `total_pages` field.




## OpenAPI

````yaml /api-reference/analytics-api.yaml get /{projectApiKey}/customers
openapi: 3.0.3
info:
  title: Qonversion Public Analytics API
  description: >
    Public API for accessing Qonversion analytics chart data and customer
    information.


    ## Quick Start


    1. Find your **Project API Key** in the Qonversion dashboard.

    2. Use it in the URL path of any analytics endpoint, for example:
       `https://api.qonversion.io/v1/analytics/{YOUR_PROJECT_API_KEY}/chart/proceeds`.
    3. No additional authentication headers are required.


    ## Where to find your API Key


    1. Sign in to the Qonversion dashboard at https://dash.qonversion.io/.

    2. Open your project, then go to **Project Settings** in the left sidebar.

    3. In the **Project Keys** section, copy the value labelled **API Key**.
       The **Project Key** field above it is the SDK key and will not authorize this API.

    The API Key is a 32-character alphanumeric string (for example,
    `JFPATc4VaaWYsfurml3qZ4zsmNw0VfWH`). It contains no fixed prefix.


    ## Authentication


    Authentication is done via the **Project API Key** in the URL path. This key
    both identifies your project and authorizes access to its analytics data. No
    `Authorization` header or query token is needed.


    **Sandbox mode is not supported by this API.** Project API Keys prefixed
    with `test_` are accepted, but the prefix is stripped and the request is
    processed as production. Use your production key.


    **Security:** Treat your Project API Key as a secret. Do not embed it in
    client-side or mobile-app code, and do not commit it to public repositories.


    ## Rate Limiting


    - **Limit:** 30 requests per minute per project (`Analytics` rate limit).

    - **Response:** HTTP 429 when the limit is exceeded. The 429 response
    carries `Retry-After: 60` so clients can honour the standard back-off
    header.

    - **Cache fallback:** If the gateway has a recent successful response cached
    for the same path + query, it is returned instead of 429 with header
    `X-Cache: HIT`. Caches expire after 5 minutes.

    - **Recommendation:** Honour `Retry-After` and implement exponential backoff
    in your client.


    ## Available Charts


    Four chart endpoints are exposed publicly:


    - **`proceeds`** - revenue and proceeds metrics. Supports all filters and
    segmentation.

    - **`users-overview`** - user acquisition and retention. Supports user
    filters and segmentation. Does NOT support product filters.

    - **`paid-subscriptions-movement`** - subscription transitions (new,
    renewed, churned). Supports common + product filters only. Does NOT support
    segmentation, `filter[user_id]`, or `filter[device_id]`.

    - **`active-subscriptions`** - currently active subscribers. Supports
    product filters and segmentation. Does NOT support `filter[user_id]` or
    `filter[device_id]`.


    ## Client Generation


    This OpenAPI specification is designed for generating type-safe clients.
    Tools you can use:

    - [openapi-generator](https://openapi-generator.tech/)

    - [swagger-codegen](https://swagger.io/tools/swagger-codegen/)


    ## Example Request


    ```bash

    curl
    "https://api.qonversion.io/v1/analytics/JFPATc4VaaWYsfurml3qZ4zsmNw0VfWH/chart/proceeds?from=1699000000&to=1701000000&unit=day&environment=1"

    ```


    Replace the path segment with your own 32-character API Key.


    ## Response Format


    **Success (200):**

    ```json

    {
      "data": {
        "code": "proceeds",
        "from": 1699000000,
        "to": 1701000000,
        "unit": "day",
        "environment": 1,
        "currency": "USD",
        "series": []
      }
    }

    ```


    **Error (4xx/5xx):**

    ```json

    {
      "error": {
        "code": "validation_error",
        "message": "Unprocessable request params",
        "type": "request"
      },
      "meta": {
        "reference": "https://documentation.qonversion.io/reference/handling-api-errors"
      }
    }

    ```
  version: 1.0.0
  contact:
    name: Qonversion API Support
    url: https://documentation.qonversion.io
    email: support@qonversion.io
servers:
  - url: https://api.qonversion.io/v1/analytics
    description: Production server
security: []
tags:
  - name: Analytics Charts
    description: Dedicated endpoints for each analytics chart type
  - name: Customers
    description: Endpoints for retrieving customer data and aggregated customer metrics
paths:
  /{projectApiKey}/customers:
    get:
      tags:
        - Customers
      summary: Get customers list
      description: >
        Retrieve a paginated list of customers with optional filters and search.


        Example:

        ```bash

        curl
        "https://api.qonversion.io/v1/analytics/JFPATc4VaaWYsfurml3qZ4zsmNw0VfWH/customers?page=1&limit=20&sort_by=since&sort_order=desc&environment=1"

        ```


        **Pagination:** Pages are 1-based at the public boundary. `page=1`
        returns the first page. Compute `total_pages` from the response as
        `ceil(total_count / limit)`; the response itself does not contain a
        `total_pages` field.
      operationId: getCustomersList
      parameters:
        - $ref: '#/components/parameters/ProjectApiKey'
        - name: page
          in: query
          required: false
          description: Page number (1-based). Page 1 is the first page.
          schema:
            type: integer
            minimum: 1
            default: 1
        - name: limit
          in: query
          required: false
          description: Items per page. Capped at 100.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: sort_by
          in: query
          required: false
          description: >-
            Field to sort by. Allowed values are tied to the underlying customer
            index.
          schema:
            type: string
            enum:
              - since
              - status
              - last_payment_at
              - purchase_currency
              - payments_count
              - net_payments_usd
              - purchase_product_id
            default: since
        - name: sort_order
          in: query
          required: false
          description: Sort direction.
          schema:
            type: string
            enum:
              - asc
              - desc
            default: desc
        - name: environment
          in: query
          required: false
          description: >-
            Environment type (0=Sandbox, 1=Production). Sandbox keys are not
            supported by this API; production keys returning environment=0 will
            yield no data.
          schema:
            type: integer
            enum:
              - 0
              - 1
            default: 1
        - name: search
          in: query
          required: false
          description: >-
            Universal search across email, transaction id, firebase id, custom
            user id, device id, and Qonversion user id. Forwarded to the backend
            as `search_all`.
          schema:
            type: string
            maxLength: 255
        - name: search_key
          in: query
          required: false
          description: >-
            Targeted search field. Use together with `search_value`. Forwarded
            as `advanced_key`.
          schema:
            type: string
            enum:
              - email
              - firebaseID
              - transactionID
              - customerUserID
              - deviceID
        - name: search_value
          in: query
          required: false
          description: >-
            Value to match for the targeted `search_key`. Forwarded as
            `advanced_value`.
          schema:
            type: string
        - $ref: '#/components/parameters/FilterSinceRange'
        - $ref: '#/components/parameters/FilterStatus'
        - $ref: '#/components/parameters/FilterTargetPlatform'
        - $ref: '#/components/parameters/FilterCountry'
        - $ref: '#/components/parameters/FilterProductId'
        - $ref: '#/components/parameters/FilterPurchaseCurrency'
        - $ref: '#/components/parameters/FilterLocale'
        - $ref: '#/components/parameters/FilterModel'
        - $ref: '#/components/parameters/FilterOsVersion'
        - $ref: '#/components/parameters/FilterAppVersion'
        - $ref: '#/components/parameters/FilterSdkVersion'
        - $ref: '#/components/parameters/FilterMediaSourceName'
        - $ref: '#/components/parameters/FilterCampaignName'
        - $ref: '#/components/parameters/FilterAdSetName'
        - $ref: '#/components/parameters/FilterAdName'
        - $ref: '#/components/parameters/FilterExperimentUid'
        - $ref: '#/components/parameters/FilterExperimentGroupUid'
      responses:
        '200':
          description: Successful response with paginated customer list
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomersListResponse'
        '400':
          description: Bad request - invalid parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized - invalid or missing Project API Key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Too many requests - rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    ProjectApiKey:
      name: projectApiKey
      in: path
      required: true
      description: >-
        Project API Key for authentication and project identification. A
        32-character alphanumeric string copied from Project Settings -> Project
        Keys -> API Key in https://dash.qonversion.io/. The key has no fixed
        prefix.
      schema:
        type: string
        minLength: 1
        example: JFPATc4VaaWYsfurml3qZ4zsmNw0VfWH
    FilterSinceRange:
      name: filter[since][]
      in: query
      required: false
      description: >-
        Date-range filter on customer first-seen time. Pass exactly two values:
        `filter[since][]=<from_unix_ts>&filter[since][]=<to_unix_ts>`. If
        omitted, both bounds default to the current time and the result will be
        empty.
      schema:
        type: array
        items:
          type: integer
          format: int64
        minItems: 2
        maxItems: 2
      style: form
      explode: true
    FilterStatus:
      name: filter[status][]
      in: query
      required: false
      description: |
        Filter by customer status. Numeric codes:
        - 1 = Trial / Intro
        - 2 = Active
        - 3 = Canceled
        - 4 = Billing Retry
      schema:
        type: array
        items:
          type: string
          enum:
            - '1'
            - '2'
            - '3'
            - '4'
      style: form
      explode: true
    FilterTargetPlatform:
      name: filter[target_platform][]
      in: query
      required: false
      description: Filter by platforms.
      schema:
        type: array
        items:
          type: string
          enum:
            - iOS
            - Android
            - Stripe
      style: form
      explode: true
    FilterCountry:
      name: filter[country][]
      in: query
      required: false
      description: Filter by countries (ISO 3166-1 alpha-2).
      schema:
        type: array
        items:
          type: string
          pattern: ^[A-Z]{2}$
      style: form
      explode: true
    FilterProductId:
      name: filter[product_id][]
      in: query
      required: false
      description: Filter by product IDs.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterPurchaseCurrency:
      name: filter[purchase_currency][]
      in: query
      required: false
      description: Filter by purchase currencies (ISO 4217).
      schema:
        type: array
        items:
          type: string
          pattern: ^[A-Z]{3}$
      style: form
      explode: true
    FilterLocale:
      name: filter[locale][]
      in: query
      required: false
      description: Filter by locales.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterModel:
      name: filter[model][]
      in: query
      required: false
      description: Filter by device models.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterOsVersion:
      name: filter[os_version][]
      in: query
      required: false
      description: Filter by OS versions.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterAppVersion:
      name: filter[app_version][]
      in: query
      required: false
      description: Filter by app versions.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterSdkVersion:
      name: filter[sdk_version][]
      in: query
      required: false
      description: Filter by SDK versions.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterMediaSourceName:
      name: filter[media_source_name][]
      in: query
      required: false
      description: Filter by media source names.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterCampaignName:
      name: filter[campaign_name][]
      in: query
      required: false
      description: Filter by campaign names.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterAdSetName:
      name: filter[ad_set_name][]
      in: query
      required: false
      description: Filter by ad set names.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterAdName:
      name: filter[ad_name][]
      in: query
      required: false
      description: Filter by ad names.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterExperimentUid:
      name: filter[experiment_uid][]
      in: query
      required: false
      description: Filter by experiment UIDs.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
    FilterExperimentGroupUid:
      name: filter[experiment_group_uid][]
      in: query
      required: false
      description: Filter by experiment group UIDs.
      schema:
        type: array
        items:
          type: string
      style: form
      explode: true
  schemas:
    CustomersListResponse:
      type: object
      required:
        - data
      description: >-
        Top-level envelope for `/customers`. Pagination is reported inside
        `data` as `total_count` and the echoed `page`; clients compute
        `total_pages` from `ceil(total_count / limit)`.
      properties:
        data:
          type: object
          required:
            - total_count
            - items
            - page
          properties:
            total_count:
              type: integer
              description: Total number of customers matching the filters across all pages.
              example: 1542
            items:
              type: array
              description: Customer entries for the current page.
              items:
                $ref: '#/components/schemas/Customer'
            page:
              type: integer
              description: Echoed 1-based page number from the request.
              example: 1
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
            - type
          properties:
            code:
              type: string
              description: Machine-readable error code.
              example: validation_error
            message:
              type: string
              description: Human-readable error message.
              example: Unprocessable request params
            type:
              type: string
              description: High-level error class.
              example: request
        meta:
          type: object
          nullable: true
          description: >-
            Optional metadata. May contain a `reference` URL pointing to
            documentation for the error code.
          additionalProperties: true
          example:
            reference: https://documentation.qonversion.io/reference/handling-api-errors
    Customer:
      type: object
      description: >-
        Customer entry as returned by `/customers`. Field names are kept stable
        for backward compatibility with the dashboard.
      properties:
        client_id:
          type: integer
          format: int64
          description: Internal numeric customer ID.
          example: 12345
        client_uid:
          type: string
          nullable: true
          description: >-
            Qonversion user ID (the SDK-issued user UID). May be empty when the
            underlying ClickHouse aggregate (`any(uid)`) returns no value for
            the customer.
          example: QON_abc123def456
        external_identity:
          type: string
          nullable: true
          description: >-
            Custom identity attached via `Qonversion.identify()` in the SDK, if
            any.
          example: user_42
        custom_uid:
          type: string
          nullable: true
          description: >-
            Custom user property `_q_custom_user_id` if set, falling back to the
            legacy `client_custom_uid` column.
          example: user_42
        since:
          type: integer
          format: int64
          description: First-seen timestamp (Unix seconds).
          example: 1699000000
        last_payment_at:
          type: integer
          format: int64
          description: >-
            Most recent paid-transaction timestamp (Unix seconds). 0 if the
            customer has never paid.
          example: 1701000000
        first_transaction_purchase_at:
          type: integer
          format: int64
          description: >-
            First paid-transaction timestamp (Unix seconds). 0 if no purchase
            has occurred.
          example: 1700000000
        payments_count:
          type: integer
          description: Number of paid transactions.
          example: 3
        purchase_currency:
          type: string
          description: Currency of the most recent purchase (ISO 4217), or empty string.
          example: USD
        purchase_product_id:
          type: string
          description: Product ID of the most recent purchase.
          example: premium_monthly
        net_payments_usd:
          type: number
          format: double
          description: Net payments in USD (sales minus refunds).
          example: 49.99
        status:
          type: integer
          enum:
            - 0
            - 1
            - 2
            - 3
            - 4
          description: |
            Subscription status:
            - 0 = Unknown / never had a tracked status event
            - 1 = Trial / Intro
            - 2 = Active
            - 3 = Canceled
            - 4 = Billing Retry
          example: 2
        trial_status:
          type: integer
          enum:
            - 0
            - 1
            - 2
            - 3
          description: |
            Trial status:
            - 0 = No trial
            - 1 = Trial started
            - 2 = Trial converted
            - 3 = Trial canceled / expired
          example: 2
        client_country:
          type: string
          description: Country code (ISO 3166-1 alpha-2).
          example: US
        device_model:
          type: string
          description: Latest device model string.
          example: iPhone15,2
        device_id:
          type: string
          description: Latest device ID.
          example: ABCDEF12-3456
        target_platform:
          type: string
          enum:
            - iOS
            - Android
            - Stripe
          description: Latest platform.
          example: iOS
        device_os_version:
          type: string
          description: Latest OS version string.
          example: '17.4'

````