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

# Filter subscribers by engagement, sign-up date, state, and tags

> Searches your subscriber list with compound conditions: email engagement (opens, clicks, sends, deliveries — with count thresholds and date ranges), sign-up date, subscriber state, and tags. Every condition in the `all` array must match (AND logic).

Use `counting_mode` to control how engagement thresholds are tallied — `raw` (default) counts every event, `unique_email` counts distinct emails — and the `include` array to embed extra fields (tags, stats, custom fields, location, attribution, canceled_at) on each returned subscriber.

**Data retention:** Starting October 15, 2026, email stats (opens, clicks, sends, bounces, and unsubscribes) are available via the API for the last 5 years — engagement-condition date bounds are clamped to that window, and a `stats` include range outside it returns a `400` error. See [Email data retention](/api-reference/email-data-retention) for the full policy.



## OpenAPI

````yaml /api-reference/v4.json post /v4/subscribers/filter
openapi: 3.0.3
info:
  title: Kit API
  version: '4.0'
servers:
  - url: https://api.kit.com
security: []
paths:
  /v4/subscribers/filter:
    post:
      tags:
        - Subscribers
      summary: Filter subscribers by engagement, sign-up date, state, and tags
      description: >-
        Searches your subscriber list with compound conditions: email engagement
        (opens, clicks, sends, deliveries — with count thresholds and date
        ranges), sign-up date, subscriber state, and tags. Every condition in
        the `all` array must match (AND logic).


        Use `counting_mode` to control how engagement thresholds are tallied —
        `raw` (default) counts every event, `unique_email` counts distinct
        emails — and the `include` array to embed extra fields (tags, stats,
        custom fields, location, attribution, canceled_at) on each returned
        subscriber.


        **Data retention:** Starting October 15, 2026, email stats (opens,
        clicks, sends, bounces, and unsubscribes) are available via the API for
        the last 5 years — engagement-condition date bounds are clamped to that
        window, and a `stats` include range outside it returns a `400` error.
        See [Email data retention](/api-reference/email-data-retention) for the
        full policy.
      parameters: []
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubscriberFilterRequest'
            example:
              all:
                - type: opens
                  count_greater_than: 5
                  after: '2024-01-01'
                  before: '2024-12-31'
                - type: clicks
                  count_greater_than: 2
                  after: '2024-01-01'
                  before: '2024-12-31'
                  any:
                    - type: urls
                      urls:
                        - kit.com
                        - amazon.com
                      matching: contains
                    - type: broadcasts
                      ids:
                        - 1
                        - 2
                        - 3
                - type: tags
                  any:
                    - type: ids
                      matching:
                        - 123
                        - 456
                - type: attribution
                  any:
                    - type: forms
                      ids:
                        - 789
                        - 1001
                    - type: kit_source
                      source_type: api_subscription
                      source_ids:
                        - 555
                      source_names:
                        - Welcome
                      mechanism: import
                      mechanism_ids:
                        - 9
                - type: custom_field
                  subscriber_custom_field_id: 42
                  value: premium
                  comparison: is
      responses:
        '200':
          description: Returns a list of subscribers matching the filters
          content:
            application/json:
              schema:
                type: object
                properties:
                  subscribers:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        first_name:
                          type: string
                          nullable: true
                        email_address:
                          type: string
                        created_at:
                          type: string
                        tag_names:
                          type: array
                          items:
                            type: string
                        tag_ids:
                          type: array
                          items:
                            type: string
                        attribution:
                          type: object
                          nullable: true
                          description: Returned when `include` contains `attribution`.
                          properties:
                            referrer:
                              type: string
                              nullable: true
                            utm_source:
                              type: string
                              nullable: true
                            utm_medium:
                              type: string
                              nullable: true
                            utm_campaign:
                              type: string
                              nullable: true
                            utm_term:
                              type: string
                              nullable: true
                            utm_content:
                              type: string
                              nullable: true
                            source_type:
                              type: string
                              nullable: true
                            source_name:
                              type: string
                              nullable: true
                            source_mechanism:
                              type: string
                              nullable: true
                            source_mechanism_id:
                              type: integer
                              nullable: true
                        tags:
                          type: array
                          description: Returned when `include` contains `tags`.
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                        location:
                          type: object
                          nullable: true
                          description: Returned when `include` contains `location`.
                          properties:
                            city:
                              type: string
                              nullable: true
                            state:
                              type: string
                              nullable: true
                            country:
                              type: string
                              nullable: true
                            latitude:
                              type: number
                              nullable: true
                              format: float
                            longitude:
                              type: number
                              nullable: true
                              format: float
                            timezone:
                              type: string
                              nullable: true
                        canceled_at:
                          type: string
                          format: date-time
                          nullable: true
                          description: >-
                            Returned when `include` contains `canceled_at`.
                            Reflects the timestamp of the subscriber's most
                            recent state transition.
                        stats:
                          type: object
                          description: >-
                            Returned when `include` contains `stats`.
                            Per-subscriber email engagement over the requested
                            date range (defaults to the last 90 days). Counts
                            cover broadcasts, sequences, and email templates.
                            Subscribers with no sends in the range come back
                            with zeroed counts and null timestamps.
                          properties:
                            sent:
                              type: integer
                            opened:
                              type: integer
                            clicked:
                              type: integer
                            bounced:
                              type: integer
                            open_rate:
                              type: number
                              format: float
                              description: >-
                                opened / sent, rounded to 3 decimals (0.0 when
                                nothing was sent).
                            click_rate:
                              type: number
                              format: float
                              description: >-
                                clicked / sent, rounded to 3 decimals (0.0 when
                                nothing was sent).
                            last_sent:
                              type: string
                              format: date-time
                              nullable: true
                            last_opened:
                              type: string
                              format: date-time
                              nullable: true
                            last_clicked:
                              type: string
                              format: date-time
                              nullable: true
                            sends_since_last_open:
                              type: integer
                            sends_since_last_click:
                              type: integer
                        fields:
                          type: object
                          description: >-
                            Returned when `include` contains `custom_fields`.
                            All account custom field keys, with the subscriber's
                            value or null for fields that have not been set.
                          additionalProperties:
                            type: string
                            nullable: true
                      required:
                        - id
                        - first_name
                        - email_address
                        - created_at
                  pagination:
                    type: object
                    properties:
                      has_previous_page:
                        type: boolean
                      has_next_page:
                        type: boolean
                      start_cursor:
                        type: string
                      end_cursor:
                        type: string
                      per_page:
                        type: integer
                      total_count:
                        type: integer
                    required:
                      - has_previous_page
                      - has_next_page
                      - start_cursor
                      - end_cursor
                      - per_page
                required:
                  - subscribers
                  - pagination
              example:
                subscribers:
                  - id: '456'
                    first_name: Jane
                    email_address: jane@example.com
                    created_at: '2024-12-01T15:45:00Z'
                    tag_names:
                      - newsletter
                      - engaged
                    tag_ids:
                      - '123'
                      - '456'
                  - id: '789'
                    first_name: null
                    email_address: anonymous@example.com
                    created_at: '2024-11-15T10:00:00Z'
                    tag_names: []
                    tag_ids: []
                pagination:
                  has_previous_page: false
                  has_next_page: true
                  start_cursor: WzQ1Nl0=
                  end_cursor: Wzc4OV0=
                  per_page: 10
                  total_count: 42
        '401':
          description: Returns a 401 if the token and/or account cannot be authenticated
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - errors
              example:
                errors:
                  - The access token is invalid
      security:
        - API Key: []
        - OAuth2: []
