CRUD and reverse-lookup endpoints for the organization's contact directory. All contacts are org-scoped; the caller's organization is derived from the auth context.
Create contact POST
POST /contacts
Create a new contact. At least one of given_name, family_name, company_name, or preferred_name must be non-empty (the vCard FN rule). If preferred_name is omitted it is synthesized from the other name fields.
Request body
Field
Type
Required
Description
preferred_name
string | null
No
Display name (max 255 chars). Synthesized if omitted.
Controls who can see the new contact. Omit (or null) → wildcard (every agent sees it, default). [] → nobody but admins/humans see it. Explicit list → only these identities see it.
Request example
JSON
Response (201)
Returns the created contact with an inlined access array (see Contact object).
Error responses
Status
Description
400
vCard FN rule violated — no name fields provided
404
One or more access_identity_ids do not resolve to an active identity in your org
422
Invalid email, non-E.164 phone, duplicate email/phone, or more than one is_primary
Code examples
cURL
List contacts GET
GET /contacts
List contacts visible to the caller. Scoped agents only see contacts they have access to; admins and Clerk JWT users see every contact in the org.
Query parameters
Parameter
Type
Default
Description
q
string
—
Case-insensitive substring match over name, company, job title, and the notes field. Max 100 chars.
order
string
name
"name" (preferred_name ascending) or "recent" (created_at descending)
limit
integer
50
Results per page (1–200)
offset
integer
0
Offset for pagination
Response (200)
Returns an array of contact objects, each with an inlined access array.
Code examples
cURL
Lookup contact GET
GET /contacts/lookup
Reverse-lookup contacts by a single field. Useful for routing inbound email or phone calls to a known contact.
Query parameters
Exactly one of the following must be provided:
Parameter
Type
Description
email
string
Exact match against a stored email (canonicalized to lowercase)
email_contains
string
Substring match on stored email values (case-insensitive)
email_domain
string
Suffix match on @<domain>. Leading @ tolerated (max 253 chars)
phone
string
Exact match against a stored E.164 phone number
phone_contains
string
Substring match on stored E.164 phone values
Response (200)
Returns an array of contact objects (up to 200). An empty array means no match.
Error responses
Status
Description
400
Zero or more than one filter provided; or phone is not a valid E.164 number
Code examples
cURL
Get contact GET
GET /contacts/{contact_id}
Fetch a single contact by its UUID.
Path parameters
Parameter
Type
Description
contact_id
UUID
Unique contact identifier
Code examples
cURL
Update contact PATCH
PATCH /contacts/{contact_id}
Update a contact using JSON-merge-patch semantics:
Omit a field to leave it unchanged
Send a value to set it
Send null on a nullable scalar to clear it
Send a list to replace the stored list wholesale (no per-item merge)
After applying the patch, the server re-runs the FN rule against the merged state — if the update would leave every name field empty, the request 400s.
Path parameters
Parameter
Type
Description
contact_id
UUID
Unique contact identifier
Request body
Any subset of the Create contact body fields. access_identity_ids cannot be changed via PATCH — use the Access control endpoints instead.
Code examples
cURL
Delete contact DELETE
DELETE /contacts/{contact_id}
Delete a contact. Returns 204 No Content on success.