Contacts et leads API v2
Répertoriez les contacts et les leads, effectuez un upsert d’un contact par ID externe, et importez des contacts en masse pour un agent.
Contact payloads expose customAttributes; write requests accept customAttributes.plan and other JSON keys such as customAttributes.seats.
Les contacts associent vos propres identifiants stables d’utilisateurs finaux à des noms, adresses e-mail et numéros de téléphone. Les leads sont des soumissions en lecture seule capturées par un agent. Chaque point de terminaison de cette page nécessite Authorization: Bearer YOUR_API_KEY et un accès à {agentId}.
Pour les revendications d’identité signées dans le chat intégré, consultez Vérification d’identité. Consultez le catalogue des erreurs pour connaître les erreurs d’authentification et de validation communes.
Objet Contact
| Champ | Type | Remarques |
|---|---|---|
id | chaîne | UUID du contact. |
externalId | chaîne | Votre identifiant stable d’utilisateur final. |
name | chaîne ou null | Nom du contact. |
email | chaîne ou null | Adresse e-mail du contact. |
phone | chaîne ou null | Numéro de téléphone du contact. |
createdAt | entier ou null | Horodatage Unix en secondes. |
updatedAt | entier ou null | Horodatage Unix en secondes. |
lastSeenAt | entier ou null | Horodatage Unix en secondes. |
Lister les contacts
Chemin : /api/v2/agents/{agentId}/contacts
GET /api/v2/agents/{agentId}/contacts
Authentification : clé API Bearer ayant accès à {agentId}.
| Paramètre | Obligatoire | Contraintes |
|---|---|---|
limit | Non | Entier de 1 à 100 ; 20 par défaut. |
cursor | Non | Curseur opaque renvoyé par la page précédente. Réutilisez-le tel quel. |
search | Non | Recherche de sous-chaîne insensible à la casse (ILIKE), sans espaces superflus, portant sur l’ID externe, l’e-mail, le nom et le téléphone. Les signes pourcentage (%) sont supprimés, mais le tiret bas (_) n’est pas échappé et agit comme un caractère générique remplaçant un seul caractère — par exemple, acct_1 correspond aussi à acctX1. Un résultat vide après suppression des espaces est ignoré. |
curl 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/contacts?search=alice&limit=20' \ -H 'Authorization: Bearer YOUR_API_KEY'
Succès : 200 OK
{
"data": [
{
"id": "f9878f31-c2b3-469f-a82e-26e996e67721",
"externalId": "customer_123",
"name": "Alice Example",
"email": "[email protected]",
"phone": "+1 555 0100",
"customAttributes": { "plan": "pro", "seats": 4 },
"createdAt": 1784332800,
"updatedAt": 1784332800,
"lastSeenAt": null
}
],
"pagination": {
"cursor": null,
"hasMore": false,
"total": 1
}
}
Une limite ou un curseur invalide renvoie 400 VALIDATION_INVALID_BODY.
Objet Lead
| Champ | Type | Remarques |
|---|---|---|
id | chaîne | UUID du lead. |
name | chaîne ou null | Nom soumis. |
email | chaîne ou null | Adresse e-mail soumise. |
phone | chaîne ou null | Numéro de téléphone soumis. |
conversationId | chaîne ou null | ID de référence public de la conversation, lorsque le lead est lié à une conversation. |
createdAt | entier | Horodatage Unix en secondes. |
Lister les leads
Chemin : /api/v2/agents/{agentId}/leads
GET /api/v2/agents/{agentId}/leads
Authentification : clé API Bearer ayant accès à {agentId}.
| Paramètre | Obligatoire | Contraintes |
|---|---|---|
limit | Non | Entier de 1 à 100 ; 20 par défaut. |
cursor | Non | Curseur opaque renvoyé par la page précédente. Réutilisez-le tel quel. |
createdAfter | Non | Date-heure ISO 8601 avec Z ou un décalage UTC. La borne inférieure est incluse. |
createdBefore | Non | Date-heure ISO 8601 avec Z ou un décalage UTC. La borne supérieure est incluse. |
Lorsque les deux filtres de date sont présents, createdAfter doit être inférieur ou égal à createdBefore une fois comparés en tant qu’instants. Des bornes égales sont valides.
curl 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/leads?createdAfter=2026-07-18T08:00:00Z&limit=20' \ -H 'Authorization: Bearer YOUR_API_KEY'
Succès : 200 OK
{
"data": [
{
"id": "ad47f673-6bfb-43a0-a296-d79c84870a32",
"name": "Alice Example",
"email": "[email protected]",
"phone": "+1 555 0100",
"conversationId": "a1b2c3d4e5f6g7h8",
"createdAt": 1784361600
}
],
"pagination": {
"cursor": null,
"hasMore": false,
"total": 1
}
}
Les leads sont classés par heure de soumission, du plus récent au plus ancien. Une limite, un curseur, une date-heure invalide, ou des bornes de date inversées renvoient 400 VALIDATION_INVALID_BODY.
Créer ou mettre à jour un contact
POST /api/v2/agents/{agentId}/contacts
Authentification : clé API Bearer ayant accès à {agentId}.
Ce point de terminaison effectue un upsert sur la paire {agentId, externalId}. Lorsqu’un contact correspondant existe, seuls les champs de profil présents dans la requête sont mis à jour. Un champ omis conserve sa valeur enregistrée ; une valeur null ou une chaîne vide explicite l’efface.
| Champ du corps | Obligatoire | Type et contraintes |
|---|---|---|
externalId | Oui | Chaîne, sans espaces superflus, de 1 à 255 caractères. |
name | Non | Chaîne réduite à 255 caractères maximum (espaces superflus supprimés), ou null. |
email | Non | Adresse e-mail valide réduite à 320 caractères maximum (espaces superflus supprimés), chaîne vide, ou null. |
phone | Non | Chaîne réduite à 50 caractères maximum (espaces superflus supprimés), chaîne vide, ou null. |
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/contacts' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"externalId":"customer_123","name":"Alice Example","email":"[email protected]","customAttributes":{"plan":"pro","seats":4}}'
Succès : 201 Created pour les insertions comme pour les mises à jour en cas de conflit. L’objet contact est renvoyé nu.
{
"id": "f9878f31-c2b3-469f-a82e-26e996e67721",
"externalId": "customer_123",
"name": "Alice Example",
"email": "[email protected]",
"phone": null,
"customAttributes": { "plan": "pro", "seats": 4 },
"createdAt": 1784332800,
"updatedAt": 1784332800,
"lastSeenAt": null
}
Un corps invalide renvoie 400 VALIDATION_INVALID_BODY avec des détails de validation.
Importer des contacts
Chemin : /api/v2/agents/{agentId}/contacts/import
POST /api/v2/agents/{agentId}/contacts/import
Authentification : clé API Bearer ayant accès à {agentId}.
La requête utilise des noms de champs en snake_case. rows doit contenir de 1 à 1 000 entrées.
| Champ de ligne | Obligatoire | Type et contraintes |
|---|---|---|
external_id | Oui | Chaîne, sans espaces superflus, de 1 à 255 caractères. |
name | Non | Chaîne réduite à 255 caractères maximum (espaces superflus supprimés), ou null. |
email | Non | Adresse e-mail valide réduite à 320 caractères maximum (espaces superflus supprimés), chaîne vide, ou null. |
phone | Non | Chaîne réduite à 50 caractères maximum (espaces superflus supprimés), ou null ; une chaîne vide est également acceptée et stockée comme null. |
Les lignes sont dédupliquées par external_id au sein de la requête ; la dernière occurrence l’emporte. Contrairement à l’upsert partiel d’un contact unique, l’import construit chaque champ de profil pour chaque ligne conservée, si bien qu’une valeur de profil omise, null, ou vide est stockée comme null en cas de conflit.
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/contacts/import' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"rows":[{"external_id":"customer_123","name":"Alice Example","email":"[email protected]","phone":"+1 555 0100","customAttributes":{"plan":"pro"}},{"external_id":"customer_456","name":"Bob Example","email":"[email protected]","phone":null}]}'
Succès : 200 OK
{
"processed": 2,
"skipped": 0
}
processed correspond au nombre d’ID externes uniques ayant fait l’objet d’un upsert. skipped correspond au nombre de lignes en double retirées du lot soumis. Un corps invalide — y compris les lots vides et les lots de plus de 1 000 lignes — renvoie 400 VALIDATION_INVALID_BODY.