Aller au contenu principal
Tous les articles

Automatisation

Votre CRM LinkedIn a une API — voici ce qu'elle sait vraiment faire

L'API publique de Swimlane couvre toute la boucle : importer des contacts depuis LinkedIn, les travailler dans le CRM, construire et lancer des campagnes. Le tour d'horizon, avec les pièges.

Par Swimlane 6 min de lecture

La plupart des « API de CRM » servent à lire des lignes. Celle-ci fait tourner le produit : elle importe des gens depuis LinkedIn, les range, et envoie les séquences. Tout ce que vous faites dans Swimlane, un script peut le faire — sur la même session LinkedIn, sous les mêmes limites quotidiennes.

Voici sa forme, point d’entrée par point d’entrée, avec ce qui surprend en premier.

Créez un jeton dans Réglages → API. Il n’est affiché qu’une fois, et voyage en Authorization: Bearer wpa_… sur chaque appel. La référence complète est sur api.getswimlane.com/docs.

Les contacts entrent par un import

C’est la partie qu’on cherche en dernier et dont on a besoin en premier. POST /v1/imports crée une liste et la remplit depuis LinkedIn :

curl -X POST https://api.getswimlane.com/v1/imports \
  -H "Authorization: Bearer wpa_…" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "competitor_engagement",
    "listName": "Ont réagi à Acme — septembre",
    "profileUrl": "https://www.linkedin.com/in/acme-founder/",
    "recurring": true
  }'

Sept sources existent : les gens qui ont réagi à un post (post_engagement), à ceux d’un concurrent (competitor_engagement) ou aux vôtres (profile_engagement) ; ceux qui ont visité votre profil sur une période (profile_visitors) ; une recherche de personnes écrite comme un persona (people_search) ; un sujet transformé en recherche booléenne (topic_search) ; et les gens que LinkedIn vous suggère (suggested_contacts).

Trois choses à anticiper :

  • La réponse est un 202, et la liste est vide. Le scraping tourne en arrière-plan sur votre propre session LinkedIn. Surveillez GET /v1/queue, ou le status de la liste qui passe scheduled → importing → done.
  • La limite quotidienne d’imports est réclamée à l’exécution, pas à l’appel. Un import lancé au-delà attend le lendemain au lieu d’échouer : mettre une journée de sourcing en file d’un coup ne casse rien. Idem pour vos horaires de bureau virtuels — une exécution en dehors est reportée, pas perdue.
  • recurring: true garde la liste en train de se remplir, toutes les quelques heures. L’intervalle est retiré au hasard dans une fourchette à chaque exécution : un métronome est une signature d’automatisation, donc il n’est pas réglable. Les planifications se gèrent sur GET|PATCH|DELETE /v1/imports/recurring.

Les contacts, et le champ qui décide de tout

GET /v1/contacts cherche dans les noms et les e-mails, filtre par liste, par tag ou par archivage. POST, PATCH et DELETE font ce que vous attendez.

Le champ qui compte, c’est linkedinId :

{ "firstName": "Sofia", "lastName": "Marchetti", "linkedinId": "https://www.linkedin.com/in/sofia-marchetti/" }

Il accepte l’identifiant public ou l’URL de profil qui le contient, et c’est lui qui rend un contact joignable. Un contact sans lui est une fiche CRM et rien d’autre : chaque étape de campagne qui touche à LinkedIn le refuse, réessaie trois fois et finit en failed. Et il ne se devine pas plus tard à partir d’un nom ou d’un e-mail. Si vous poussez des leads venus d’ailleurs pour les séquencer, transportez l’URL de profil.

Il est unique par espace de travail : un doublon répond 409 et nomme le contact qui le détient déjà, plutôt que de fusionner deux personnes en silence.

Listes, tags et pipelines

POST /v1/lists/<uuid>/contacts ajoute des contacts en lot ; ceux déjà présents sont ignorés, l’appel est donc rejouable. Une chose à savoir avant de l’automatiser : si une campagne continue en cours utilise cette liste comme source, les contacts que vous ajoutez commencent à recevoir ses invitations dans la minute. C’est tout l’intérêt du montage — un import de sourcing plus une campagne continue font un pipeline qui s’alimente seul — mais l’appel n’est pas inerte.

