LinkedFlow Docs Ouvrir l’app

API et intégrations

LinkedFlow dialogue avec le reste de vos outils par trois chemins : une API REST avec jeton, un webhook qui déclenche des workflows depuis l'extérieur, et des nœuds qui appellent vos propres services depuis l'intérieur d'un parcours. Cette page est le contrat exact, avec des exemples prêts pour n8n, Make ou un simple curl.

L'API utilisée par l'application est l'API publique : mêmes endpoints, même authentification. Pour une intégration, n'utilisez pas le jeton du navigateur : créez un jeton d'API dans Paramètres → Jetons d'API, avec l'expiration de votre choix et rattaché à cet espace.

Les trois chemins

CheminQui appelle quiÀ quoi ça sert
API RESTVotre outil → LinkedFlowCréer des prospects et des listes, lancer des workflows, lire les exécutions, résoudre des approbations, récupérer le tunnel.
Webhook entrantVotre outil → un workflow précisDémarrer un parcours pour un prospect qui existe déjà dans le CRM, le jeton du workflow servant d'identifiant.
Nœuds sortantsLinkedFlow → votre outilPrévenir votre CRM ou n8n en plein parcours (Webhook sortant) ou lui demander une valeur et continuer avec la réponse (Requête HTTP).

Authentification

Toute l'API vit sous https://app.linkedflow.pro/api/v1 et s'authentifie par un jeton dans l'en-tête Authorization. Il y a deux façons d'en obtenir un, et seule la première est faite pour les intégrations.

Jeton d'API (celui qu'il vous faut pour n8n)

Dans l'application : Paramètres → Jetons d'API → Nouveau jeton. Donnez-lui un nom (« n8n · signaux quotidiens »), choisissez l'expiration — 30 jours, 90 jours, 1 an ou sans expiration — et copiez-le : il ne s'affiche qu'une fois.

PropriétéCe que ça veut dire
Rattaché à un espaceCelui où il a été créé, sans possibilité d'en changer : même si vous changez d'espace dans l'application ou que quelqu'un envoie l'en-tête X-Workspace, ce jeton continue d'écrire là où il a été configuré.
Hérite de votre rôleIl n'ajoute aucun droit. Passez de MANAGER à VIEWER et ses appels en écriture renvoient 403.
Survit à votre mot de passeChanger de mot de passe ferme les autres sessions du navigateur mais ne révoque pas les jetons d'API : une rotation ne casse jamais vos intégrations.
Révocable à l'instantDepuis le même écran. Il cesse de fonctionner à l'appel suivant, et cet écran indique aussi sa dernière utilisation.

Conseil : créez un utilisateur dédié à la machine (« automatisation@votreentreprise.com ») avec le rôle minimal nécessaire et générez le jeton depuis ce compte. L'activité de l'espace distingue alors ce qu'a fait un humain de ce qu'a fait n8n, et vous pouvez lui couper l'accès sans toucher au vôtre.

Jeton de session (pour un script jetable)

Le login de l'application renvoie aussi un jeton, mais il expire au bout de 30 jours et suit l'espace actif de votre utilisateur. Parfait pour un curl de test ; pas pour une automatisation censée durer des mois :

curl -X POST https://app.linkedflow.pro/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"email":"vous@email.com","password":"votre-mot-de-passe"}'
{
  "user": { "id": "…", "name": "Valen", "current_workspace": { "id": "…", "role": "OWNER" } },
  "token": "198|eMdBPK8g…"
}

Ensuite, chaque appel porte deux en-têtes :

Authorization: Bearer 198|eMdBPK8g…
Accept: application/json

Le jeton est votre mot de passe. Stockez-le comme identifiant dans n8n (Header Auth : nom Authorization, valeur Bearer <jeton>), jamais dans une URL ni dans le corps d'un nœud. Si un jeton d'API fuite, révoquez-le dans Paramètres → Jetons d'API : c'est immédiat et sans effet sur les autres.

Espace de travail et rôles

Inutile d'envoyer l'espace de travail : le jeton agit toujours sur l'espace courant de l'utilisateur. Si vous appartenez à plusieurs, POST /auth/switch-workspace/{workspace} en change. Chaque endpoint exige le même rôle que l'écran équivalent dans l'application (VIEWER < MEMBER < MANAGER < ADMIN < OWNER) ; sinon, c'est un 403. Les rôles sont détaillés dans Paramètres.

