Contacts

Filter contacts

List contacts with filters sent in the request body. Accepts a Prisma-shaped `where` clause, an optional geographic `near` radius, and pagination. Returns the same shape as `GET /v2/contacts/` with an

POST /v2/contacts/filter

Building a where filter? See the Filtering contacts guide for every key, its value shapes, and end-to-end examples.

Request body

Content-Type: application/json

take
integer
skip
integer
cursor
string (uuid)
where
object
where.in
string (uuid)
where.not_in
string (uuid)
where.ignore_merge
boolean
Filter by the ignore_merge flag (excluded from merge suggestions).
where.is_starred
boolean
Match starred (true) or non-starred (false) contacts.
where.is_archived
boolean
Match archived (true) or active (false) contacts. Defaults to false when omitted.
where.has_priority_tier
integer
where.has_linkedin
string
where.has_instagram
string
where.has_twitter
string
where.has_source
string
where.has_name
string
where.has_groups
object
where.has_groups.not
string
where.has_user_created_groups
boolean
Non-system group membership: true for at least one user-created group; false for no user-created groups, including contacts with zero memberships or only Dex system-group memberships.
where.has_grouping_signal
boolean enum
Internal organize prefilter: title, company, location, or LinkedIn summary is non-null and non-empty. Whitespace-only values are removed by the organize serializer.Possible values: true
where.has_groups_all
array<array>
Array of group-id rows: AND across rows, OR within each row (contact must be in at least one group from every row).
where.has_frequency
string
where.has_location
string
where.has_location_exact
string
Location: exact string match (not fuzzy).
where.has_job_title
string
where.has_never_keep_in_touch
boolean
Filter by the never_keep_in_touch flag.
where.has_created_at
object
Creation-date range: { gte?, lte? } ISO 8601 datetimes (at least one bound required).
where.has_created_at.gte
string (date-time)
where.has_created_at.lte
string (date-time)
where.has_updated_at
object
Last-updated-date range: { gte?, lte? } ISO 8601 datetimes (at least one bound required).
where.has_updated_at.gte
string (date-time)
where.has_updated_at.lte
string (date-time)
where.has_birthday
string (date-time)
where.has_tag
string (uuid)
Match contacts carrying this single tag id.
where.has_tags
array<string (uuid)>
where.has_tags_all
array<array>
Array of tag-id rows: AND across rows, OR within each row (contact must carry at least one tag from every row).
where.has_company
string
where.has_education
string
where.has_description
string
where.has_linkedin_companies
string
where.has_linkedin_education
string
where.has_email
boolean
Match contacts that have (true) or lack (false) at least one email.
where.has_phone_number
boolean
Match contacts that have (true) or lack (false) at least one phone number.
where.not_has_name
string
where.not_has_company
string
where.not_has_job_title
string
where.not_has_education
string
where.not_has_description
string
where.not_has_linkedin_companies
string
where.not_has_linkedin_education
string
where.has_linkedin_last_message_at
boolean
where.has_last_seen_at
boolean
where.has_distance
object
Geo radius filter: contacts within meters of { lat, lon } (PostGIS ST_DWithin on geocoded coordinates). label is an optional display name for the point.
where.has_distance.lat
number
where.has_distance.lon
number
where.has_distance.meters
number
where.has_distance.label
string
where.has_interaction
boolean
where.has_next_reminder
boolean
where.custom_fields
array<object>
User-defined custom-field filters. Each clause is { field_id, operator, value? }; multiple clauses AND together. Operators: contains, eq, in, not_in, present, absent, gte, lte.
where.custom_fields[].field_id
string (uuid)
where.custom_fields[].operator
string enum
Possible values: "contains", "eq", "in", "not_in", "present", "absent", "gte", "lte"
where.custom_fields[].value
string
where._or
array<object>
Compound-OR escape hatch: an array of filter branches combined with OR, each ANDed with the top-level keys. One level deep — branches cannot themselves contain _or.
where._or[].in
string (uuid)
where._or[].not_in
string (uuid)
where._or[].ignore_merge
boolean
Filter by the ignore_merge flag (excluded from merge suggestions).
where._or[].is_starred
boolean
Match starred (true) or non-starred (false) contacts.
where._or[].is_archived
boolean
Match archived (true) or active (false) contacts. Defaults to false when omitted.
where._or[].has_priority_tier
integer
where._or[].has_linkedin
string
where._or[].has_instagram
string
where._or[].has_twitter
string
where._or[].has_source
string
where._or[].has_name
string
where._or[].has_groups
object
where._or[].has_groups.not
string
where._or[].has_user_created_groups
boolean
Non-system group membership: true for at least one user-created group; false for no user-created groups, including contacts with zero memberships or only Dex system-group memberships.
where._or[].has_grouping_signal
boolean enum
Internal organize prefilter: title, company, location, or LinkedIn summary is non-null and non-empty. Whitespace-only values are removed by the organize serializer.Possible values: true
where._or[].has_groups_all
array<array>
Array of group-id rows: AND across rows, OR within each row (contact must be in at least one group from every row).
where._or[].has_frequency
string
where._or[].has_location
string
where._or[].has_location_exact
string
Location: exact string match (not fuzzy).
where._or[].has_job_title
string
where._or[].has_never_keep_in_touch
boolean
Filter by the never_keep_in_touch flag.
where._or[].has_created_at
object
Creation-date range: { gte?, lte? } ISO 8601 datetimes (at least one bound required).
where._or[].has_created_at.gte
string (date-time)
where._or[].has_created_at.lte
string (date-time)
where._or[].has_updated_at
object
Last-updated-date range: { gte?, lte? } ISO 8601 datetimes (at least one bound required).
where._or[].has_updated_at.gte
string (date-time)
where._or[].has_updated_at.lte
string (date-time)
where._or[].has_birthday
string (date-time)
where._or[].has_tag
string (uuid)
Match contacts carrying this single tag id.
where._or[].has_tags
array<string (uuid)>
where._or[].has_tags_all
array<array>
Array of tag-id rows: AND across rows, OR within each row (contact must carry at least one tag from every row).
where._or[].has_company
string
where._or[].has_education
string
where._or[].has_description
string
where._or[].has_linkedin_companies
string
where._or[].has_linkedin_education
string
where._or[].has_email
boolean
Match contacts that have (true) or lack (false) at least one email.
where._or[].has_phone_number
boolean
Match contacts that have (true) or lack (false) at least one phone number.
where._or[].not_has_name
string
where._or[].not_has_company
string
where._or[].not_has_job_title
string
where._or[].not_has_education
string
where._or[].not_has_description
string
where._or[].not_has_linkedin_companies
string
where._or[].not_has_linkedin_education
string
where._or[].has_linkedin_last_message_at
boolean
where._or[].has_last_seen_at
boolean
where._or[].has_distance
object
Geo radius filter: contacts within meters of { lat, lon } (PostGIS ST_DWithin on geocoded coordinates). label is an optional display name for the point.
where._or[].has_distance.lat
number
where._or[].has_distance.lon
number
where._or[].has_distance.meters
number
where._or[].has_distance.label
string
where._or[].has_interaction
boolean
where._or[].has_next_reminder
boolean
where._or[].custom_fields
array<object>
User-defined custom-field filters. Each clause is { field_id, operator, value? }; multiple clauses AND together. Operators: contains, eq, in, not_in, present, absent, gte, lte.
where._or[].custom_fields[].field_id
string (uuid)
where._or[].custom_fields[].operator
string enum
Possible values: "contains", "eq", "in", "not_in", "present", "absent", "gte", "lte"
where._or[].custom_fields[].value
string
orderBy
any
include
object
include.linkedin_data
boolean
include.web_search_summary
boolean
include.groups_count
boolean
include.coordinates
boolean
include.last_note
boolean
select
object
select.linkedin_data
boolean
select.web_search_summary
boolean
select.groups_count
boolean
select.coordinates
boolean
select.last_note
boolean
near
string
radiusKm
number

