Search contacts
Search contacts (customers and leads) with a structured filter AST, sorting, and cursor pagination.
Structured query AST
Each clause has the shape { field, operator, value }. You can pass a single clause or wrap up to 15 in a top-level AND group:
{
"query": {
"operator": "AND",
"value": [
{ "field": "type", "operator": "=", "value": "customer" },
{ "field": "lastActivity", "operator": ">", "value": 1735689600 }
]
},
"sort": "lastActivity:desc",
"limit": 20
}Top-level OR groups and nested groups are not supported in this version.
Supported fields and operators
Field names are camelCase, matching the rest of the v2 public API. Snake_case names that this endpoint originally shipped with (external_id, company_ids, posts_created, comments_created, last_activity, created_at) are still accepted for back-compat but are deprecated — please migrate to camelCase in new code.
| Field | Type | Operators |
|---|---|---|
externalId | string (caller-provided user id) | =, !=, IN, NIN |
email | string | =, !=, IN, NIN |
name | string | =, !=, IN, NIN, ~ |
type | enum (customer, lead) | =, !=, IN, NIN |
companyIds | id (Featurebase company id) | =, !=, IN, NIN |
postsCreated | number | =, !=, >, < |
commentsCreated | number | =, !=, >, < |
lastActivity | unix seconds | =, !=, >, < |
createdAt | unix seconds | =, !=, >, < |
The name ~ "..." operator runs a word-aware substring search via the underlying text index. Other string operators (!~, ^, $) are reserved for future use and currently return 400.
A query consisting only of != or NIN clauses on unbounded fields is rejected with query_too_broad to prevent full-org scans. Combine the negation with at least one positive clause (=, IN, >, <) instead. The closed-enum field type is exempt from this guard.
Contacts that have been merged into another contact (lead-to-customer rollup) are always excluded from results.
Sort
Allowed values:
lastActivity:desc(default),lastActivity:asccreatedAt:desc,createdAt:ascpostsCreated:desc,postsCreated:asccommentsCreated:desc,commentsCreated:asc
Snake_case sort axes (last_activity:desc, created_at:asc, etc.) are accepted for back-compat — the cursor encodes the canonical camelCase identity, so a caller can switch naming conventions mid-pagination without restarting.
The chosen sort axis is encoded in the cursor; switching sort mid-pagination returns 400 invalid_cursor. Restart pagination without a cursor when changing sort.
Pagination
Cursor-based, limit between 1 and 100 (default 10). totalCount is approximate and capped at 5000; totalCountCapped is true when the real count may be higher.
Response
Returns a standard list envelope with contact rows identical to GET /v2/contacts/{id}.
Version Availability
This endpoint is only available in API version 2026-01-01.nova and newer.
Body
An opaque cursor for pagination. Use the nextCursor value from a previous response to fetch the next page of results.
512eyJpZCI6IjUwN2YxZjc3YmNmODZjZDc5OTQzOTAxMSJ9A limit on the number of objects to be returned, between 1 and 100.
1 <= x <= 10010Structured filter AST. Either a single filter clause or one top-level AND group (max 15 clauses). Top-level OR groups are not yet supported.
Sort field + direction. Defaults to lastActivity:desc (matches the dashboard's default contact ordering). The chosen sort axis is encoded in the cursor; switching sort mid-pagination returns 400 invalid_cursor. Snake_case names (last_activity:desc, posts_created:asc, …) are accepted for back-compat — prefer camelCase in new code.
createdAt:desc, createdAt:asc, lastActivity:desc, lastActivity:asc, postsCreated:desc, postsCreated:asc, commentsCreated:desc, commentsCreated:asc, created_at:desc, created_at:asc, last_activity:desc, last_activity:asc, posts_created:desc, posts_created:asc, comments_created:desc, comments_created:asclastActivity:descResponse
Success
Cursor for fetching the next page (null if no more results)
eyJpZCI6IjUwN2YxZjc3YmNmODZjZDc5OTQzOTAxMSJ9Total number of contacts matching the query, capped at 5000. When the actual total is at or above the cap, totalCountCapped is true and the value is exactly the cap.
42