Contacts
List contacts
Newest first. Filter by phone, email, externalRef, or updatedSince. presence=online keeps only the contacts online now (needs the contacts:presence-read scope). To search, send q (name, email, phone, externalRef and the values of the contact fields): each result says in match which field matched. pipelineId keeps the contacts with a case in that pipeline, hasOpenCases=true the ones with an open case, fieldKey with fieldValue the ones whose contact field has that value. Any of these, or order, sorts by latest activity (or by name) instead of newest first, and adds caseCount, openCaseCount and lastActivityAt to each contact.
Required scope: contacts:read.
query Parameters
limitcursorThe nextCursor of the previous page, with the same filters.
phoneExact match on the stored phone.
emailExact match, ignoring case.
externalRefupdatedSinceOnly contacts changed at or after this moment.
presenceonline: only contacts that are online now. Needs the contacts:presence-read scope. Answers 409 presence_not_configured when presence is not active, and 503 when the online list cannot be read.
qSearches name, email, phone, externalRef and the values of the contact fields, ignoring case and accents. With q the answer carries match, the field that matched.
pipelineIdOnly contacts that have a case in this pipeline.
hasOpenCasestrue keeps only the contacts with an open case.
orderactivity: the latest activity first. name: A to Z. Without order and without the other search parameters the list is newest first.
fieldKeyThe key of a contact field. Send it with fieldValue.
fieldValueOnly contacts whose fieldKey has exactly this value. Send it with fieldKey.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
List contacts › Responses
objecthasMorenextCursorCreate a contact
A contact is the person the organization attends. Send externalRef to keep your own id on it: sending the same externalRef again is a 409. To create or update in one call, use PUT /v2/contacts/by-external-ref/{externalRef}.
Required scope: contacts:write.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Idempotency-KeyMakes the request safe to retry. Once it starts running, its final response (2xx, 4xx or 5xx) is kept for 24 hours and the same key gets it back, without repeating the effect. A request rejected before it runs leaves the key free. A replayed create omits the secret. The same key with a different request is rejected with 409 idempotency_key_reused.
Create a contact › Request Body
nameemail^[A-Za-z0-9!#$%&'*+/…phoneexternalRefYour own id for this person. Unique in the organization: sending it again is a 409.
companyIdThe company this person works in, created with POST /v2/companies. A company that does not exist in the organization is a 400 with param companyId.
tagsValues for the contact fields you created with POST /v2/contact-fields, by key. Each value is checked against the type of its field. Nothing is saved if one key or value is not accepted.
Create a contact › Responses
objectidnameemailphoneexternalRefcompanyIdThe company of this contact, or null when it has none.
tagsThe values of the contact fields this contact has, by key. Empty when it has none.
createdAtupdatedAtWhether the contact is online. Present only when the organization setting presenceEnabled is on, at least one presence signal has arrived, and the key has the contacts:presence-read scope.
matchOnly when you search with q: the field of the contact that matched and its value, or null when the match was the name, email, phone or externalRef. Fields marked sensitive are never searched or shown.
caseCountOnly when you search, filter by pipeline or open cases, or sort: how many cases the contact has.
openCaseCountSame as caseCount, only the open ones.
lastActivityAtSame as caseCount: the latest message of its cases, or its creation date.
Create or update a contact by your own id
Calling it twice with the same externalRef leaves one contact. The fields you omit stay as they were; a new contact with no name is named after the externalRef. Always answers 200.
Required scope: contacts:write.
path Parameters
externalRefYour own id for this person. The contact with this externalRef is updated; if there is none it is created.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Create or update a contact by your own id › Request Body optional
nameRequired to create. When the contact exists and you omit it, the name stays. A new contact with no name is named after the externalRef.
email^[A-Za-z0-9!#$%&'*+/…phonecompanyIdLinks the contact to a company. When you omit it the company stays; null unlinks it. A company that does not exist in the organization is a 400 with param companyId.
tagsValues for the contact fields you created with POST /v2/contact-fields, by key. The keys you omit stay as they were; null removes the value. Each value is checked against the type of its field. Nothing is saved if one key or value is not accepted.
Create or update a contact by your own id › Responses
objectidnameemailphoneexternalRefcompanyIdThe company of this contact, or null when it has none.
tagsThe values of the contact fields this contact has, by key. Empty when it has none.
createdAtupdatedAtWhether the contact is online. Present only when the organization setting presenceEnabled is on, at least one presence signal has arrived, and the key has the contacts:presence-read scope.
matchOnly when you search with q: the field of the contact that matched and its value, or null when the match was the name, email, phone or externalRef. Fields marked sensitive are never searched or shown.
caseCountOnly when you search, filter by pipeline or open cases, or sort: how many cases the contact has.
openCaseCountSame as caseCount, only the open ones.
lastActivityAtSame as caseCount: the latest message of its cases, or its creation date.
Retrieve a contact
Returns one contact by id. Use it to refresh a single record you already know; to find records, use the list route. To search for a person, use the list route. Read only. 404 not_found when the id does not exist or belongs to another organization. You can repeat it safely: it has no side effects.
Required scope: contacts:read.
path Parameters
id^ctc_[0-9A-Za-z]{22}… · requiredThe id of the contact (ctc_…).
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Retrieve a contact › Responses
objectidnameemailphoneexternalRefcompanyIdThe company of this contact, or null when it has none.
tagsThe values of the contact fields this contact has, by key. Empty when it has none.
createdAtupdatedAtWhether the contact is online. Present only when the organization setting presenceEnabled is on, at least one presence signal has arrived, and the key has the contacts:presence-read scope.
matchOnly when you search with q: the field of the contact that matched and its value, or null when the match was the name, email, phone or externalRef. Fields marked sensitive are never searched or shown.
caseCountOnly when you search, filter by pipeline or open cases, or sort: how many cases the contact has.
openCaseCountSame as caseCount, only the open ones.
lastActivityAtSame as caseCount: the latest message of its cases, or its creation date.
Erase a contact
Use it when a person asks to be erased or when you decide to erase them. It is permanent: the contact, its cases, messages, files, fields, agent memory and logs lose their content; the contact is anonymized in place and what remains is an aggregate shell of each case with a new id and dates cut to the day. It does not delete rows, so statistics keep working. The erasure runs as a job: it answers 202 with a suppression to follow with GET /v2/suppressions/{id} and the contact.suppressed webhook. Without closeOpenCases it answers 409 resource_in_use while the contact has open cases. Use dryRun=true first to get the inventory without content (200, changes nothing). legalHold=true records the request and keeps everything until you repeat it without legalHold. Not idempotent in effect but safe to repeat: once started the contact answers 404.
Required scope: contacts:erase.
path Parameters
id^ctc_[0-9A-Za-z]{22}… · requiredThe id of the contact (ctc_…).
query Parameters
reasonWhy the contact is erased: the person asked (data_subject_request) or you decided it as the data controller (controller_instruction). It is kept in the suppression record.
legalHoldtrue: you must keep this data by law (a debt, a credit, a refund). The request is recorded as held and nothing is erased until you repeat it without legalHold.
closeOpenCasestrue: close the open cases of the contact and erase it. Without it, a contact with open cases is a 409 resource_in_use.
dryRunWhen true, the request goes through the same validation as the real one and is answered with what would happen (always 200), and nothing is saved, sent or charged. The answer has the same shape as the real one plus dryRun: true; an id in it is not saved. It does not use the Idempotency-Key.
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Erase a contact › Responses
dryRun=true: the inventory, nothing changes.
objectidnull on a dryRun: nothing was created.
contactIdstatusphasereasonlegalHoldclosedOpenCasesRows erased or anonymized per store. Numbers only.
errorCodeOnly on dryRun: what would be erased, by store, without content.
createdAtcompletedAtdryRunPresent and true only on a dry run: nothing was erased and the inventory shows what would be.
Update a contact
Send null in email, phone or externalRef to remove it. tags replaces the whole list.
Required scope: contacts:write.
path Parameters
id^ctc_[0-9A-Za-z]{22}… · requiredThe id of the contact (ctc_…).
Headers
Lelemon-Subaccount^sub_[0-9A-Za-z]{22}…The subaccount (sub_…) this request acts on. Only for the keys of a platform account; without it the request acts on the account itself.
Update a contact › Request Body optional
nameemail^[A-Za-z0-9!#$%&'*+/…null removes it.
phonenull removes it.
externalRefnull removes it.
companyIdLinks the contact to a company, or to another one. null unlinks it. A company that does not exist in the organization is a 400 with param companyId.
tagsReplaces the whole list.
Values for the contact fields you created with POST /v2/contact-fields, by key. The keys you omit stay as they were; null removes the value. Each value is checked against the type of its field. Nothing is saved if one key or value is not accepted.
Update a contact › Responses
objectidnameemailphoneexternalRefcompanyIdThe company of this contact, or null when it has none.
tagsThe values of the contact fields this contact has, by key. Empty when it has none.
createdAtupdatedAtWhether the contact is online. Present only when the organization setting presenceEnabled is on, at least one presence signal has arrived, and the key has the contacts:presence-read scope.
matchOnly when you search with q: the field of the contact that matched and its value, or null when the match was the name, email, phone or externalRef. Fields marked sensitive are never searched or shown.
caseCountOnly when you search, filter by pipeline or open cases, or sort: how many cases the contact has.
openCaseCountSame as caseCount, only the open ones.
lastActivityAtSame as caseCount: the latest message of its cases, or its creation date.