DEV Community

Cover image for Comment Utiliser l'API LinkedIn: Guide Complet d'Intégration du Réseau Professionnel (2026)
Antoine Laurent
Antoine Laurent

Posted on • Originally published at apidog.com

Comment Utiliser l'API LinkedIn: Guide Complet d'Intégration du Réseau Professionnel (2026)

En bref

L'API LinkedIn permet aux développeurs d'intégrer leur application au réseau professionnel de LinkedIn de manière programmatique. Elle utilise l'authentification OAuth 2.0, des points de terminaison RESTful et GraphQL pour les profils, les publications, les commentaires, les pages d'entreprise et les publicités, avec des limitations de débit de 100 à 500 requêtes par jour et par application. Ce guide couvre la configuration de l'authentification, l'accès au profil, la publication de contenu, la gestion des pages d'entreprise, l'API publicitaire et les stratégies d'intégration en production.

Essayez Apidog dès aujourd'hui

Introduction

LinkedIn compte plus de 900 millions d'utilisateurs professionnels dans plus de 200 pays. Pour les développeurs qui créent des outils de recrutement, des plateformes marketing ou des applications B2B, l'intégration de l'API LinkedIn est essentielle pour atteindre ce public professionnel.

Voici la réalité : les spécialistes du marketing B2B gérant manuellement leur présence sur LinkedIn perdent 15 à 20 heures par semaine à publier, suivre l'engagement et générer des prospects. Une solide intégration de l'API LinkedIn automatise la distribution de contenu, la capture de prospects, l'analyse de l'engagement et les flux de travail de recrutement.

Ce guide vous accompagne tout au long du processus complet d'intégration de l'API LinkedIn. Vous apprendrez l'authentification OAuth 2.0, l'accès au profil, la publication de contenu, la gestion des pages d'entreprise, l'intégration des publicités, les webhooks et les stratégies de déploiement en production. À la fin, vous disposerez d'une intégration LinkedIn prête pour la production.

💡 Astuce : Apidog simplifie les tests d'intégration d'API. Testez vos points de terminaison LinkedIn, validez les flux OAuth, inspectez les réponses API et déboguez les problèmes d'autorisation dans un seul espace de travail. Importez des spécifications API, simulez des réponses et partagez des scénarios de test avec votre équipe.

Qu'est-ce que l'API LinkedIn ?

LinkedIn fournit des API RESTful et GraphQL pour accéder aux données du réseau professionnel. L'API gère :

  • Les informations de profil utilisateur (avec consentement)
  • Les pages et mises à jour des entreprises
  • Les publications, commentaires et réactions
  • Les connexions (limité)
  • Les offres d'emploi et candidatures
  • La gestion des publicités LinkedIn
  • Les formulaires de génération de prospects
  • La messagerie (partenaires limités uniquement)

Fonctionnalités clés

Fonctionnalité Description
RESTful + GraphQL Plusieurs styles d'API
OAuth 2.0 Autorisation utilisateur requise
Rate Limiting 100-500 requêtes/jour par application
Company Pages Opérations CRUD complètes
Ads API Gestion des campagnes
Webhooks Notifications en temps réel
Media Upload Images et vidéos

Produits API

API Niveau d'accès Cas d'utilisation
Sign In with LinkedIn Ouvert Authentification utilisateur
Profile API Partenaire Lire le profil utilisateur
Company Admin API Partenaire Gérer les pages d'entreprise
Ads API Partenaire Gestion des campagnes publicitaires
Job Posting API Partenaire Publier et gérer des offres d'emploi
Marketing Developer Platform Partenaire Accès API complet

Versions de l'API

Version Statut Date de fin
v2 Actuelle Active
v1 Retirée Décembre 2023

Démarrage : Configuration de l'authentification

Étape 1 : Créer un compte développeur LinkedIn

  1. Visitez le Portail développeur LinkedIn
  2. Connectez-vous avec votre compte LinkedIn
  3. Cliquez sur Créer une application dans le tableau de bord Mes applications
  4. Remplissez les détails de l'application (nom, logo, description)