Example

{
  "take": 0,
  "skip": 0
}

Responses

200 — Successful response

Content-Type: application/json

data
object required
data.contacts
array<object> required
data.contacts[].id
string (uuid) required
data.contacts[].user_id
string
data.contacts[].first_name
string | null
data.contacts[].last_name
string | null
data.contacts[].full_name
string | null
data.contacts[].description
string | null
data.contacts[].job_title
string | null
data.contacts[].company
string | null
data.contacts[].education
string | null
data.contacts[].legacy_location
string | null
data.contacts[].image_url
string | null
data.contacts[].business_card_url
string | null
data.contacts[].website
string | null
data.contacts[].image_source
string | null
data.contacts[].birthday
string (date-time)
data.contacts[].birthday_year
integer | null
data.contacts[].linkedin
string | null
data.contacts[].twitter
string | null
data.contacts[].facebook
string | null
data.contacts[].instagram
string | null
data.contacts[].telegram
string | null
data.contacts[].tiktok
string | null
data.contacts[].youtube
string | null
data.contacts[].starred
boolean
data.contacts[].is_archived
boolean
data.contacts[].ignore_merge
boolean
data.contacts[].never_keep_in_touch
boolean
data.contacts[].source
string
data.contacts[].priority_tier
integer | null
data.contacts[].frequency
string | null
data.contacts[].frequency_text
string | null
data.contacts[].last_seen_at
string (date-time)
data.contacts[].last_reminder_at
string (date-time)
data.contacts[].next_reminder_at
string (date-time)
data.contacts[].first_met_at
string (date-time)
data.contacts[].first_interaction_at
string (date-time)
data.contacts[].linkedin_companies
string | null
data.contacts[].linkedin_education
string | null
data.contacts[].linkedin_enhance_date
string (date-time)
data.contacts[].linkedin_last_message_at
string (date-time)
data.contacts[].linkedin_last_message_snippet
string | null
data.contacts[].linkedin_message_link
string | null
data.contacts[].linkedin_urn
string | null
data.contacts[].linkedin_headline
string | null
data.contacts[].whatsapp_message_link
string | null
data.contacts[].whatsapp_message_snippet
string | null
data.contacts[].whatsapp_last_message_at
string (date-time)
data.contacts[].imessage_message_link
string | null
data.contacts[].imessage_message_snippet
string | null
data.contacts[].imessage_last_message_at
string (date-time)
data.contacts[].instagram_message_link
string | null
data.contacts[].instagram_message_snippet
string | null
data.contacts[].instagram_last_message_at
string (date-time)
data.contacts[].gmail_last_interaction_at
string (date-time)
data.contacts[].gmail_last_interaction_provider
string enum
Possible values: "GOOGLE", "OFFICE365"
data.contacts[].gmail_last_interaction_provider_id
string | null
data.contacts[].gmail_last_interaction_subject
string | null
data.contacts[].gcal_last_interaction_at
string (date-time)
data.contacts[].gcal_last_interaction_provider
string enum
Possible values: "GOOGLE", "OFFICE365"
data.contacts[].gcal_last_interaction_provider_id
string | null
data.contacts[].gcal_last_interaction_title
string | null
data.contacts[].phone_call_interaction_snippet
string | null
data.contacts[].phone_call_last_interaction_at
string (date-time)
data.contacts[].web_search_summary
any | null
data.contacts[].created_at
string (date-time)
data.contacts[].updated_at
string (date-time)
data.contacts[].geocode_attempts
integer
data.contacts[].geocode_failed_at
string (date-time)
data.contacts[]._count
object
data.contacts[]._count.groups_contacts
integer
data.contacts[].frequency_interval
any
data.contacts[].linkedin_data
object | null
data.contacts[].latitude
number | null
data.contacts[].longitude
number | null
data.contacts[].last_note
object | null
data.contacts[].last_note.id
string (uuid)
data.contacts[].last_note.preview
string
data.contacts[].last_note.event_time
string (date-time)
data.contacts[].last_note.emoji
string | null
data.contacts[].last_note.meeting_type
string | null
data.contacts[].contact_emails
array<object>
data.contacts[].contact_phone_numbers
array<object>
data.contacts[].contact_birthdays
object | null
data.contacts[].contact_locations
array<object>
data.contacts[].contacts_custom_fields
array<object>
data.contacts[].legacy_contact_addresses
array<object>
data.contacts[].groups_contacts
array<object>
data.contacts[].tags_contacts
array<object>
data.contacts[].timeline_items_contacts
array<object>
data.contacts[].reminders_contacts
array<object>
data.contacts[].contact_relations_contact_relations_sourceTocontacts
array<object>
data.contacts[].contact_relations_contact_relations_destinationTocontacts
array<object>
data.contacts[].feed_items
array<object>
data.contacts[].keep_in_touch_reminders
object | null
data.pagination
object
data.pagination.nextCursor
string | null
data.pagination.count
integer
data.filterHash
string required

Example

{
  "data": {
    "contacts": [
      {
        "id": "00000000-0000-0000-0000-000000000000"
      }
    ],
    "filterHash": "string"
  }
}

400 — Request body failed validation.

Content-Type: application/json

(body)
any

401 — Missing or invalid API key.

Content-Type: application/json

(body)
any

403 — Valid key, insufficient permission.

Content-Type: application/json

(body)
any

404 — Resource does not exist.

Content-Type: application/json

(body)
any

409 — Request conflicts with the current state of the resource.

Content-Type: application/json

(body)
any

429 — Rate limit exceeded.

Content-Type: application/json

(body)
any

500 — Unexpected server error.

Content-Type: application/json

(body)
any

Code samples

curl https://api.prod.getdex.com/v2/contacts/filter \
  --request POST \
  --header 'Authorization: Bearer YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{
  "take": 0,
  "skip": 0
}'
Copyright © 2026