Conseil : créez un utilisateur dédié à la machine (« automatisation@votreentreprise.com ») avec le rôle minimum nécessaire. Vous pourrez lui couper l'accès sans toucher au vôtre, et l'activité de l'espace distinguera ce qu'a fait un humain de ce qu'a fait n8n.

Conventions

  • Sans Accept: application/json, pas de JSON : l'application répondrait par une redirection ou du HTML. C'est l'erreur numéro un des débuts.
  • Erreurs : 401 jeton absent ou expiré, 403 rôle insuffisant ou abonnement inactif, 404 hors de votre espace, 422 validation ({"message":"…","errors":{"champ":["…"]}}), 429 trop d'appels.
  • Collections : les prospects arrivent paginés (data, current_page, last_page, total) ; d'autres ressources renvoient la collection brute ou l'enveloppent dans items. Regardez toujours la première réponse avant de mapper les champs.
  • Langue : les messages d'erreur sortent dans la langue de votre utilisateur. On peut la forcer avec Accept-Language: fr.
  • Rythme : pas de limite globale, mais les endpoints coûteux ont la leur (le webhook de workflow, 30 appels par minute ; le compositeur IA, 20).

Endpoints principaux

La liste complète est celle de l'application ; voici ce qui sert vraiment depuis l'extérieur.

Prospects et listes

