Aller au contenu

Leads

Un lead, c’est une personne à qui ton setter IA parle. L’API expose la même fiche que l’onglet Leads du dashboard : statut, tags, propriétaire, prochaine action, résultat commercial et notes.

Méthode Chemin Scope
GET /leads leads:read
GET /leads/{id} leads:read
PATCH /leads/{id} leads:write
GET /leads/{id}/notes leads:read
POST /leads/{id}/notes leads:write
POST /leads/{id}/handoff leads:write
POST /leads/{id}/resume leads:write

Les leads arrivent du plus récemment actif au plus ancien, 25 par page par défaut.

Terminal window
curl "https://app.whatsetter.com/api/v1/leads?status=qualified&campaign_id=acme-france-1-ab12&limit=25" \
-H "Authorization: Bearer ws_live_…"
{
"data": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"phone": "33612345678",
"whatsapp_id": "33612345678@c.us",
"name": "Julien",
"status": "qualified",
"qualified": true,
"qualified_at": "2026-09-12T10:04:31.000Z",
"replied": true,
"campaign_id": "acme-france-1-ab12",
"list_id": null,
"channel": "whatsapp",
"ig_username": null,
"external_reference": "4471",
"source": "api",
"source_confidence": null,
"tracked_link_id": null,
"email": "julien@example.com",
"tags": ["hot", "demo"],
"messages_count": 14,
"booking_status": "booked",
"first_contact_at": "2026-09-10T08:00:12.000Z",
"last_message_at": "2026-09-18T16:42:05.000Z",
"last_message_direction": "inbound",
"assigned_to": "66a1b2c3d4e5f6a7b8c9d0e1",
"stage": "booked",
"deal_status": "open",
"lost_reason": null,
"next_action_at": "2026-09-22T09:00:00.000Z",
"next_action_label": "Rappeler",
"created_at": "2026-09-10T07:59:58.000Z",
"updated_at": "2026-09-18T16:42:05.000Z"
}
],
"pagination": { "has_more": true, "next_cursor": "66f1a2b3c4d5e6f7a8b9c0d1" }
}

phone ne contient que des chiffres, sans le +. Passe cursor=next_cursor pour obtenir la page suivante.

Paramètre Effet
status Un des statuts ci-dessous. qualified renvoie tous les leads qualifiés à un moment donné (leur date de qualification est renseignée).
campaign_id Le slug campaign_id de la campagne ou son id, les deux viennent de GET /campaigns.
phone Recherche exacte, format international (+33612345678).
external_reference Recherche exacte sur l’identifiant que tu as envoyé avec POST /campaigns/{id}/leads.
source D’où vient le lead : instagram, facebook, tiktok, youtube, linkedin, x, snapchat, pinterest, google, website, email, sms, qr, ads, other, direct, list, api, webhook, inbound, manual.
tracked_link_id Seulement les leads amenés par ce lien traqué.
channel whatsapp ou instagram.
since Seulement les leads actifs après cette date ISO 8601 (sur last_message_at).
limit, cursor Pagination, 1 à 100 par page.
status Signification
queued Importé, en attente de son premier message.
pending L’agent s’est arrêté et attend ton équipe.
in_progress La conversation est en cours.
qualified L’agent a validé l’intérêt, ou tu l’as posé depuis l’API.
not_interested Mauvaise cible ou refus explicite.
cold Pas de réponse après les relances.
stopped La conversation a été arrêtée.
unknown Une valeur interne que l’API publique ne nomme pas.
Terminal window
curl "https://app.whatsetter.com/api/v1/leads/66f1a2b3c4d5e6f7a8b9c0d1" \
-H "Authorization: Bearer ws_live_…"

La réponse est { "data": lead } avec le même objet que ci-dessus. Un lead d’un autre espace de travail répond 404, jamais 403.

N’envoie que les champs que tu changes. Il en faut au moins un.

Terminal window
curl -X PATCH "https://app.whatsetter.com/api/v1/leads/66f1a2b3c4d5e6f7a8b9c0d1" \
-H "Authorization: Bearer ws_live_…" \
-H "Content-Type: application/json" \
-d '{
"status": "qualified",
"tags": ["hot", "demo"],
"assigned_to": "66a1b2c3d4e5f6a7b8c9d0e1",
"next_action_at": "2026-09-22T09:00:00.000Z",
"next_action_label": "Rappeler"
}'

La réponse est le lead mis à jour, 200.

Champ Règles
status qualified, in_progress, not_interested, cold, pending, stopped ou queued. Poser qualified renseigne qualified_at une seule fois.
tags Tableau de 20 chaînes maximum, 40 caractères chacune. Remplace toute la liste. Les tags vides ou trop longs sont ignorés, les doublons retirés.
assigned_to Un id de membre venant de GET /team/members, ou null pour retirer le propriétaire. Id inconnu : 422.
next_action_at Date ISO 8601, ou null.
next_action_label 80 caractères maximum, ou null. Exige une date next_action_at (422 sinon). Effacer la date efface le libellé.
deal_status open, won ou lost.
lost_reason Une valeur parmi price, timing, unqualified, competitor, unreachable, other. Obligatoire avec deal_status: "lost", effacée pour open et won.

