Skip to content

List a customer's contacts

GET
/customers/{customerId}/contacts
curl --request GET \
--url 'https://api.usesonora.com/v1/customers/example/contacts?departed=true&includeArchived=true&sort=-createdAt&limit=25' \
--header 'Authorization: Bearer <token>'

The people at one customer, named by its Sonora id or, with idType, your own system’s id for it. Newest first, or — with sort=updatedAt — oldest change first, to keep another system in step with Sonora. People who have left their customer are included (departedAt set); archived contacts are left out unless includeArchived=true.

Requires the contacts:read scope.

customerId
required
string

The customer’s Sonora id — or, with idType, its id in another system, or its domain.

idType
string

How id names the account: sonora (the default; Sonora’s customer id), salesforce, hubspot, domain, or custom_field:<key>. So GET /customers/001Ab…?idType=salesforce finds a customer by its Salesforce Account id.

email
string format: email

The person’s email address, matched without regard to case.

departed
string
Allowed values: true false

true: only people who have left their customer. false: only people still there. Omit for both.

includeArchived
string
Allowed values: true false

Also list archived contacts. A sync should set it, so it sees a contact leave.

createdAfter
string format: date-time
updatedAfter
string format: date-time

Contacts changed at or after this instant. With sort=updatedAt, resume a sync from the last updatedAt you saw, a few minutes back.

sort
string
default: -createdAt
Allowed values: -createdAt updatedAt

-createdAt: newest first (the default). updatedAt: oldest change first, for syncing.

limit
integer
default: 25 >= 1 <= 100

Page size, 1–100.

cursor
string
<= 200 characters

The previous page’s nextCursor, unchanged. Omit for the first page.

include
string

Comma-separated optional parts of the response: totalCount.

A page of contacts.

Media typeapplication/json
object
data
required
Array<object>

A person at one of your customers.

object
id
required
string
customerId
required

The customer the person works at. Null when Sonora hasn’t matched them to one.

string | null
firstName
required
string | null
lastName
required
string | null
name
required

First and last name together; null when Sonora has neither.

string | null
email
required
string | null
phone
required
string | null
title
required

Job title.

string | null
linkedinUrl
required
string | null
isChampion
required

Marked as a champion at their account.

boolean
departedAt
required
Any of:
string format: date-time
archivedAt
required
Any of:
string format: date-time
doNotContact
required

Someone on your team marked the person do-not-contact, so Sonora never emails them. The mark is on the address, so changing it doesn’t move updatedAt.

boolean
externalIds
required
Array<object>

The record’s id in another system.

object
source
required

The system the id is from: salesforce, hubspot, zendesk, intercom, …

string
id
required
string
engagementsCount
required

Calls, emails, meetings and tickets Sonora has seen the person in.

integer
lastEngagementAt
required
Any of:
string format: date-time
createdAt
required
string format: date-time
updatedAt
required

Moves on any change to the record, including Sonora’s own bookkeeping (engagement counts).

string format: date-time
links
required
object
self
required

This resource’s canonical URL on the API host.

string
totalCount

Only with ?include=totalCount: every match under the same filters.

integer
nextCursor
required

Pass as cursor for the next page; null on the last page.

string | null
Examplegenerated
{
"data": [
{
"id": "example",
"customerId": "example",
"firstName": "example",
"lastName": "example",
"name": "example",
"email": "example",
"phone": "example",
"title": "example",
"linkedinUrl": "example",
"isChampion": true,
"departedAt": "2026-04-15T12:00:00Z",
"archivedAt": "2026-04-15T12:00:00Z",
"doNotContact": true,
"externalIds": [
{
"source": "example",
"id": "example"
}
],
"engagementsCount": 1,
"lastEngagementAt": "2026-04-15T12:00:00Z",
"createdAt": "2026-04-15T12:00:00Z",
"updatedAt": "2026-04-15T12:00:00Z",
"links": {
"self": "example"
}
}
],
"totalCount": 1,
"nextCursor": "example"
}

invalid_request: A parameter or body field is missing, malformed or unknown; details.issues names each.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

unauthorized: The Authorization header is missing, or the key is invalid, revoked or expired.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

insufficient_scope: The key or token lacks the scope this endpoint needs, and details.required names it; or an OAuth access token called an endpoint only an API key can.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

customer_not_found: No customer matches the id (and idType) in the path.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

rate_limited: Too many requests for this key; retry after Retry-After seconds.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

internal_error: Something went wrong on Sonora’s side. Retry, and quote requestId if it persists.

Media typeapplication/json

The one error shape every endpoint answers with.

object
error
required
object
code
required

Stable snake_case code to branch on; see the error table.

string
message
required

For humans; may change.

string
details
object
key
additional properties
requestId
required

Quote it when asking for help.

string | null
Examplegenerated
{
"error": {
"code": "example",
"message": "example",
"details": {
"additionalProperty": "example"
},
"requestId": "example"
}
}

Try it

Run this request against your own Sonora workspace. Sign in, pick the workspace, and the page gets an access token that only reads, only what your role covers, for an hour.

GEThttps://api.usesonora.com/v1/customers/{customerId}/contacts

As curl

$SONORA_TOKEN is your access token or an API key; the page never shows the token.