Les tags sont partagés : la table tags tient une ligne par nom, et « inbound » est le même tag dans tous les espaces de travail. Renommer un tag que d’autres utilisent le copie donc d’abord et renomme la copie, et en supprimer un ne fait que le détacher de vos contacts. POST /v1/contacts/<uuid>/tags remplace l’ensemble : envoyez tous les identifiants que le contact doit avoir au final, sinon ceux que vous omettez disparaissent.

Les pipelines portent un champ de plus qui mérite d’être renseigné : le type d’une étape, done ou abandoned. Les deux sont terminaux, et Swimlane cesse de proposer ces contacts en relance. Une colonne « Gagné » créée sans lui continue de vous rappeler des affaires closes depuis des mois.

Les campagnes, de bout en bout

Trois appels, dans cet ordre.

# 1. un brouillon, pointé sur la liste que l'import a remplie
POST /v1/campaigns
{"name": "Engagés Acme", "type": "outbound", "listUuid": "…", "continuous": true}

# 2. le flux, en arbre envoyé d'un bloc
PUT /v1/campaigns/<uuid>/steps

# 3. l'envoi démarre
POST /v1/campaigns/<uuid>/start

C’est le flux qui demande du soin. Chaque étape porte un id que vous choisissez et désigne son parent avec parentId ; un parent doit apparaître plus tôt dans le tableau, et exactement une étape n’a pas de parent. La ramification, c’est branchKey, et il vaut "yes" ou "no" — rien d’autre. Sous une condition il est obligatoire, et son sens suit le parent : pour un connection_request, yes signifie « l’invitation a été acceptée » ; pour un send_message, yes signifie « la personne a répondu ».

{"steps": [
  {"id": "invite", "type": "connection_request"},
  {"id": "connecte?", "type": "condition", "parentId": "invite",
   "conditionType": "is_connected", "delayDays": 3},
  {"id": "intro", "type": "send_message", "parentId": "connecte?", "branchKey": "yes",
   "messageTemplate": "Merci pour la connexion ! Sur quoi travaillez-vous ce trimestre ?"},
  {"id": "plus-tard", "type": "add_tag", "parentId": "connecte?", "branchKey": "no",
   "tagName": "invitation-en-attente"}
]}

Un flux qui ne peut pas fonctionner est refusé par un 422 qui nomme le problème : un enfant de condition sans branche, une branche sous une étape qui ne ramifie pas, deux enfants sur la même branche, une étape à qui manque ce que son type exécute. Le guide complet, avec l’exemple ci-dessus d’un seul tenant, est dans la description de PUT /steps de la référence.

Les étapes sont gelées dès qu’une campagne quitte draft : les contacts enrôlés pointent sur l’étape où ils sont, un remplacement les laisserait en rade. Le nom, la description et le ciblage restent modifiables à tout statut.

Après start, l’enrôlement tourne en arrière-plan — GET /v1/campaigns/<uuid>/stats reste vide une minute environ. Ce n’est pas une panne.

Quand rien ne semble se passer

Deux points d’entrée répondent à cette question plus vite que tout le reste.

GET /v1/account/usage met chaque compteur journalier à côté de la limite qui lui est fixée. Un compteur au plafond est la raison habituelle d’une campagne devenue muette : les quotas existent pour qu’un compte ressemble à une personne qui utilise LinkedIn, et ils s’appliquent au travail déclenché par l’API exactement comme à celui de l’app.

GET /v1/queue montre ce qui est programmé, en cours ou terminé, failed compris. À elles deux, « pourquoi rien n’est parti depuis mardi » est normalement une question de trente secondes.

Le code de la route

  • 100 requêtes par minute et par jeton, avec les en-têtes X-RateLimit-* sur chaque réponse.
  • Un jeton agit comme son propriétaire, et les campagnes tournent sur la session LinkedIn de cette personne — un jeton ne voit donc jamais les campagnes d’un collègue et n’y touche pas.
  • Chaque appel est journalisé dans Réglages → API, avec sa méthode, son chemin, son statut et sa durée. Utile quand un workflow déraille à 3 h du matin.
  • Les erreurs ont une seule forme : {"error": "domaine.action.raison", "message": "…"}. 409 veut dire que l’état l’interdit, 422 que la charge utile est incohérente.

Si vous préférez décrire ce que vous voulez plutôt que d’écrire les appels, la même surface est offerte aux assistants IA : voir connecter Claude à votre CRM LinkedIn.

Faites-le avec Swimlane

Tout ce qu’il y a dans cet article, sans la partie manuelle.

Démarrer mon essai gratuit

Voir comment Swimlane le fait Assistant IA

À lire ensuite