Étape 2 : Configurer les paramètres de l'application

Configurez l'authentification de l'application :

const LINKEDIN_CLIENT_ID = process.env.LINKEDIN_CLIENT_ID;
const LINKEDIN_CLIENT_SECRET = process.env.LINKEDIN_CLIENT_SECRET;
const LINKEDIN_REDIRECT_URI = process.env.LINKEDIN_REDIRECT_URI;

// Get these from your app dashboard
// https://www.linkedin.com/developers/apps/{appId}/auth
Enter fullscreen mode Exit fullscreen mode

Étape 3 : Demander les autorisations requises

LinkedIn exige l'approbation des autorisations :

Permission Description Approbation requise
r_liteprofile Profil de base (nom, photo) Approuvé automatiquement
r_emailaddress Adresse e-mail Approuvé automatiquement
w_member_social Publier au nom de l'utilisateur Vérification partenaire
r_basicprofile Profil complet Vérification partenaire
r_organization_social Accès aux pages d'entreprise Vérification partenaire
w_organization_social Publier sur une page d'entreprise Vérification partenaire
rw_ads Gestion des publicités Vérification partenaire
r_ads_reporting Analyse des publicités Vérification partenaire

Étape 4 : Construire l'URL d'autorisation

Implémentez le flux OAuth 2.0 :

const getAuthUrl = (state, scopes = ['r_liteprofile', 'r_emailaddress']) => {
  const params = new URLSearchParams({
    response_type: 'code',
    client_id: LINKEDIN_CLIENT_ID,
    redirect_uri: LINKEDIN_REDIRECT_URI,
    scope: scopes.join(' '),
    state: state
  });

  return `https://www.linkedin.com/oauth/v2/authorization?${params.toString()}`;
};

// Usage
const state = require('crypto').randomBytes(16).toString('hex');
const authUrl = getAuthUrl(state, ['r_liteprofile', 'r_emailaddress', 'w_member_social']);
console.log(`Redirect user to: ${authUrl}`);
Enter fullscreen mode Exit fullscreen mode

Étape 5 : Échanger le code contre un jeton d'accès

Gérez le rappel OAuth :

const exchangeCodeForToken = async (code) => {
  const response = await fetch('https://www.linkedin.com/oauth/v2/accessToken', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: new URLSearchParams({
      grant_type: 'authorization_code',
      code: code,
      client_id: LINKEDIN_CLIENT_ID,
      client_secret: LINKEDIN_CLIENT_SECRET,
      redirect_uri: LINKEDIN_REDIRECT_URI
    })
  });

  const data = await response.json();

  return {
    accessToken: data.access_token,
    expiresIn: data.expires_in // 60 days
  };
};

// Handle callback
app.get('/oauth/callback', async (req, res) => {
  const { code, state } = req.query;

  try {
    const tokens = await exchangeCodeForToken(code);

    // Store tokens securely
    await db.users.update(req.session.userId, {
      linkedin_access_token: tokens.accessToken,
      linkedin_token_expires: Date.now() + (tokens.expiresIn * 1000)
    });

    res.redirect('/success');
  } catch (error) {
    console.error('OAuth error:', error);
    res.status(500).send('Authentication failed');
  }
});
Enter fullscreen mode Exit fullscreen mode

Étape 6 : Actualiser le jeton d'accès

Les jetons d'accès expirent après 60 jours :

const refreshAccessToken = async (refreshToken) => {
  // Note: LinkedIn doesn't provide refresh tokens
  // Users must re-authenticate after 60 days
  // Implement expiry notification
};

// Check token expiry before API calls
const ensureValidToken = async (userId) => {
  const user = await db.users.findById(userId);

  if (user.linkedin_token_expires < Date.now() + 86400000) { // 24 hours
    // Notify user to re-authenticate
    await notifyUserToReauth(user.id);
    throw new Error('Token expired, please re-authenticate');
  }

  return user.linkedin_access_token;
};
Enter fullscreen mode Exit fullscreen mode

Étape 7 : Effectuer des appels API authentifiés

