Contacts
Contacts are the people at your customers: their names, titles and ways to reach them, whether they’ve left, whether your team has marked them do-not-contact, and the ids your CRM knows them by. Reading them needs a key with the contacts:read scope; marking someone do-not-contact needs contacts:write. Every field is in the API reference; this page covers how to use them.
List contacts
Section titled “List contacts”curl "https://api.usesonora.com/v1/contacts?customerId=c1d2…&limit=50" \ -H "Authorization: Bearer sonora_sk_…"{ "data": [ { "id": "7f3a…", "customerId": "c1d2…", "firstName": "Ana", "lastName": "Alvarez", "name": "Ana Alvarez", "email": "ana@acme.com", "phone": "+1 555 0100", "title": "VP Operations", "linkedinUrl": "https://www.linkedin.com/in/ana", "isChampion": true, "departedAt": null, "archivedAt": null, "doNotContact": false, "externalIds": [{ "source": "salesforce", "id": "003Ab00000Qr7stAAB" }], "engagementsCount": 38, "lastEngagementAt": "2026-10-14T16:02:11.000Z", "createdAt": "2026-04-03T09:12:00.000Z", "updatedAt": "2026-10-14T16:02:12.418Z", "links": { "self": "https://api.usesonora.com/v1/contacts/7f3a…" } } ], "nextCursor": "MjAyNi0wNC0wM1Qw…"}Contacts come newest first. Narrow the list with:
| Parameter | |
|---|---|
customerId |
Only the people at this customer, by its Sonora id. |
email |
The person’s email address, matched without regard to case. |
departed |
true for only the people who have left their customer, false for only the ones still there. Leave it out for both. |
includeArchived |
true to list archived contacts too. |
createdAfter, updatedAfter |
ISO 8601 instants with an offset. |
customerId is null for someone Sonora has seen but hasn’t matched to one of your customers. name is the first and last name together, and null when Sonora has neither — it may still have an email.
Who is listed
Section titled “Who is listed”- People who have left are listed, with
departedAtset, so you can see the change rather than have them disappear. Passdeparted=falsefor only the people still at their customer. - Archived contacts are left out unless you pass
includeArchived=true. A contact is archived when its customer is, and comes back when the customer does. - Suppressed contacts are never returned. Suppression is how Sonora, or someone on your team, sets aside an address that isn’t a person — a mailing list, a
no-reply@sender — andGET /contacts/{contactId}answers404 contact_not_foundfor one, as the people pages hide it.
GET /contacts/{contactId} finds departed and archived contacts.
Do not contact
Section titled “Do not contact”doNotContact is true when the person has been marked do-not-contact — by someone on your team in Sonora, or by a key — which stops every email Sonora would send them. The mark is on their email address, so it holds however a workflow or draft comes to name them. It doesn’t reflect unsubscribes or bounces.
Mark someone do-not-contact
Section titled “Mark someone do-not-contact”PUT /contacts/{contactId}/do-not-contact marks a person, as Mark do not contact on their page in Sonora does. It needs the contacts:write scope (with contacts:read), and takes no body:
curl -X PUT "https://api.usesonora.com/v1/contacts/7f3a…/do-not-contact" \ -H "Authorization: Bearer sonora_sk_…"The answer is the contact, now with "doNotContact": true. From then on no workflow or draft in Sonora emails them, under any customer, until someone lifts the mark. Their emails and meetings still come in, and they stay in your lists. This is the call to make when your CRM says a person has opted out — Salesforce’s HasOptedOutOfEmail, say — so Sonora honours it too.
DELETE /contacts/{contactId}/do-not-contact lifts the mark, as Allow contact does, and answers 200 with the contact. Workflows and drafts include the person again from their next send.
- Both are safe to repeat. Marking someone already marked, or clearing someone who isn’t, changes nothing and answers
200with the contact as it is. A mark someone on your team made stays theirs, with the reason they gave: the API never overwrites it. - Sonora shows who marked them. The person’s page in Sonora names the key that made the mark, so your team can see where it came from before they lift it.
- Unsubscribes and bounces are separate. Clearing the mark lifts only the mark. A person who unsubscribed, or whose address bounced, still isn’t emailed.
- The mark needs an address. Marking a contact with no email is
422 contact_has_no_email. Clearing one answers200: there is nothing to clear. - A contact Sonora can’t find — including a suppressed one, which isn’t listed — is
404 contact_not_found.
Changing the mark doesn’t move the contact’s updatedAt (see below), so read the contact back if you need to confirm it.
One customer’s people
Section titled “One customer’s people”GET /customers/{customerId}/contacts is the same list for one customer, named the way GET /customers/{customerId} names it — Sonora’s id, or with idType your own system’s:
curl "https://api.usesonora.com/v1/customers/001Ab00000XyZ12/contacts?idType=salesforce&departed=false" \ -H "Authorization: Bearer sonora_sk_…"It takes every filter GET /contacts does except customerId. An unknown customer is 404 customer_not_found. An archived customer’s people are archived with it, so its list is empty unless you pass includeArchived=true.
Keep another system in step
Section titled “Keep another system in step”Contacts sync the way customers do: read them oldest change first and resume from where you stopped.
- First run:
GET /contacts?sort=updatedAt&includeArchived=true, followingnextCursorto the last page. Remember the largestupdatedAtyou saw. - Each later run:
GET /contacts?sort=updatedAt&includeArchived=true&updatedAfter=<that updatedAt minus 5 minutes>.
Upsert by id, so the overlap costs nothing. A person who leaves comes through with departedAt set; one whose customer is archived, with archivedAt set; one newly linked to a record in another system, with the new entry in externalIds. updatedAt also moves on Sonora’s own bookkeeping — a new call or email bumps engagementsCount — so a sync will see some people again with nothing you store changed.
Changing a do-not-contact mark doesn’t move updatedAt: the mark belongs to the address, not the contact. To keep doNotContact current, re-read the people you mirror from time to time.