components:
  schemas:
    SubscriberFilterRequest:
      type: object
      description: >-
        Filter subscribers based on engagement and subscription criteria using
        the 'all' array with filter conditions that must all be met (AND logic).
      properties:
        counting_mode:
          type: string
          enum:
            - raw
            - unique_email
          description: >-
            Controls how engagement-filter count thresholds are tallied. `raw`
            (default) counts every event — five opens of the same email = five.
            `unique_email` counts distinct emails on which the action occurred —
            five opens of the same email = one. Applies to every engagement
            filter (opens, clicks, sent, delivered) in the request; ignored for
            other filter types.
        all:
          type: array
          description: Array of filter conditions where ALL must be met (AND logic)
          items:
            $ref: '#/components/schemas/FilterCondition'
        include:
          type: array
          description: >-
            Optional. Array of `{ type, ...config }` objects naming additional
            fields to embed on each subscriber row. Valid types: `attribution`,
            `tags`, `location`, `canceled_at`, `stats`, `custom_fields`. The
            `stats` type accepts an optional `range: { start, end }` (YYYY-MM-DD
            dates, defaulting to the last 90 days). The `custom_fields` type
            adds a `fields` object with all account custom field values (null
            for fields the subscriber has not set).
          example:
            - type: tags
            - type: stats
              range:
                start: '2026-05-01'
                end: '2026-06-30'
          items:
            type: object
            required:
              - type
            properties:
              type:
                type: string
                enum:
                  - attribution
                  - tags
                  - location
                  - canceled_at
                  - stats
                  - custom_fields
              range:
                type: object
                description: >-
                  Only used by the `stats` type. Date window for the engagement
                  stats. Defaults to the last 90 days; clamped to the account's
                  data-retention window.
                properties:
                  start:
                    type: string
                    format: date
                  end:
                    type: string
                    format: date
      required:
        - all
    FilterCondition:
      type: object
      description: >-
        A filter condition with type and optional parameters. Used within the
        'all' array for complex filtering where multiple conditions must be met.
      properties:
        type:
          type: string
          enum:
            - opens
            - clicks
            - sent
            - delivered
            - subscribed
            - subscriber_state
            - tags
            - attribution
            - custom_field
            - location
          description: >-
            Type of filter condition. `attribution` matches subscribers by their
            *original signup attribution* — supports two sub-conditions: `forms`
            matches by the form / landing-page id the subscriber signed up
            through, and `kit_source` matches by any combination of the
            underlying Kit source fields (source type, source id, source name,
            mechanism, mechanism id). Attribution is the original signup source;
            it does not track current subscription state. `custom_field` matches
            subscribers by the value they have stored for a particular custom
            field, identified by `subscriber_custom_field_id`. `location`
            matches subscribers whose primary location falls within a `radius`
            (miles) of (`latitude`, `longitude`). All three fields are required.
        count_greater_than:
          type: integer
          description: >-
            Minimum count (exclusive). Only applicable for engagement types
            ('opens', 'clicks', 'sent', 'delivered').
        count_greater_than_or_equal:
          type: integer
          description: >-
            Minimum count (inclusive). Only applicable for engagement types
            ('opens', 'clicks', 'sent', 'delivered').
        count_less_than:
          type: integer
          description: >-
            Maximum count (exclusive). Only applicable for engagement types
            ('opens', 'clicks', 'sent', 'delivered').
        count_less_than_or_equal:
          type: integer
          description: >-
            Maximum count (inclusive). Only applicable for engagement types
            ('opens', 'clicks', 'sent', 'delivered').
        after:
          type: string
          format: date
          description: >-
            Start date (YYYY-MM-DD). For 'subscribed' type, filters by
            subscriber_created_at. For engagement types, filters by event date.
            Not applicable for 'tags', 'subscriber_state', 'attribution', or
            'custom_field' types.
        before:
          type: string
          format: date
          description: >-
            End date (YYYY-MM-DD). For 'subscribed' type, filters by
            subscriber_created_at. For engagement types, filters by event date.
            Not applicable for 'tags', 'subscriber_state', 'attribution', or
            'custom_field' types.
        states:
          type: array
          items:
            type: string
            enum:
              - active
              - inactive
              - bounced
              - cancelled
              - complained
          description: >-
            Subscriber lifecycle states. Required for 'subscriber_state' type;
            ignored for other types. Subscribers matching any of the listed
            states pass the filter. Strongly recommended to use `['active']`
            unless you specifically need other states — most subscriber-facing
            queries elsewhere in the app scope to active subscribers by default.
        subscriber_custom_field_id:
          type: integer
          description: >-
            Id of the custom field whose stored value is being filtered on.
            Required for 'custom_field' type; ignored for other types.
        value:
          type: string
          description: >-
            Value to compare against. Used by 'custom_field' type together with
            `comparison`. For the numeric comparisons (`greater_than`,
            `greater_than_or_equal`, `less_than`, `less_than_or_equal`) the
            value is parsed as a number; non-numeric stored values are excluded.
            Ignored when `comparison` is `has_value`.
        comparison:
          type: string
          enum:
            - is
            - contains
            - has_value
            - greater_than
            - greater_than_or_equal
            - less_than
            - less_than_or_equal
          description: >-
            How `value` is matched against the stored custom-field value. `is`
            is exact equality, `contains` is a case-insensitive substring (blank
            `value` matches any subscriber that has a value stored for the
            field), `has_value` matches any non-empty stored value (ignores
            `value`), `greater_than` / `greater_than_or_equal` / `less_than` /
            `less_than_or_equal` compare numerically. Only applicable for
            'custom_field' type.
        latitude:
          type: number
          format: float
          description: >-
            Center latitude (decimal degrees). Required for the 'location' type.
            Combined with `longitude` and `radius` to form a bounding box around
            the point.
        longitude:
          type: number
          format: float
          description: >-
            Center longitude (decimal degrees). Required for the 'location'
            type.
        radius:
          type: number
          description: >-
            Radius around (`latitude`, `longitude`) in miles. Required for the
            'location' type. Subscribers whose primary location falls inside the
            bounding box pass the filter.
        any:
          type: array
          description: >-
            Array of OR conditions. Subscriber activity must match ANY of these
            conditions. Engagement types accept broadcasts/URLs; 'tags' accepts
            tag id matchers; 'attribution' accepts attribution sub-conditions
            ('forms' or 'kit_source'). Not applicable for 'subscribed',
            'subscriber_state', 'custom_field', or 'location' types.
          items:
            oneOf:
              - $ref: '#/components/schemas/BroadcastAnyCondition'
                title: Broadcasts
              - $ref: '#/components/schemas/UrlAnyCondition'
                title: URLs (clicks only)
              - $ref: '#/components/schemas/IdsAnyCondition'
                title: Tag ids (tags only)
              - $ref: '#/components/schemas/FormsAnyCondition'
                title: Forms (attribution only)
              - $ref: '#/components/schemas/KitSourceAnyCondition'
                title: Kit source (attribution only)
      required:
        - type
    BroadcastAnyCondition:
      type: object
      description: >-
        Filter by specific broadcast IDs. Subscriber must have interacted with
        ANY of the specified broadcasts.
      properties:
        type:
          type: string
          enum:
            - broadcasts
          description: Must be 'broadcasts'
        ids:
          type: array
          items:
            type: integer
          description: Array of broadcast IDs. Subscriber must match ANY of these.
      required:
        - type
        - ids
    UrlAnyCondition:
      type: object
      description: >-
        Filter by URL patterns. Only applicable for 'clicks' type. Subscriber
        must have clicked ANY of the specified URLs.
      properties:
        type:
          type: string
          enum:
            - urls
          description: Must be 'urls'
        ids:
          type: array
          items:
            type: integer
          description: Array of URL IDs. Subscriber must have clicked ANY of these.
        urls:
          type: array
          items:
            type: string
          description: Array of URL patterns. Subscriber must have clicked ANY of these.
        matching:
          type: string
          enum:
            - exact
            - contains
            - starts_with
            - ends_with
          description: URL matching strategy
          default: exact
      required:
        - type
    IdsAnyCondition:
      type: object
      description: Match a list of ids. Used by the 'tags' filter to select tag ids.
      properties:
        type:
          type: string
          enum:
            - ids
          description: Must be 'ids'
        matching:
          type: array
          items:
            type: integer
          description: Ids the filter should match against.
      required:
        - type
        - matching
    FormsAnyCondition:
      type: object
      description: >-
        Attribution sub-condition: matches subscribers whose original signup
        attribution points at one of the given form / landing-page ids. Ids may
        refer to either a form or a legacy landing page — the attribution source
        does not distinguish between the two.
      properties:
        type:
          type: string
          enum:
            - forms
          description: Must be 'forms'
        ids:
          type: array
          items:
            type: integer
          description: Form / landing-page ids the subscriber's attribution should match.
      required:
        - type
        - ids
    KitSourceAnyCondition:
      type: object
      description: >-
        Attribution sub-condition: matches subscribers whose original signup
        attribution row matches any combination of the supplied Kit source
        fields. All fields are optional; supplied fields are ANDed together
        against the same attribution row, and array fields (`source_ids`,
        `source_names`, `mechanism_ids`) match any value in the array. Known
        `source_type` values include `form_subscription` (form / landing-page
        signup), `api_subscription` (added via the API), and `manual` (added by
        the creator). Multiple entries in the parent `attribution` filter's
        `any` array are OR-ed together (consistent with `any` semantics
        elsewhere in this endpoint), so use separate entries to express
        "kit_source A OR kit_source B".
      properties:
        type:
          type: string
          enum:
            - kit_source
          description: Must be 'kit_source'
        source_type:
          type: string
          description: Match attribution rows whose `kit_source_type` equals this value.
        source_ids:
          type: array
          items:
            type: integer
          description: Match attribution rows whose `kit_source_id` is in this list.
        source_names:
          type: array
          items:
            type: string
          description: Match attribution rows whose `kit_source_name` is in this list.
        mechanism:
          type: string
          description: >-
            Match attribution rows whose `kit_source_mechanism` equals this
            value.
        mechanism_ids:
          type: array
          items:
            type: integer
          description: >-
            Match attribution rows whose `kit_source_mechanism_id` is in this
            list.
      required:
        - type
  securitySchemes:
    API Key:
      description: Authenticate API requests via an API Key
      type: apiKey
      in: header
      name: X-Kit-Api-Key
    OAuth2:
      description: Authenticate API requests via an OAuth token
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://api.kit.com/v4/oauth/authorize
          tokenUrl: https://api.kit.com/v4/oauth/token
          refreshUrl: https://api.kit.com/v4/oauth/token
          scopes:
            read: Read access to Kit API v4
            write: Write access to Kit API v4

````