Aller au contenu

Listes et import

Une liste, c’est un lot de contacts destiné à une campagne. C’est la seule porte pour la prospection à froid : les contacts passent par la vérification et l’envoi cadencé anti-ban de WhatSetter, jamais par un envoi direct.

Méthode Chemin Scope
GET /lists lists:read
POST /lists lists:write
POST /lists/{id}/leads lists:write
Terminal window
curl -X POST "https://app.whatsetter.com/api/v1/lists" \
-H "Authorization: Bearer ws_live_…" \
-H "Content-Type: application/json" \
-d '{"name":"Sync CRM, leads chauds"}'
{
"data": {
"id": "66f1a2b3c4d5e6f7a8b9c0a1",
"name": "Sync CRM, leads chauds",
"status": "ready",
"total_rows": 0,
"valid_leads": 0,
"invalid_leads": 0,
"created_at": "2026-09-19T08:00:00.000Z"
}
}

name fait 1 à 255 caractères. Un espace de travail peut contenir 200 listes au maximum ; au-delà, 429 quota_exceeded.

Jusqu’à 500 leads par appel. Chaque lead a besoin d’un phone au format international. name, email et custom_variables sont optionnels.

Terminal window
curl -X POST "https://app.whatsetter.com/api/v1/lists/66f1a2b3c4d5e6f7a8b9c0a1/leads" \
-H "Authorization: Bearer ws_live_…" \
-H "Content-Type: application/json" \
-d '{
"leads": [
{ "phone": "+33612345678", "name": "Julien", "email": "julien@example.com",
"custom_variables": { "ville": "Lyon", "offre": "Pro" } },
{ "phone": "+33698765432", "name": "Marie" }
]
}'
{
"data": {
"imported": 2,
"duplicates_in_list": 0,
"rejected": [],
"lead_ids": ["66f1a2b3c4d5e6f7a8b9c0b1", "66f1a2b3c4d5e6f7a8b9c0b2"]
}
}

Le statut est 201 dès qu’au moins un lead était importable. lead_ids sont les lignes importées, dans l’ordre de création. name et email sont coupés à 255 caractères.

Cas Ce qui se passe
Même numéro deux fois dans le lot Le premier est gardé, l’autre apparaît dans rejected avec la raison duplicate_in_batch.
Numéro déjà dans cette liste Pas recréé, compté dans duplicates_in_list.
Numéro invalide Dans rejected avec une raison qui commence par invalid_phone. Un numéro valide fait 8 à 15 chiffres, avec ou sans +, espaces, points, tirets ou parenthèses.
custom_variables n’est pas un objet Rejeté avec la raison custom_variables must be an object.
custom_variables dépasse 2000 caractères une fois sérialisé Rejeté avec la raison custom_variables exceeds 2000 characters.

Les entrées de rejected portent l’index du lead dans ton tableau, pour journaliser ou réessayer précisément.

Les colonnes personnalisées deviennent des variables

Section intitulée « Les colonnes personnalisées deviennent des variables »

Chaque clé de custom_variables devient une variable par lead que ton agent peut utiliser dans son premier message, écrite {{lead:clé}} dans l’éditeur de prompt. Les clés sont normalisées en slug : accents retirés, minuscules, tout ce qui n’est pas une lettre ou un chiffre devient _. Ville du client et ville_du_client sont la même variable.

Avec l’exemple ci-dessus, le prompt peut dire {{lead:ville}} et {{lead:offre}}. Une clé absente sur un lead donné est signalée à l’agent comme non fournie, avec la consigne de ne jamais inventer de valeur.

GET /lists renvoie les 100 listes les plus récentes de l’espace de travail, dans data, les plus récentes d’abord. Pas de curseur sur cet endpoint.

{
"data": [
{
"id": "66f1a2b3c4d5e6f7a8b9c0a1",
"name": "Sync CRM, leads chauds",
"status": "ready",
"total_rows": 2,
"valid_leads": 0,
"invalid_leads": 0,
"created_at": "2026-09-19T08:00:00.000Z"
}
]
}

valid_leads et invalid_leads se remplissent à mesure que WhatSetter vérifie les numéros après l’import.

Importer n’envoie rien. La liste est prise en charge par la campagne à laquelle elle est rattachée dans le dashboard : les lignes sont vérifiées, puis envoyées à un rythme humain, dans le quota quotidien du numéro. Rattache la liste depuis ta campagne dans le dashboard, puis suis les leads avec GET /leads?campaign_id=.

Quand une personne vient de s’inscrire sur ton funnel et attend un message maintenant, utilise plutôt POST /campaigns/{id}/leads. Il envoie tout de suite un premier message personnalisé, avec les mêmes protections anti-ban, et te laisse joindre un external_reference.

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 lists:read ou lists:write.
404 not_found Liste inconnue, ou liste d’un autre espace de travail.
422 validation_error name absent ou trop long ; leads qui n’est pas un tableau de 1 à 500 ; aucun lead importable dans le lot (le message donne la première raison).
429 quota_exceeded 200 listes existent déjà dans l’espace de travail.
429 rate_limited Trop de requêtes cette minute. Respecte Retry-After.