Créez un client API réutilisable :

const LINKEDIN_BASE_URL = 'https://api.linkedin.com/v2';

const linkedinRequest = async (endpoint, options = {}) => {
  const accessToken = await ensureValidToken(options.userId);

  const response = await fetch(`${LINKEDIN_BASE_URL}${endpoint}`, {
    ...options,
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
      'X-Restli-Protocol-Version': '2.0.0',
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`LinkedIn API Error: ${error.message}`);
  }

  return response.json();
};

// Usage
const profile = await linkedinRequest('/me');
console.log(`Hello, ${profile.localizedFirstName} ${profile.localizedLastName}`);
Enter fullscreen mode Exit fullscreen mode

Accès au profil

Obtenir le profil utilisateur

Récupérez le profil de l'utilisateur authentifié :

const getUserProfile = async () => {
  const response = await linkedinRequest('/me?projection=(id,firstName,lastName,profilePicture(displayImage~:playableStreams))');
  return response;
};

// Usage
const profile = await getUserProfile();

console.log(`Name: ${profile.localizedFirstName} ${profile.localizedLastName}`);
console.log(`ID: ${profile.id}`);
console.log(`Photo: ${profile.profilePicture?.['displayImage~']?.elements?.[0]?.identifiers?.[0]?.identifier}`);
Enter fullscreen mode Exit fullscreen mode

Obtenir l'adresse e-mail

Récupérez l'e-mail de l'utilisateur :

const getUserEmail = async () => {
  const response = await linkedinRequest('/emailAddress?q=members&projection=(emailAddress*)');
  return response;
};

// Usage
const email = await getUserEmail();
console.log(`Email: ${email.elements?.[0]?.emailAddress}`);
Enter fullscreen mode Exit fullscreen mode

Champs de profil disponibles

Champ Permission Description
id r_liteprofile ID du membre LinkedIn
firstName r_liteprofile Prénom
lastName r_liteprofile Nom de famille
profilePicture r_liteprofile URL de la photo de profil
headline r_basicprofile Titre professionnel
summary r_basicprofile Section À propos
positions r_basicprofile Historique professionnel
educations r_basicprofile Historique des études
emailAddress r_emailaddress E-mail principal

Publication de contenu

Créer une publication

Publiez un contenu texte sur le fil d'actualité de l'utilisateur :

const createPost = async (authorUrn, postContent) => {
  const response = await linkedinRequest('/ugcPosts', {
    method: 'POST',
    body: JSON.stringify({
      author: authorUrn,
      lifecycleState: 'PUBLISHED',
      specificContent: {
        'com.linkedin.ugc.ShareContent': {
          shareCommentary: {
            text: postContent.text
          },
          shareMediaCategory: 'NONE'
        }
      },
      visibility: {
        'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
      }
    })
  });

  return response;
};

// Usage
const post = await createPost('urn:li:person:ABC123', {
  text: 'Excited to announce our new product launch! 🚀 #innovation #startup'
});

console.log(`Post created: ${post.id}`);
Enter fullscreen mode Exit fullscreen mode

Créer une publication avec une image

Publiez un contenu avec une image :

const createPostWithImage = async (authorUrn, postData) => {
  // Step 1: Register media upload
  const uploadRegistration = await linkedinRequest('/assets?action=registerUpload', {
    method: 'POST',
    body: JSON.stringify({
      registerUploadRequest: {
        recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
        owner: authorUrn,
        serviceRelationships: [
          {
            relationshipType: 'OWNER',
            identifier: 'urn:li:userGeneratedContent'
          }
        ]
      }
    })
  });

  const uploadUrl = uploadRegistration.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl;
  const assetUrn = uploadRegistration.value.asset;

  // Step 2: Upload image to provided URL
  await fetch(uploadUrl, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + await getAccessToken(),
      'Content-Type': 'application/octet-stream'
    },
    body: postData.imageBuffer
  });

  // Step 3: Create post with uploaded image
  const post = await linkedinRequest('/ugcPosts', {
    method: 'POST',
    body: JSON.stringify({
      author: authorUrn,
      lifecycleState: 'PUBLISHED',
      specificContent: {
        'com.linkedin.ugc.ShareContent': {
          shareCommentary: {
            text: postData.text
          },
          shareMediaCategory: 'IMAGE',
          media: [
            {
              status: 'READY',
              description: {
                text: postData.imageDescription || ''
              },
              media: assetUrn,
              title: {
                text: postData.title || ''
              }
            }
          ]
        }
      },
      visibility: {
        'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
      }
    })
  });

  return post;
};
Enter fullscreen mode Exit fullscreen mode