Chaque changement écrit le journal du lead, les mêmes événements que le dashboard (owner, next_action, outcome), avec le nom de ta clé API comme acteur.

Les notes sont les textes libres que ton équipe voit sur la fiche du lead.

Terminal window
curl -X POST "https://app.whatsetter.com/api/v1/leads/66f1a2b3c4d5e6f7a8b9c0d1/notes" \
-H "Authorization: Bearer ws_live_…" \
-H "Content-Type: application/json" \
-d '{"text":"Rappelé, veut un devis avant vendredi."}'
{
"data": {
"id": "66f1a2b3c4d5e6f7a8b9c0e2",
"text": "Rappelé, veut un devis avant vendredi.",
"author": "API · Mon CRM",
"created_at": "2026-09-19T08:12:00.000Z"
}
}

text fait 1 à 2000 caractères. L’auteur est API · <nom de la clé> pour les notes que tu crées, ou le nom du coéquipier pour les notes écrites dans le dashboard. GET /leads/{id}/notes renvoie { "data": [ ...notes ] }, les plus récentes d’abord, 100 maximum.

Passer une conversation à un humain, puis la rendre

Section intitulée « Passer une conversation à un humain, puis la rendre »

POST /leads/{id}/handoff arrête l’agent IA sur ce lead. Il reste silencieux jusqu’à ce que tu appelles POST /leads/{id}/resume. C’est le même interrupteur que la prise en main du dashboard, les deux ne peuvent jamais se contredire.

Terminal window
curl -X POST "https://app.whatsetter.com/api/v1/leads/66f1a2b3c4d5e6f7a8b9c0d1/handoff" \
-H "Authorization: Bearer ws_live_…"
{
"data": {
"id": "66f1a2b3c4d5e6f7a8b9c0d1",
"external_reference": "4471",
"agent_active": false,
"manual_override": true,
"status": "in_progress",
"dashboard_synced": true,
"updated_at": "2026-09-19T08:12:00.000Z"
}
}
  • Le status du lead est préservé : prendre la main ne marque jamais un lead comme arrêté ou qualifié.
  • Les deux appels sont idempotents : un deuxième handoff sur un lead déjà pris en main répond 200.
  • dashboard_synced: false signifie que l’agent est bien arrêté mais que la liste Leads peut avoir un temps de retard. La vue conversation est toujours juste.
  • La règle de statut : handoff et resume ne s’appliquent qu’aux leads déjà engagés par l’agent (in_progress, stopped, cold, qualified, not_interested). Un lead queued ou pending n’a pas de conversation à passer et répond 409 invalid_state.

stage est en lecture seule et dérivé du lead exactement comme le funnel du dashboard. Il répond « où en est cette personne commercialement ? » en un mot, alors que status est le vocabulaire propre à l’IA.

stage Quand
contacted Contacté, pas encore de réponse.
conversation Le lead a répondu, l’IA ou un humain lui parle.
waiting L’IA s’est arrêtée et attend ton équipe (status: pending).
qualified Intérêt validé (status: qualified).
booked Un rendez-vous est au calendrier, ou a eu lieu. L’emporte sur toutes les autres valeurs.
not_interested Mauvaise cible ou refus.
cold Pas de réponse après les relances.
stopped La conversation a été arrêtée.

Envoie l’identifiant de ta propre fiche dans external_reference quand tu pousses un lead opt-in avec POST /campaigns/{id}/leads. WhatSetter le stocke tel quel, le renvoie sur chaque lead et chaque webhook, et te laisse le retrouver :

Terminal window
curl "https://app.whatsetter.com/api/v1/leads?external_reference=4471" \
-H "Authorization: Bearer ws_live_…"

external_reference vaut null pour les leads qui ne viennent pas de toi (imports CSV, imports de liste, formulaires de page de vente). Pour ceux-là, compare sur phone : chiffres seuls des deux côtés.

HTTP code Quand
401 missing_api_key, invalid_api_key Clé absente, inconnue ou révoquée.
403 insufficient_scope La clé n’a pas leads:read ou leads:write.
404 not_found Lead inconnu, ou lead d’un autre espace de travail.
409 invalid_state Handoff ou resume sur un lead jamais contacté.
422 validation_error Statut inconnu, téléphone invalide, id de membre inconnu, corps vide, curseur invalide ou expiré.
429 rate_limited Trop de requêtes cette minute. Respecte Retry-After.
502 upstream_error Le workflow de contrôle de l’agent était injoignable. Tu peux réessayer.