Contacts API
Contacts represent people in your Pathbound CRM. Each contact has a unified profile, an event timeline, conversation history, and a list of notes. Contacts are associated with a company and have a chronological event timeline.
Create a Contact
Section titled “Create a Contact”POST /v1/contactsRequired scope: contacts:write
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
email | string | yes | Contact email address (must be unique). |
properties | object | no | Arbitrary key-value properties for the contact. |
visitor_id | string | string[] | no | Website visitor ID(s) from the tracker to associate. |
company_id | string | no | Associate the new contact with this company. |
Response — 201 Created
Section titled “Response — 201 Created”{ "status": "success", "contact": { "contact_id": "ct_abc", "_id": "ct_abc", "properties": { "firstname": "Ada", "lastname": "Lovelace" }, "associations": { "companies": ["co_xyz"] }, "first_seen_at": "2026-01-15T10:00:00.000Z", "segment_ids": [], "creation_source": "manual", "created_at": "2026-01-15T10:00:00.000Z", "updated_at": "2026-01-15T10:00:00.000Z", "notes": [] }}_id is a transitional alias for contact_id and will be removed in a future release — prefer contact_id in new integrations.
Returns 409 Conflict if a contact with the same email already exists.
List Contacts
Section titled “List Contacts”GET /v1/contactsRequired scope: contacts:read
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
page | number | 1 | Page number. |
limit | number | 20 | Results per page (1–100). |
status | string | — | Filter: enriched or not_enriched. |
lifecycle_stage | string | — | Filter by lifecycle stage (lead, prospect, mql, sql, opportunity, customer, evangelist, subscriber, other). |
lead_status | string | — | Filter by lead status. |
country | string | — | Filter by country. |
industry | string | — | Filter by industry. |
city | string | — | Filter by city. |
state | string | — | Filter by state/region. |
job_title | string | — | Filter by job title (case-insensitive match). |
has_linkedin | boolean | — | Filter contacts with/without a LinkedIn profile. |
company_id | string | — | Filter by associated company ID. |
created_after | string | — | Only contacts created after this ISO 8601 date. |
created_before | string | — | Only contacts created before this ISO 8601 date. |
search | string | — | Free-text search across name, email, company, job title. |
sort_by | string | — | Field to sort by (email, firstname, lastname, company, createdate). |
sort_dir | string | desc | Sort direction (asc or desc). |
count_only | boolean | false | If true, return only { count } — no records. |
fields | string | — | summary (compact identifier + key properties), full (default), or a comma-separated list of field names. Internal fields (tenant_id, user_id, __v, properties_provenance) are blocked from projection. |
include | string | — | Comma-separated list of optional fields to include. Currently supports provenance to add the per-field source/timestamp record (properties_provenance). Default omits provenance for response-size hygiene. |
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "contacts": [ { "contact_id": "ct_abc", "_id": "ct_abc", "associations": { "companies": ["co_xyz"] }, "first_seen_at": "2026-01-15T10:00:00.000Z", "created_at": "2026-01-15T10:00:00.000Z", "updated_at": "2026-01-15T10:00:00.000Z" } ], "pagination": { "page": 1, "limit": 20, "total_pages": 5, "total_items": 100 }}_id is a transitional alias for contact_id and will be removed in a future release.
For a “how many” question, prefer count_only=true. For multi-entity lookups, use the batch API instead of paginating with filters.
Get a Contact
Section titled “Get a Contact”GET /v1/contacts/:contact_idRequired scope: contacts:read
Returns the contact along with its unified profile and (optionally) recent events.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
include_events | boolean | true | If false, omit the events array and total_events. |
events_limit | number | 20 | Max events to include (1–50). Ignored when include_events=false. |
include | string | — | Comma-separated list of optional fields to include. Supports provenance (per-field provenance on the base contact record) and raw (adds unified_profile.raw_data — the un-deduplicated per-source field dumps; large, omitted by default). |
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "contact": { "contact_id": "ct_abc", "_id": "ct_abc", "associations": { "companies": ["co_xyz"] }, "_summary": "Ada Lovelace | CTO | at Analytical Engines | London | Stage: customer", "created_at": "2026-01-15T10:00:00.000Z", "updated_at": "2026-04-29T12:00:00.000Z" }, "unified_profile": { "_id": "ct_abc", "source_count": 3, "sources": { "internal": { "id": "ct_abc", "updated_at": "...", "first_seen_at": "..." }, "hubspot": { "id": "12345", "synced_at": "...", "first_seen_at": "..." }, "apollo": { "id": "ap_678", "enriched_at": "..." } }, "profile": { "email": { "unique_values": [ { "value": "[email protected]", "sources": [{ "source": "hubspot", "updated_at": "..." }, { "source": "apollo", "updated_at": "..." }] } ], "all_sources": ["hubspot", "apollo"], "has_conflict": false }, "jobtitle": { "unique_values": [ { "value": "CTO", "sources": [{ "source": "hubspot", "updated_at": "..." }] }, { "value": "Chief Technology Officer", "sources": [{ "source": "apollo", "updated_at": "..." }] } ], "all_sources": ["hubspot", "apollo"], "has_conflict": true } }, "created_at": "...", "updated_at": "...", "enriched_at": "..." }, "events": [ { "event_id": "evt_1", "_id": "evt_1", "event": "page_view", "timestamp": "...", "url": "...", "title": "..." } ], "total_events": 42, "timestamp": "2026-04-29T12:00:00.000Z"}_summary is a human-readable one-liner the backend stitches together from the contact’s name, title, company, industry, location, and lifecycle stage. Parts are joined with | and prefixed where applicable (at <company>, Stage: <stage>). Convenient for list views, but not a stable contract — don’t parse it.
unified_profile is the full deduplicated cross-source profile. Each profile field is a multi-source object: unique_values holds every distinct value found across sources (deduplicated), each annotated with the sources that supplied it; all_sources lists every source that had any value for the field; and has_conflict is true when sources disagree (more than one distinct value). sources is a per-source map (presence, external IDs, and sync/enrichment timestamps), and source_count is how many sources contributed. Pass ?include=raw to additionally get raw_data — the verbatim, un-deduplicated per-source field dumps. events is a compact projection of the contact’s most recent events and is omitted (along with total_events) when the request is made with ?include_events=false.
When PII redaction is enabled for an AI-agent (MCP) caller, the personal values inside unified_profile.profile are masked (the field and its source attribution remain visible) and raw_data is never returned, even with ?include=raw.
Update a Contact
Section titled “Update a Contact”PUT /v1/contacts/:contact_idRequired scope: contacts:write
Request Body
Section titled “Request Body”| Field | Type | Required | Description |
|---|---|---|---|
properties | object | no | Properties to update or add (merge). |
visitor_id | string | string[] | no | Visitor ID(s) to associate. |
To change a contact’s lifecycle stage, set properties.lifecyclestage to one of the allowed values.
Lifecycle stages
Section titled “Lifecycle stages”lead, prospect, mql, sql, opportunity, customer, evangelist, subscriber, other.
Delete a Contact
Section titled “Delete a Contact”DELETE /v1/contacts/:contact_idRequired scope: contacts:write
Permanently removes the contact and its notes. Events remain in the audit log.
Get Contact Events
Section titled “Get Contact Events”GET /v1/contacts/events/:contact_idRequired scope: contacts:read
Returns all events associated with a contact. For aggregate event queries (across many contacts), use the Events API directly.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
event_type | string | — | Filter by event type. |
sort_dir | string | desc | Sort direction (asc or desc). |
fields | string | — | summary for a compact projection (event_id, _id, event, timestamp, url, contact_id); omit for full. |
include | string | — | Comma-separated list of optional fields to include. Currently supports provenance. |
Response — 200 OK
Section titled “Response — 200 OK”{ "status": "success", "events": [ { "event_id": "evt_abc", "_id": "evt_abc", "event": "page_view", "timestamp": "2026-04-29T11:23:45.000Z", "url": "https://example.com/pricing", "domain": "example.com", "data": { "title": "Pricing — Example", "path": "/pricing" } } ], "contact_id": "ct_abc", "total_items": 12, "returned": 12}Get Contact Conversations
Section titled “Get Contact Conversations”GET /v1/contacts/:contact_id/conversationsRequired scope: contacts:read
Returns the contact’s email (Gmail) and Intercom conversation history.
Query Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
include_messages | boolean | false | Include the full message bodies, not just thread metadata. |
messages_per_thread | number | 5 | Max messages per thread when include_messages=true. |
limit | number | 20 | Total threads to return. |
List Contact Email Threads
Section titled “List Contact Email Threads”GET /v1/contacts/:contact_id/email-threadsRequired scope: contacts:read
Returns a compact list of Gmail threads for the contact — thread_id, last_message_id, subject — useful for joining inbound and outbound communication into a single conversation view.
Contact Notes
Section titled “Contact Notes”Each contact can have an unlimited list of free-form notes. Notes are written directly (no approval flow) and are visible to anyone with contacts:read.
List Notes
Section titled “List Notes”GET /v1/contacts/:contact_id/notesRequired scope: contacts:read
Create a Note
Section titled “Create a Note”POST /v1/contacts/:contact_id/notesRequired scope: contacts:write
| Field | Type | Required | Description |
|---|---|---|---|
content | string | yes | Note body (markdown). |
Update a Note
Section titled “Update a Note”PATCH /v1/contacts/:contact_id/notes/:note_idRequired scope: contacts:write
Delete a Note
Section titled “Delete a Note”DELETE /v1/contacts/:contact_id/notes/:note_idRequired scope: contacts:write