Contacts
Create, search, update and delete the people your agents call.
A contact is a person in your account, identified by a phone number and optionally an email address. Contacts can carry tags and your own metadata, and they feed audiences.
| Endpoint | Request |
|---|---|
| List contacts | GET/v1/contacts |
| Get a contact | GET/v1/contacts/{id} |
| Create a contact | POST/v1/contacts |
| Update a contact | PATCH/v1/contacts/{id} |
| Delete a contact | DEL/v1/contacts/{id} |
The contact object
Contact fields use snake_case.
Attributes
idstringrequiredfirst_namestring | nulllast_namestring | nullnull when empty.namestringphonestring | nullphone_numberstring | nullphone.phone_numbersstring[]emailstring | nullemailsstring[]companystring | nullcontact_typestringclient, supplier, partner or other. Contacts created through this API are other.timezonestringUTC.tagsstring[]metadataobject | nulluser_id and file_id, are left out of responses. Use your own key names, such as crm_id.created_atstring | nullupdated_atstring | nullPhone number validation
phone must be a real, dialable number, using the same check as placing a call. So a saved contact can always be called. It can be up to 32 characters, and it is stored in E.164 format.
| You send | Stored as | Rule |
|---|---|---|
+1 (202) 555-0123 | +12025550123 | Starts with +, so the digits are kept as sent. |
555-555-0123 | +12025550123 | Ten digits are treated as a US or Canadian number. |
12025550123 | +12025550123 | Eleven digits starting with 1 get a +. |
442079460123 | +442079460123 | Anything else gets a + with no other change. |
Whatever the form, the result must be valid for its country, or the request returns 400. A national number such as 02025550123 is refused, so send international numbers in E.164 format.
Emails are converted to lowercase before they are stored.
Duplicate contacts
Each account can have only one active contact with a given primary phone number. The same applies to primary email addresses, ignoring case.
POST /v1/contacts doesn't update an existing contact. A request that reuses a phone number or email returns 409 with the code CONFLICT, and no contact is changed. PATCH returns the same error when a new value belongs to another contact. To upsert, search for the number first, then call PATCH or POST based on the result.
A deleted contact doesn't count as a duplicate. Its phone number and email can be used again, and the new contact gets a new id.
List contacts
/v1/contactsread keyReturns your active contacts, newest first.
Query parameters
limitintegerdefault 50offsetintegerdefault 0searchstring* returns 400. Leave it out to list everything.search matches any part of the first name, last name, full name, company or primary email, ignoring case. Phone numbers and additional email addresses match only in full, so search=555 won't find +12025550123. The search value goes through the same normalization as a stored number.
Encode + as %2B in the query string.
curl "https://backend.synthesys.app/api/v1/contacts?limit=10&search=jane" \
-H "SYNTH_API_KEY: YOUR_API_KEY"{
"success": true,
"data": [
{
"id": "3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c",
"first_name": "Jane",
"last_name": "Doe",
"phone_numbers": ["+12025550123"],
"emails": ["jane@example.com"],
"contact_type": "other",
"timezone": "UTC",
"company": "Example Inc",
"phone": "+12025550123",
"phone_number": "+12025550123",
"name": "Jane Doe",
"email": "jane@example.com",
"tags": ["VIP"],
"metadata": { "crm_id": "A-1001" },
"created_at": "2026-10-01T09:30:00.000Z",
"updated_at": "2026-10-01T09:30:00.000Z"
}
],
"pagination": { "total": 1, "limit": 10, "offset": 0 }
}Get a contact
/v1/contacts/{id}read keyReturns one contact.
Path parameters
idstringrequiredReturns 404 if the contact doesn't exist, belongs to another account or was deleted. An id that isn't a valid UUID returns 400.
curl https://backend.synthesys.app/api/v1/contacts/3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c \
-H "SYNTH_API_KEY: YOUR_API_KEY"{
"success": true,
"data": {
"id": "3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c",
"first_name": "Jane",
"last_name": "Doe",
"phone_numbers": ["+12025550123"],
"emails": ["jane@example.com"],
"contact_type": "other",
"timezone": "UTC",
"company": "Example Inc",
"phone": "+12025550123",
"phone_number": "+12025550123",
"name": "Jane Doe",
"email": "jane@example.com",
"tags": ["VIP"],
"metadata": { "crm_id": "A-1001" },
"created_at": "2026-10-01T09:30:00.000Z",
"updated_at": "2026-10-01T09:30:00.000Z"
}
}{
"success": false,
"error": "Contact not found",
"code": "NOT_FOUND",
"requestId": "e3a1c5d7-2b4f-4a6c-9d8e-1f2a3b4c5d6e",
"timestamp": "2026-10-31T14:02:11.482Z"
}Create a contact
/v1/contactswrite keyCreates a contact and returns it with status 201. Fields not listed below, such as contact_type and external_id, are ignored.
Body parameters
first_namestringrequiredphonestringrequiredlast_namestringemailstringcompanystringtagsstring[]metadataobjectTag names match existing tags ignoring case, and the contact shows the tag's existing display name. Names that differ only in spacing or punctuation, such as VIP Lead and vip_lead, count as one tag.
Warnings
If the contact is saved but its tags can't be applied, the request still succeeds. The response adds a warnings array, and the contact is returned without the new tags. Send the tags again with PATCH. Don't repeat the POST, because it would return 409.
{
"success": true,
"data": { "id": "3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c", "first_name": "Jane" },
"warnings": [
{
"code": "TAGS_NOT_APPLIED",
"message": "The contact was saved, but its tags could not be applied. Send them again with PATCH."
}
]
}Errors:
400: a field fails validation,first_nameorphoneis missing, or the number isn't dialable.details.issuesnames the field.409: the phone number or email already belongs to an active contact. See duplicate contacts.
curl -X POST https://backend.synthesys.app/api/v1/contacts \
-H "SYNTH_API_KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jane",
"last_name": "Doe",
"phone": "+12025550123",
"email": "jane@example.com",
"company": "Example Inc",
"tags": ["VIP"],
"metadata": { "crm_id": "A-1001" }
}'{
"success": true,
"data": {
"id": "3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c",
"first_name": "Jane",
"last_name": "Doe",
"phone_numbers": ["+12025550123"],
"emails": ["jane@example.com"],
"contact_type": "other",
"timezone": "UTC",
"company": "Example Inc",
"phone": "+12025550123",
"phone_number": "+12025550123",
"name": "Jane Doe",
"email": "jane@example.com",
"tags": ["VIP"],
"metadata": { "crm_id": "A-1001" },
"created_at": "2026-10-01T09:30:00.000Z",
"updated_at": "2026-10-01T09:30:00.000Z"
}
}{
"success": false,
"error": "The request is invalid.",
"code": "VALIDATION_ERROR",
"requestId": "e3a1c5d7-2b4f-4a6c-9d8e-1f2a3b4c5d6e",
"timestamp": "2026-10-31T14:02:11.482Z",
"details": {
"issues": [
{ "path": "phone", "message": "This field is required." }
]
}
}{
"success": false,
"error": "A contact with this phone number or email already exists",
"code": "CONFLICT",
"requestId": "1d2c3b4a-5f6e-4d7c-8b9a-0f1e2d3c4b5a",
"timestamp": "2026-10-31T14:03:40.120Z"
}Update a contact
/v1/contacts/{id}write keyUpdates only the fields you send and returns the contact. An empty body returns the contact unchanged.
Path parameters
idstringrequiredBody parameters
first_namestringlast_namestringphonestringemailstringcompanystringtagsstring[]metadataobjectA warnings array appears here too if the contact is saved but its tags can't be applied. See Warnings.
Errors:
400: a field fails validation.details.issuesnames the field.404: the contact doesn't exist, belongs to another account or was deleted.409: the new phone number or email already belongs to another active contact.
curl -X PATCH https://backend.synthesys.app/api/v1/contacts/3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c \
-H "SYNTH_API_KEY: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "company": "Example Group", "tags": ["VIP", "Renewal"] }'{
"success": true,
"data": {
"id": "3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c",
"first_name": "Jane",
"last_name": "Doe",
"phone_numbers": ["+12025550123"],
"emails": ["jane@example.com"],
"contact_type": "other",
"timezone": "UTC",
"company": "Example Group",
"phone": "+12025550123",
"phone_number": "+12025550123",
"name": "Jane Doe",
"email": "jane@example.com",
"tags": ["VIP", "Renewal"],
"metadata": { "crm_id": "A-1001" },
"created_at": "2026-10-01T09:30:00.000Z",
"updated_at": "2026-10-02T14:05:00.000Z"
}
}Delete a contact
/v1/contacts/{id}delete keyRemoves a contact from your account. The record is marked as deleted rather than erased, but the API has no way to restore it.
Path parameters
idstringrequiredAn id that isn't a valid UUID returns 400.
Deleting a contact has these effects:
- The contact stops appearing in the contacts endpoints. Reading, updating or deleting it again returns
404. - Its tags are removed from it. The tags stay in your account.
- It is removed from contact lists and from static audiences.
- It drops out of dynamic audience results.
- Its phone number and email become available for a new contact.
curl -X DELETE https://backend.synthesys.app/api/v1/contacts/3f2b8c1e-7a4d-4e9b-9c10-5d6e7f8a9b0c \
-H "SYNTH_API_KEY: YOUR_API_KEY"{ "success": true, "message": "Contact deleted successfully" }{
"success": false,
"error": "Contact not found",
"code": "NOT_FOUND",
"requestId": "e3a1c5d7-2b4f-4a6c-9d8e-1f2a3b4c5d6e",
"timestamp": "2026-10-31T14:02:11.482Z"
}