Créer une publication avec une vidéo

Publiez un contenu vidéo :

const createPostWithVideo = async (authorUrn, postData) => {
  // Register video upload
  const uploadRegistration = await linkedinRequest('/assets?action=registerUpload', {
    method: 'POST',
    body: JSON.stringify({
      registerUploadRequest: {
        recipes: ['urn:li:digitalmediaRecipe:feedshare-video'],
        owner: authorUrn,
        serviceRelationships: [
          {
            relationshipType: 'OWNER',
            identifier: 'urn:li:userGeneratedContent'
          }
        ]
      }
    })
  });

  const assetUrn = uploadRegistration.value.asset;

  // Upload video (use presigned upload URLs from response)
  // ... upload logic ...

  // Create post
  const post = await linkedinRequest('/ugcPosts', {
    method: 'POST',
    body: JSON.stringify({
      author: authorUrn,
      lifecycleState: 'PUBLISHED',
      specificContent: {
        'com.linkedin.ugc.ShareContent': {
          shareCommentary: { text: postData.text },
          shareMediaCategory: 'VIDEO',
          media: [{ status: 'READY', media: assetUrn }]
        }
      },
      visibility: { 'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC' }
    })
  });

  return post;
};
Enter fullscreen mode Exit fullscreen mode

Spécifications des médias

Type de média Format Taille maximale Durée
Image JPG, PNG, GIF 8 Mo N/A
Vidéo MP4, MOV 5 Go 15 min max
Document PDF, PPT, DOC 100 Mo N/A

Gestion des pages d'entreprise

Obtenir des informations sur l'entreprise

Récupérez les détails de la page d'entreprise :

const getCompanyInfo = async (companyId) => {
  const response = await linkedinRequest(
    `/organizations/${companyId}?projection=(id,localizedName,vanityName,tagline,description,universalName,logoV2(original~:playableStreams),companyType,companyPageUrl,confirmedLocations,industries,followerCount,staffCountRange,website, specialties)`
  );
  return response;
};

// Usage
const company = await getCompanyInfo('1234567');
console.log(`Company: ${company.localizedName}`);
console.log(`Followers: ${company.followerCount}`);
console.log(`Website: ${company.website}`);
Enter fullscreen mode Exit fullscreen mode

Publier sur une page d'entreprise

Partagez une mise à jour sur une page d'entreprise :

const createCompanyPost = async (organizationUrn, postContent) => {
  const response = await linkedinRequest('/ugcPosts', {
    method: 'POST',
    body: JSON.stringify({
      author: organizationUrn,
      lifecycleState: 'PUBLISHED',
      specificContent: {
        'com.linkedin.ugc.ShareContent': {
          shareCommentary: {
            text: postContent.text
          },
          shareMediaCategory: postContent.media ? 'IMAGE' : 'NONE',
          media: postContent.media ? [
            {
              status: 'READY',
              media: postContent.media.assetUrn
            }
          ] : []
        }
      },
      visibility: {
        'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
      }
    })
  });

  return response;
};

// Usage
const post = await createCompanyPost('urn:li:organization:1234567', {
  text: "We're hiring! Join our growing team. #careers #hiring"
});
Enter fullscreen mode Exit fullscreen mode

Obtenir les abonnés de l'entreprise

Récupérez le nombre d'abonnés :

const getFollowerCount = async (organizationId) => {
  const response = await linkedinRequest(
    `/organizationalEntityFollowerStatistics?q=organizationalEntity&organizationalEntity=urn:li:organization:${organizationId}`
  );
  return response;
};
Enter fullscreen mode Exit fullscreen mode

