# List Contacts

POST /api/v2/projects/{projectId}/crm/contacts/query

Queries contacts with attribute and event filters, returning a page of contacts plus the total `count` matching the filter. A POST because the filter structure is too rich for a query string. This is the endpoint behind audience building. The same filter shape defines a dynamic contact list or a campaign audience.

## Request

- projectId: string, path, required — ID of the project to list contacts from.
- attributes: string[] — Property names to include on each contact. Omit for the default set. Narrowing this is the main lever for making large queries cheaper.
- contactIds: string[] — Restrict the result to these contact IDs.
- contactsFilterGroup: object — Attribute and event conditions the contact must satisfy. Omit to match every contact in the project.
  - filters: object[], required — Attribute filters combined with groupType.
    - attributeDistinctId: string, required — Contact attribute distinct id to filter on.
    - operator: equals | contains | notEquals | notContains | gt | gte | lt | lte | on | since | before | between | last, required — Comparison operator for the attribute value.
    - value: string, required — Value to compare the attribute against.
    - attributeType: string | number | boolean | date | url | email, default string — Attribute type. Defaults to string when omitted.
  - groupType: AND | OR | NOT, required — How filters in this group are combined.
  - oneDayEventFilters: object[] — Event filters evaluated over the last 24 hours only.
    - eventName: string, required — Analytics event name.
    - operator: performed | notPerformed, required — Whether the contact performed the event in the last 24 hours.
  - requireSubscribed: boolean — When true, the group is ANDed with `$subscribed == true`. Set by email sending, not the filter UI.
- includeCount: boolean, default true — When false, skip the Tinybird uniqExact count and return the page length. Use a follow-up tak
…

## Response

- 200: Successful response
  - count: number, required
  - data: object[], required
    - createdAt: string, required
    - distinctId: string, required
    - id: string, required
    - projectId: string, required
    - properties: object, required
    - toDelete: boolean, required
    - updatedAt: string, required
    - email: string
  - usage: object, required
    - cost: number, required
    - duration: number
    - metricCount: number
- 400: Invalid input data
- 401: Authorization not provided
- 403: Insufficient access
- 500: Internal server error
