Démarrage rapide
Cinq requêtes, en cURL, JavaScript et Python. À la fin tu as une clé, une liste de contacts et un webhook qui te prévient quand un lead est qualifié.
Avant de commencer
Section intitulée « Avant de commencer »- Tu es propriétaire ou admin de ton espace WhatSetter. La page API le dit : Seuls les propriétaires et admins peuvent gérer les clés API.
- Tu as
curl, Node.js 18 ou plus récent, ou Python 3 avecrequests. - L’URL de base est
https://app.whatsetter.com/api/v1.
1. Crée une clé API
Section intitulée « 1. Crée une clé API »- Ouvre Paramètres, puis API & MCP.
- Clique sur Créer une clé.
- Renseigne Nom de la clé (par exemple
Sync CRM) et choisis les Permissions : Accès complet, ou Personnalisé pour cocher les scopes un par un. - Clique sur Créer la clé.
- Copie la clé. La fenêtre le dit : Copie ta clé maintenant. Elle ne sera plus jamais affichée. Puis clique sur J’ai enregistré ma clé.
Range-la dans une variable d’environnement, jamais dans ton code :
export WHATSETTER_API_KEY="ws_live_…"2. Vérifie la clé
Section intitulée « 2. Vérifie la clé »GET /me ne demande aucun scope. Il te dit quel espace et quelles permissions la clé possède.
curl https://app.whatsetter.com/api/v1/me \ -H "Authorization: Bearer $WHATSETTER_API_KEY"const res = await fetch('https://app.whatsetter.com/api/v1/me', { headers: { Authorization: `Bearer ${process.env.WHATSETTER_API_KEY}` },});console.log(await res.json());import os, requests
r = requests.get( "https://app.whatsetter.com/api/v1/me", headers={"Authorization": f"Bearer {os.environ['WHATSETTER_API_KEY']}"},)print(r.json()){ "data": { "team_id": "6b0c1d2e3f405162738a", "key": { "id": "66f1a2b3c4d5e6f7a8b9c0d1", "name": "Sync CRM", "scopes": ["leads:read", "leads:write", "lists:write", "webhooks:manage"] } }}Un 401 invalid_api_key signifie que la clé est mal copiée ou révoquée. Un 401 missing_api_key signifie que l’en-tête ne nous est pas parvenu.
3. Liste tes leads
Section intitulée « 3. Liste tes leads »GET /leads demande leads:read. Filtre par status, campaign_id, phone, source ou since, et pagine avec limit (1 à 100) et cursor.
curl "https://app.whatsetter.com/api/v1/leads?status=qualified&limit=10" \ -H "Authorization: Bearer $WHATSETTER_API_KEY"const url = new URL('https://app.whatsetter.com/api/v1/leads');url.searchParams.set('status', 'qualified');url.searchParams.set('limit', '10');
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.WHATSETTER_API_KEY}` },});const { data, pagination } = await res.json();console.log(data.length, pagination.next_cursor);import os, requests
r = requests.get( "https://app.whatsetter.com/api/v1/leads", params={"status": "qualified", "limit": 10}, headers={"Authorization": f"Bearer {os.environ['WHATSETTER_API_KEY']}"},)body = r.json()print(len(body["data"]), body["pagination"]["next_cursor"]){ "data": [ { "id": "66f1a2b3c4d5e6f7a8b9c0d1", "phone": "33612345678", "name": "Julien", "status": "qualified", "qualified": true, "qualified_at": "2026-09-18T09:12:41.000Z", "campaign_id": "acme-france-1-ab12", "source": "list", "tags": ["hot"], "messages_count": 14, "last_message_at": "2026-09-18T09:12:00.000Z", "last_message_direction": "inbound" } ], "pagination": { "has_more": false, "next_cursor": null }}L’objet lead est raccourci ici. Quand has_more vaut true, renvoie next_cursor dans cursor pour obtenir la page suivante.
4. Importe une liste de contacts
Section intitulée « 4. Importe une liste de contacts »Deux appels : POST /lists crée une liste vide, puis POST /lists/{id}/leads y pousse jusqu’à 500 contacts par appel. Les deux demandent lists:write. Les numéros sont dédupliqués dans le lot et contre la liste.
# 1. Créer la listecurl -X POST https://app.whatsetter.com/api/v1/lists \ -H "Authorization: Bearer $WHATSETTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name":"Sync CRM, leads chauds"}'
# 2. Y pousser des contacts (remplace LIST_ID par l'id de l'étape 1)curl -X POST https://app.whatsetter.com/api/v1/lists/LIST_ID/leads \ -H "Authorization: Bearer $WHATSETTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"leads":[{"phone":"+33612345678","name":"Julien","custom_variables":{"ville":"Lyon"}}]}'const headers = { Authorization: `Bearer ${process.env.WHATSETTER_API_KEY}`, 'Content-Type': 'application/json',};
// 1. Créer la listeconst created = await fetch('https://app.whatsetter.com/api/v1/lists', { method: 'POST', headers, body: JSON.stringify({ name: 'Sync CRM, leads chauds' }),});const { data: list } = await created.json();
// 2. Y pousser des contactsconst imported = await fetch(`https://app.whatsetter.com/api/v1/lists/${list.id}/leads`, { method: 'POST', headers, body: JSON.stringify({ leads: [{ phone: '+33612345678', name: 'Julien', custom_variables: { ville: 'Lyon' } }], }),});console.log(await imported.json());import os, requests
headers = {"Authorization": f"Bearer {os.environ['WHATSETTER_API_KEY']}"}base = "https://app.whatsetter.com/api/v1"
# 1. Créer la listelst = requests.post(f"{base}/lists", headers=headers, json={"name": "Sync CRM, leads chauds"}).json()["data"]
# 2. Y pousser des contactsr = requests.post( f"{base}/lists/{lst['id']}/leads", headers=headers, json={"leads": [{"phone": "+33612345678", "name": "Julien", "custom_variables": {"ville": "Lyon"}}]},)print(r.json()){ "data": { "imported": 1, "duplicates_in_list": 0, "rejected": [], "lead_ids": ["66f1a2b3c4d5e6f7a8b9c0d2"] }}5. Crée un webhook
Section intitulée « 5. Crée un webhook »POST /webhooks demande webhooks:manage. L’endpoint doit être en HTTPS.
curl -X POST https://app.whatsetter.com/api/v1/webhooks \ -H "Authorization: Bearer $WHATSETTER_API_KEY" \ -H "Content-Type: application/json" \ -d '{"url":"https://ton-serveur.com/webhooks/whatsetter","events":["contact.qualified","contact.not_qualified"]}'const res = await fetch('https://app.whatsetter.com/api/v1/webhooks', { method: 'POST', headers: { Authorization: `Bearer ${process.env.WHATSETTER_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ url: 'https://ton-serveur.com/webhooks/whatsetter', events: ['contact.qualified', 'contact.not_qualified'], }),});const { data } = await res.json();console.log(data.secret); // whsec_… affiché une seule fois, stocke-le maintenantimport os, requests
r = requests.post( "https://app.whatsetter.com/api/v1/webhooks", headers={"Authorization": f"Bearer {os.environ['WHATSETTER_API_KEY']}"}, json={"url": "https://ton-serveur.com/webhooks/whatsetter", "events": ["contact.qualified", "contact.not_qualified"]},)print(r.json()["data"]["secret"]) # whsec_… affiché une seule fois, stocke-le maintenant{ "data": { "id": "66f1c0ffee00000000000abc", "url": "https://ton-serveur.com/webhooks/whatsetter", "events": ["contact.qualified", "contact.not_qualified"], "active": true, "description": null, "secret_prefix": "whsec_3f9a", "secret": "whsec_3f9a…", "last_delivery_at": null, "last_delivery_status": null, "created_at": "2026-09-19T10:00:00.000Z" }}Le secret n’apparaît que dans cette réponse. Stocke-le : tu en as besoin pour vérifier la signature de chaque livraison. Envoie-toi ensuite un événement de test signé avec POST /webhooks/{id}/test.
La suite
Section intitulée « La suite »- Authentification et permissions : scopes, limites de débit, rotation des clés.
- Erreurs, limites et idempotence : chaque
code, et comment réessayer sans risque. - Les guides par ressource : leads, campagnes, messages, groupes, contacts bloqués, liens.
- Serveur MCP : donne la même clé à Claude, Cursor ou ChatGPT.
- Utiliser ces docs avec des assistants IA : laisse un assistant construire l’intégration pour toi.