Limitation de débit

Comprendre les limitations de débit

LinkedIn applique des limitations de débit par application :

API Limite Fenêtre
Profile API 100 requêtes Par jour
UGC Posts 50 publications Par jour
Company Admin 500 requêtes Par jour
Ads API 100 requêtes Par minute

En-têtes de limitation de débit

En-tête Description
X-Restli-Quota-Remaining Requêtes restantes
X-Restli-Quota-Reset Secondes avant réinitialisation

Dépannage des problèmes courants

Problème : 401 Non autorisé

Solutions :

  1. Vérifiez que le jeton d'accès n'a pas expiré (60 jours)
  2. Vérifiez que la portée du jeton inclut la ressource demandée
  3. Assurez-vous que l'en-tête Authorization: Bearer {token} est présent

Problème : 403 Interdit

Solutions :

  1. Vérifiez que l'application dispose des autorisations requises
  2. Vérifiez que l'utilisateur a approuvé les portées demandées
  3. Une vérification partenaire peut être requise

Problème : 429 Limitation de débit

Solutions :

  1. Mettre en œuvre une file d'attente de requêtes
  2. Mettre en cache les réponses pour réduire les appels
  3. Utiliser des webhooks au lieu de l'interrogation

Liste de contrôle du déploiement en production

Avant la mise en ligne :

  • [ ] Effectuer la vérification partenaire LinkedIn
  • [ ] Implémenter OAuth 2.0 avec un stockage sécurisé des jetons
  • [ ] Ajouter des notifications d'expiration de jeton (60 jours)
  • [ ] Configurer la limitation de débit et la mise en file d'attente
  • [ ] Configurer les points de terminaison des webhooks
  • [ ] Implémenter une gestion complète des erreurs
  • [ ] Ajouter la journalisation pour tous les appels API
  • [ ] Créer un examen de conformité aux directives de marque

Cas d'utilisation concrets

Plateforme de recrutement

Un outil de recrutement automatise la publication d'offres d'emploi :

  • Défi : Publication manuelle sur plusieurs canaux
  • Solution : Intégration de l'API LinkedIn Jobs
  • Résultat : 80% de gain de temps, 3x plus de candidatures

Automatisation du marketing B2B

Une plateforme marketing planifie du contenu LinkedIn :

  • Défi : Calendrier de publication incohérent
  • Solution : Publication automatisée via l'API UGC
  • Résultat : 5x plus d'engagement, présence de marque cohérente

Conclusion

L'API LinkedIn offre un accès complet aux fonctionnalités du réseau professionnel. Principaux points à retenir :

  • Authentification OAuth 2.0 avec des jetons valides 60 jours
  • API de profil, de publication et de page d'entreprise disponibles
  • Les limitations de débit nécessitent une gestion attentive (100-500/jour)
  • La vérification partenaire est requise pour la plupart des API
  • Apidog simplifie les tests d'API et la collaboration d'équipe

Section FAQ

Comment puis-je accéder à l'API LinkedIn ?

Créez un compte développeur LinkedIn, créez une application et effectuez la vérification partenaire pour un accès avancé à l'API.

Puis-je publier automatiquement sur LinkedIn ?

Oui, utilisez l'API UGC (User Generated Content) avec la permission w_member_social pour les publications personnelles ou w_organization_social pour les publications d'entreprise.

Quelles sont les limitations de débit de LinkedIn ?

Les limitations de débit varient de 100 à 500 requêtes par jour selon l'API. L'API Ads autorise 100 requêtes par minute.

Combien de temps les jetons LinkedIn sont-ils valides ?

Les jetons d'accès expirent après 60 jours. Les utilisateurs doivent se réauthentifier pour continuer à accéder à l'API.

Puis-je accéder aux connexions utilisateur ?

Non, LinkedIn a supprimé l'accès à l'API des connexions pour la plupart des applications en raison de modifications liées à la confidentialité.

Top comments (0)