---
title: "POST /api/lead-lists/audience/preview"
method: POST
path: "/api/lead-lists/audience/preview"
tags: ["lead-lists"]
---

# POST /api/lead-lists/audience/preview

`POST /api/lead-lists/audience/preview`

## Request

- Base URL: `https://app.heykairon.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.heykairon.com/api/lead-lists/audience/preview`
- Auth: API key in header `x-api-key`

## Request body

- AudiencePreviewDto
  - `audience` object, required
    - `include` object, required: Who the rule selects. Required — a rule with only an exclude would select everyone and then take some away, which is never what an operator means.
      - `match` 'all' | 'any', required: How this group's conditions join. `all` means a lead must satisfy EVERY condition; `any` means one is enough. Inside a single condition the fields always AND and the values in a field always OR, whatever `match` says — so `{ crmStage: ['on_hold','lost'], tagId: ['t1'] }` reads as (on_hold OR lost) AND t1.
      - `conditions` object[], required: The conditions this group joins, 1 to 10. Each must name at least one field; an empty condition is refused rather than read as 'everyone'.
        - `crmStage` string[]: Keep leads standing at ANY of these Pipeline columns. `on_hold` is the parked pile — people a campaign ran out of things to say to, or whose conversation went quiet for two weeks. `new` is NOT 'people arriving': it is every lead nobody has worked yet, including every CSV row ever imported, so a rule over it can select tens of thousands.
        - `tagId` union
          - string
          - string[]
        - `ownerId` union
          - string
          - string[]
        - `qualificationStatus` union: Keep leads whose ICP verdict is ANY of these. A lead the audience adds can still be qualified afterwards like any other member — `list_qualify` works on an audience list exactly as it does on a hand-made one.
          - string
          - string[]
        - `lastContacted` string: Keep leads last contacted inside this window — `7d`, `30d`, `90d`, `never`, or `YYYY-MM-DD..YYYY-MM-DD`. Counts BOTH a campaign send and a message in the chat. This is the field that makes an `exclude` group safe: `exclude` + `lastContacted: '30d'` is how you say 'nobody who heard from me this month'. Resolved against the clock at every evaluation, so a stored `30d` always means the 30 days before tonight's run, never the 30 days before the day you saved it.
        - `companyId` union
          - string
          - string[]
        - `createdAfter` string, date-time: Keep only leads that ARRIVED in the org after this instant (ISO-8601, e.g. `2026-09-21T00:00:00.000Z`). This is what 'the people coming in' means: `crmStage: ['new']` on its own is the whole untouched backlog — every CSV row ever imported — which in the largest orgs is tens of thousands of people who have been sitting there for a year. Pair the two: `{ crmStage: ['new'], createdAfter: '<now>' }` is a flow for people who arrive from here on. An ABSOLUTE instant, not a rolling window, so the audience does not quietly forget the people it admitted last month.
    - `exclude` object: Who to take back OUT of that selection. Optional, and evaluated as `include AND NOT exclude`, so both apply at once. A lead the exclude cannot decide about — no owner on file when you exclude by owner, no employer when you exclude by company — is KEPT, not dropped.
      - `match` 'all' | 'any', required: How this group's conditions join. `all` means a lead must satisfy EVERY condition; `any` means one is enough. Inside a single condition the fields always AND and the values in a field always OR, whatever `match` says — so `{ crmStage: ['on_hold','lost'], tagId: ['t1'] }` reads as (on_hold OR lost) AND t1.
      - `conditions` object[], required: The conditions this group joins, 1 to 10. Each must name at least one field; an empty condition is refused rather than read as 'everyone'.
        - `crmStage` string[]: Keep leads standing at ANY of these Pipeline columns. `on_hold` is the parked pile — people a campaign ran out of things to say to, or whose conversation went quiet for two weeks. `new` is NOT 'people arriving': it is every lead nobody has worked yet, including every CSV row ever imported, so a rule over it can select tens of thousands.
        - `tagId` union
          - string
          - string[]
        - `ownerId` union
          - string
          - string[]
        - `qualificationStatus` union: Keep leads whose ICP verdict is ANY of these. A lead the audience adds can still be qualified afterwards like any other member — `list_qualify` works on an audience list exactly as it does on a hand-made one.
          - string
          - string[]
        - `lastContacted` string: Keep leads last contacted inside this window — `7d`, `30d`, `90d`, `never`, or `YYYY-MM-DD..YYYY-MM-DD`. Counts BOTH a campaign send and a message in the chat. This is the field that makes an `exclude` group safe: `exclude` + `lastContacted: '30d'` is how you say 'nobody who heard from me this month'. Resolved against the clock at every evaluation, so a stored `30d` always means the 30 days before tonight's run, never the 30 days before the day you saved it.
        - `companyId` union
          - string
          - string[]
        - `createdAfter` string, date-time: Keep only leads that ARRIVED in the org after this instant (ISO-8601, e.g. `2026-09-21T00:00:00.000Z`). This is what 'the people coming in' means: `crmStage: ['new']` on its own is the whole untouched backlog — every CSV row ever imported — which in the largest orgs is tens of thousands of people who have been sitting there for a year. Pair the two: `{ crmStage: ['new'], createdAfter: '<now>' }` is a flow for people who arrive from here on. An ABSOLUTE instant, not a rolling window, so the audience does not quietly forget the people it admitted last month.

## Response `200`

---

[API](https://skmtc.dev/heykairon/apis/kairon-api.md) · [All operations](https://skmtc.dev/heykairon/apis/kairon-api/llms.txt) · [OpenAPI document](https://skmtc.dev/heykairon/apis/kairon-api/revisions/35de550d5938?raw)
