Référence de l'API publique Swimlane
Tour d'horizon de tous les endpoints de l'API publique, avec les champs que vous pouvez envoyer et lire. Pour une prise en main concrète, voir Créer un token API et faire votre première requête. La version interactive se trouve sur https://api.getswimlane.com/docs.
L'essentiel
- URL de base :
https://api.getswimlane.com/v1 - Authentification :
Authorization: Bearer wpa_…, avec un token créé dans Paramètres → API. - Périmètre : tout se passe dans l'organisation utilisée en dernier dans l'application. Les campagnes, les rappels et les imports récurrents sont limités plus finement, à l'utilisateur du token : ils tournent sur la session LinkedIn de cette personne, donc un token ne voit jamais ceux d'un coéquipier.
- Pagination (endpoints de liste) :
page,per_page(50 par défaut, 100 au maximum). Les réponses ont la forme{ "meta": {…}, "data": [ … ] }. - Limite : 100 requêtes par minute par utilisateur, avec les en-têtes
X-RateLimit-*sur chaque réponse. - Erreurs :
401token invalide,403aucune organisation,404resource.not_found,409l'état l'interdit,422validation.failedavec un tableauerrors,429rate_limit.exceeded. - Tout est journalisé dans Paramètres → API : méthode, chemin, statut et durée.
Imports — par où entrent les contacts
POST /imports crée une liste et la remplit depuis LinkedIn. C'est le point d'entrée : tous les autres endpoints travaillent sur des contacts déjà présents.
{
"source": "competitor_engagement",
"listName": "Ont réagi à Acme — septembre",
"profileUrl": "https://www.linkedin.com/in/acme-founder/",
"recurring": true
}
source |
Qui est récupéré | Champs requis |
|---|---|---|
post_engagement |
ceux qui ont réagi ou commenté un post | postUrl |
competitor_engagement |
ceux qui réagissent aux posts de quelqu'un d'autre | profileUrl |
profile_engagement |
ceux qui réagissent à vos propres posts | — |
profile_visitors |
ceux qui ont visité votre profil sur une période | from, to |
people_search |
une recherche de personnes écrite comme un persona | persona |
topic_search |
un sujet transformé en recherche booléenne | topic, strategy |
suggested_contacts |
les personnes que LinkedIn vous suggère | — |
- La réponse est un
202, et la liste est vide. La collecte tourne en arrière-plan sur votre session LinkedIn ; suivez-la avecGET /queue, ou regardez lestatusde la liste passerscheduled → 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, et une exécution en dehors de vos horaires de bureau virtuels est reportée, pas perdue.
- Une source à qui manque un champ répond
422 import.missing_parameters. recurring: trueenregistre en plus une planification. Gérez-les avecGET /imports/recurring,PATCH /imports/recurring/:uuid({"isActive": false}met en pause) etDELETE /imports/recurring/:uuid(la liste et ses contacts sont conservés). L'intervalle est tiré au hasard dans une fourchette à chaque exécution :frequencyHoursindique donc le dernier utilisé, pas une cadence réglable — un métronome est une signature d'automatisation.
Contacts
GET /contacts: du plus récent au plus ancien. Filtres :search(prénom, nom ou e-mail),list_uuid,tag_id,archived.GET /contacts/:uuid,POST /contacts,PATCH /contacts/:uuid,DELETE /contacts/:uuid.
Champs que vous pouvez envoyer (tous facultatifs) : firstName, lastName, email, phone, website, headline, note, location, countryIso (2 lettres), archived, linkedinId.
Champs que vous lisez : les précédents plus uuid, avatarUrl, followersCount, isPremium, isCreator, isInfluencer, listUuids, companyUuids, tagIds, pipelineStageUuid, createdAt, updatedAt.
Remarques :
linkedinIdest le champ qui décide de tout. Il accepte l'identifiant public ou l'URL de profil qui le contient (https://www.linkedin.com/in/…), 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 enfailed. Il ne se devine pas plus tard à partir d'un nom ou d'un e-mail : transportez l'URL de profil quand vous poussez des leads venus d'ailleurs.- Il est unique par organisation. Un doublon répond
409 contact.linkedin_id_takenet nomme le contact qui le détient déjà, plutôt que de fusionner deux personnes. - Écrire
noteouheadlinemarque les scores ICP en cache comme périmés, pour qu'ils soient recalculés. pipelineStageUuidrenvoie une seule étape, prise dans les pipelines que vous voyez.- Les réponses à
POSTetPATCHlaissentlistUuids,companyUuidsettagIdsvides etpipelineStageUuidà null. Relisez le contact avecGETpour les obtenir. - Les réponses contiennent aussi un champ
score: c'est une valeur interne que l'application n'affiche plus. Ne construisez rien dessus.
Listes
GET /lists,GET /lists/:uuid,POST /lists(nameobligatoire,description,icon),PATCH,DELETE.POST /lists/:uuid/contacts: corps{"contactUuids": ["…"]}. Les contacts déjà présents et les uuids inconnus sont ignorés sans erreur.DELETE /lists/:uuid/contacts/:contactUuid.
Champs que vous lisez : uuid, name, description, icon, status, source, createdAt, updatedAt. source nomme l'import qui a produit la liste, ou vaut null si quelqu'un l'a créée à la main.
Ajouter à une liste n'est pas inerte. Si une campagne en cours l'utilise comme source et a été créée avec continuous: true, les contacts que vous ajoutez sont enrôlés au prochain balayage : dans la minute environ, ils commencent à recevoir ses invitations et ses messages.
Entreprises (lecture seule)
GET /companies (filtre : search), GET /companies/:uuid. Champs : uuid, name, linkedinId, logoUrl, createdAt, updatedAt.
Tags
GET /tags,POST /tags(nameobligatoire,coloren#RRGGBB),PATCH /tags/:id,DELETE /tags/:id.GET /contacts/:uuid/tags,POST /contacts/:uuid/tagsavec{"tagIds": [12, 18]}. Cette liste remplace tous les tags du contact. Envoyez[]pour tous les retirer.
Un tag est une ligne par nom, partagée par tous les espaces de travail. « inbound » est le même tag partout. 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. Ni l'un ni l'autre ne peut atteindre l'espace de travail de quelqu'un d'autre.
Pipelines et étapes
GET /pipelines,POST /pipelines(nameobligatoire,visibilityprivateouteam,icon),PATCH,DELETE.GET /pipelines/:uuid/stages,POST /pipelines/:uuid/stages,PATCH /pipelines/stages/:stageUuid,DELETE /pipelines/stages/:stageUuid.POST /pipelines/stages/:stageUuid/contactsavec{"contactUuids": ["…"]}. Un contact occupe une seule étape par pipeline : il est donc déplacé.DELETE /pipelines/stages/:stageUuid/contacts/:contactUuid.
Champs d'une étape : uuid, name, icon, color, type, order, createdAt, updatedAt.
typevautdone,abandonedou null, et se définit à la création comme à la modification. Les deux valeurs sont terminales : 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.- Un nouveau pipeline arrive avec les quatre étapes que crée l'application — Cold, Connected, Engaged et Closed, la dernière déjà typée
done. - Le pipeline privé d'un coéquipier ne peut être ni lu ni modifié.
visibility: teamest le seul moyen d'en partager un.
Rappels
GET /reminders (filtres : completed, contact_uuid, due_after, due_before, order), GET /reminders/:uuid, POST, PATCH, DELETE, et GET /contacts/:uuid/reminders.
Un rappel est une tâche personnelle, limitée à l'utilisateur du token. L'échéance est stockée à minuit : l'application ne propose pas de choisir l'heure, donc une heure envoyée est ignorée plutôt que de mal se trier face à celles de l'app.
Campagnes
GET /campaigns(filtres :type,status),GET /campaigns/:uuid,POST,PATCH,DELETE.POST /campaigns/:uuid/start|pause|resume.GET|PUT /campaigns/:uuid/steps,GET /campaigns/:uuid/contacts,GET /campaigns/:uuid/stats.
Trois appels mènent de rien à une campagne qui tourne : créer un brouillon pointé sur une liste, envoyer le flux en PUT, puis start.
Le flux est un arbre envoyé d'un bloc. 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. branchKey vaut "yes" ou "no", rien d'autre : obligatoire sous une condition, facultatif sous connection_request (yes = l'invitation a été acceptée) et send_message (yes = la personne a répondu), refusé partout ailleurs. Un flux qui ne peut pas fonctionner est refusé par un 422 qui nomme le problème.
Les étapes sont gelées dès qu'une campagne quitte draft — les contacts enrôlés pointent sur l'étape où ils sont. Après start, l'enrôlement tourne en arrière-plan : les statistiques restent vides une minute environ.
Supprimer une campagne annule aussi tout ce qu'elle avait mis en file.
La file d'attente et votre compte
GET /queue(filtres :statepending/running/done,method,since),GET /queue/:id. Lecture seule : ce que l'application a programmé, exécute ou a terminé,failedcompris.GET|PATCH /account,GET|PATCH /account/settings(limites quotidiennes, horaires de bureau virtuels, ton de voix),GET /account/usage.
Quand rien ne semble se passer, ces deux-là répondent le plus vite. GET /account/usage met chaque compteur journalier à côté de son plafond — un compteur au maximum est la raison habituelle d'une campagne devenue muette. GET /queue montre ce qui a échoué. 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'application.
Ce que l'API ne couvre pas
Aucun endpoint pour les conversations et les messages : l'API peut vous dire que quelqu'un a répondu, pas ce qu'il a écrit, et elle ne peut pas envoyer un message ponctuel à une personne. Les notes, l'adéquation ICP comme filtre et le fil d'activité ne sont pas exposés non plus.
Pour réagir aux contacts nouveaux ou modifiés sans interroger l'API en boucle, utilisez les webhooks (voir Configurer des webhooks). Pour confier toute cette surface à un assistant IA au lieu d'écrire les appels, voir Brancher un assistant IA avec le serveur MCP.