EndpointRôleCe qu'il fait
GET /prospectsVIEWERListe paginée. Filtres : search, status, list_id, tag.
POST /prospectsMEMBERCrée un prospect. Accepte list_id pour le déposer dans une liste au passage.
GET /prospects/{id}VIEWERFiche complète.
PUT /prospects/{id}MEMBERModifie des champs (pas le statut : c'est le moteur qui le fait avancer).
POST /prospects/bulk-tagsMEMBERÉtiquette en masse.
GET /prospects/{id}/conversationVIEWERLe fil réel de LinkedIn.
POST /prospects/{id}/conversation/messagesMANAGEREnvoie un vrai message (quotas et horaires s'appliquent).
GET · POST /listsVIEWER · MEMBERLister et créer des listes.
POST /lists/{id}/prospectsMEMBERAjoute des prospects existants à une liste.
POST /suppressionMANAGEREnvoie quelqu'un dans la liste de suppression.

Workflows et exécutions

EndpointRôleCe qu'il fait
GET /workflowsVIEWERListe avec statut, version courante et dernière exécution.
POST /workflows/{id}/runMANAGERLance sur list_id ou prospect_ids[]. Accepte account_id et allow_repeat.
POST /workflows/{id}/activate · /pauseMANAGERAllume ou éteint les déclencheurs.
POST /workflows/{id}/validate · /dry-runMEMBERValide et simule sans toucher LinkedIn.
GET /executions · /executions/{id}VIEWERExécutions et leur détail avec KPI par nœud.
GET /prospect-executions/{id}VIEWERLe parcours d'une personne, nœud par nœud.
POST /executions/{id}/cancelMANAGERArrête ce qui reste en attente.
GET /approvals · POST /approvals/{id}/approveVIEWER · MANAGERLa boîte d'approbations depuis l'extérieur — depuis Slack, par exemple.
GET /dashboard/funnel · /stats · /activityVIEWERLes chiffres du tableau de bord, pour vos propres rapports.
GET /errors/unmanaged · /pausedVIEWERCe qui attend une décision humaine. Parfait pour une alerte quotidienne.

La recette qui règle 80 % des cas : créer et déclencher

Un nouveau prospect entre dans le CRM et, si vous le déposez dans une liste, le workflow qui écoute cette liste démarre tout seul. Deux appels, voire un seul :

curl -X POST https://app.linkedflow.pro/api/v1/prospects \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -H "Accept: application/json" \
  -d '{
    "linkedin_url": "https://www.linkedin.com/in/quelquun",
    "first_name": "Ana",
    "company": "Conseil Nord",
    "tags": ["n8n", "signal:recrute"],
    "source": "n8n",
    "list_id": "01a05d4e-23b2-725c-9aa4-e1ed9e8fd6da"
  }'

D'où vient le list_id ? De l'application : Prospects → cliquez sur la liste pour la sélectionner → bouton Copier l'ID. Par l'API, GET /lists renvoie l'id de chacune. C'est un UUID (01a05d4e-23b2-725c-…) ; envoyez autre chose et vous obtenez un 422 indiquant que list_id n'est pas valide.

Trois choses à savoir sur cet appel :

  • linkedin_url ou public_identifier suffit. Si l'URL n'est pas un profil, c'est un 422.
  • Un doublon répond 409 et ce n'est pas un échec : il renvoie le prospect qui existait déjà et l'ajoute quand même à la liste. Dans n8n, configurez le nœud pour ne pas s'arrêter sur 409 — c'est le chemin normal quand vous retraitez une source.
  • L'entrée dans la liste déclenche le trigger « Ajouté à une liste » de tout workflow actif qui l'écoute, que le prospect soit tout neuf ou qu'il existait déjà sans être dedans. C'est l'accroche : n8n n'a rien à savoir des workflows, il lui suffit de remplir une liste.

Un list_id bien formé mais inexistant (ou appartenant à un autre espace) ne renvoie pas d'erreur : le prospect est créé et n'entre dans aucune liste. C'est de l'isolation entre locataires — la réponse ne doit pas révéler les listes des autres — alors vérifiez le champ lists de la réponse si vous voulez être sûr.

Si vous préférez déclencher explicitement, utilisez POST /workflows/{id}/run avec {"list_id":"…"} ou {"prospect_ids":["…"]}. Il faut le rôle MANAGER et une version enregistrée du workflow.

Webhook entrant : déclencher un workflow depuis l'extérieur

Un workflow qui commence par le nœud Webhook expose une URL avec son propre jeton (visible dans le builder, rôle MANAGER ou plus) :

POST https://app.linkedflow.pro/api/v1/webhooks/workflows/{token}
Content-Type: application/json

{ "linkedin_url": "https://www.linkedin.com/in/quelquun" }

Identifiants valides, au moins un : public_identifier, linkedin_url ou email. Tout ce que vous envoyez en plus reste disponible dans le parcours sous {{trigger.*}} : vous pouvez donc transmettre le motif du signal et l'utiliser dans le texte du message.

RéponseSignification
202 {"status":"accepted"}Reçu. C'est toujours celle-ci, que le prospect existe ou non et que le parcours démarre ou non.
404Jeton inconnu, workflow inactif, ou premier nœud qui n'est pas un Webhook.
422Aucun identifiant envoyé.

Cet endpoint ne crée pas de prospects. Il résout quelqu'un qui est déjà dans votre CRM ; s'il ne trouve personne, il répond quand même 202 et rien ne se passe. C'est délibéré : la réponse ne doit pas permettre de deviner qui figure ou non dans votre base. Si votre intégration amène de nouvelles personnes, créez-les d'abord avec POST /prospects.

Un 202 ne garantit pas non plus le démarrage : un prospect supprimé, marqué « ne pas contacter » ou qui a déjà répondu reste dehors, à cause des protections habituelles. Ce qui s'est réellement passé se voit dans Exécutions.

Sorties : quand LinkedFlow appelle votre outil

Webhook sortant

Le nœud Webhook sortant fait un POST vers l'URL que vous indiquez. Sans corps personnalisé, il envoie ceci :

{
  "prospect": {
    "id": "01a0…",
    "full_name": "Ana García",
    "linkedin_url": "https://www.linkedin.com/in/…",
    "company": "Conseil Nord",
    "status": "REPLIED"
  },
  "execution_id": "01a0…",
  "node_id": "webhook_1"
}

Le POST n'est pas signé, et le nœud n'a que deux champs : méthode et URL. Ni en-têtes ni corps personnalisable — vous ne pouvez donc pas envoyer de signature ni de secret dans un en-tête. Tout ce qui doit voyager avec passe par l'URL, qui accepte les variables :

https://votre-n8n/webhook/reponses?s=UN-SECRET-LONG&cat={{previous.classification}}

Dans n8n cela arrive comme {{ $json.query.s }} et {{ $json.query.cat }} — pas dans headers ni dans body. Vérifiez le secret avec un nœud Si juste après le webhook et jetez ce qui ne l'a pas : sans ce contrôle, quiconque trouve l'URL peut vous injecter de fausses données.

Détails opérationnels : 15 secondes de délai maximum ; un 5xx est considéré comme passager et retenté jusqu'à trois fois avec attente croissante ; un 4xx est marqué comme erreur de configuration et attend votre décision dans la boîte d'erreurs. Répondez vite et en 200 : si votre automatisation est lente, acceptez d'abord et traitez ensuite.

Requête HTTP : demander une valeur et continuer

Le nœud Requête HTTP est identique, mais pensé pour exploiter la réponse. Ce que vous renvoyez est disponible dans le nœud suivant :

{{previous.status}}              → 200
{{previous.response.tier}}       → "A"   (votre JSON, sous "response")
{{previous.response.angle}}      → "recrute des commerciaux"

Avec ça, un nœud Si bifurque sur votre propre scoring : {{previous.response.tier}} == "A". Renvoyez toujours un JSON plat et répondez en moins de 15 secondes ; si votre service peut être lent, renvoyez une valeur par défaut plutôt que de faire attendre le parcours.

Cinq flux n8n qui fonctionnent

1 · Signal externe → prise de contact (capter)

Schedule à 7 h 30 → HTTP Request vers votre source de signaux (publications, changements de poste, offres d'emploi) → Code qui normalise en linkedin_url → Remove Duplicates → HTTP Request vers POST /prospects avec le list_id de « Signaux du jour » et le signal dans tags.

Dans LinkedFlow : un workflow actif déclenché par Ajouté à une liste → Lire le profil → Score IA → Si {{previous.score}} >= 70 → Réagir à sa dernière publication → Attendre 1 jour → Envoyer l'invitation avec note. Configurez le nœud n8n pour traiter le 409 comme un succès.

2 · Réponse classée → CRM et agenda (traiter)

Dans LinkedFlow : déclencheur Message reçu → nœud Classer la réponse → toutes les sorties vers le même Webhook sortant, avec la catégorie dans l'URL : ?cat={{previous.classification}}.

Dans n8n : Webhook → un Si comparant {{ $json.query.s }} à votre secret → Switch sur {{ $json.query.cat }} : INTERESTED crée l'affaire dans votre CRM, prévient Slack et envoie le lien de prise de rendez-vous ; QUESTION rédige un brouillon avec l'IA et le dépose dans Slack pour approbation ; NOT_NOW écrit la date de relance dans une feuille et un cron la réinjecte à 90 jours ; DO_NOT_CONTACT appelle POST /suppression et referme.

3 · « Commentez GUIDE et je vous l'envoie »

Dans LinkedFlow : déclencheur Commentaire sur une publication avec mot-clé → Réagir au commentaire → Répondre au commentaire → Envoyer le message avec le lien → Webhook sortant.

Dans n8n : inscription dans votre outil d'emailing, ligne dans une feuille avec commenté → livré → ouvert, et au bout de trois jours, s'il n'y a pas eu de réponse, un POST vers le webhook entrant d'un workflow de relance. Rappel : les commentaires sont sondés toutes les 5 minutes et répondre à un commentaire ne consomme pas le quota de messages.

4 · Enrichissement et scoring maison en plein parcours

Ici, c'est LinkedFlow qui appelle n8n. Dans le parcours : Lire le profil → Requête HTTP vers votre webhook n8n (réponse par le dernier nœud) → Si {{previous.response.tier}} == "A" → invitation avec note sur mesure ; sinon, direction une liste de nurturing.

Dans n8n : Webhook → scraping du site de l'entreprise → un modèle d'IA qui renvoie un JSON strict (tier, angle, douleur) → Respond to Webhook. Prévoyez un repli (tier: "B") pour qu'une panne chez vous ne bloque jamais le parcours.

5 · Le rapport du lundi (surveiller)

Schedule lundi 7 h → GET /dashboard/funnel et GET /executions → GET /errors/unmanaged → un modèle d'IA avec la consigne « trois décisions, pas trois graphiques » → email. Aucun nouveau tableau de bord : les chiffres viennent de l'API qui dessine déjà celui de l'application.

Téléchargez-les tout faits

Quatre workflows n8n prêts à importer depuis un fichier. Avant de les activer : créez un identifiant Header Auth nommé Authorization avec la valeur Bearer <votre-jeton>, et remplacez l'id de liste d'exemple par le vôtre.

Bonnes pratiques

  • Dédupliquez avant d'appeler, par linkedin_url et par jour. Deux POST identiques ne dupliquent pas le prospect, mais peuvent le faire passer deux fois dans le flux si vous le retirez de la liste puis l'y remettez.
  • Ne luttez pas contre les quotas. Peu importe la vitesse d'envoi : les actions sortent au rythme du compte (25 visites, 20 invitations et 30 messages par jour par défaut). Empiler 500 prospects n'accélère rien, ça remplit la file.
  • Consignez l'execution_id reçu dans les webhooks sortants : c'est la clé pour retrouver ce parcours dans l'application.
  • Un utilisateur par intégration, avec le rôle minimal, et faites tourner son jeton quand il change de mains.

Il vous manque un endpoint ? Écrivez-nous depuis le chat d'assistance de l'application : ce qui est documenté et ouvert en priorité est décidé par les intégrations que les gens construisent réellement.