DEV Community

Cover image for LinkedIn API nutzen: Umfassende Anleitung zur professionellen Netzwerkintegration (2026)
Emre Demir
Emre Demir

Posted on • Originally published at apidog.com

LinkedIn API nutzen: Umfassende Anleitung zur professionellen Netzwerkintegration (2026)

TL;DR

Die LinkedIn API ermöglicht Entwicklern die programmatische Integration in das professionelle Netzwerk von LinkedIn. Sie unterstützt OAuth 2.0-Authentifizierung, RESTful- und GraphQL-Endpunkte für Profile, Beiträge, Kommentare, Unternehmensseiten und Anzeigen, mit Ratenbegrenzungen von 100-500 Anfragen pro Tag pro App. In diesem Leitfaden findest du konkrete Schritte zur Authentifizierung, zum Profilzugriff, zum Posten von Inhalten, zur Verwaltung von Unternehmensseiten, zur Ads API und zu produktionsreifen Integrationsstrategien.

Teste Apidog noch heute

Einleitung

LinkedIn zählt über 900 Millionen professionelle Nutzer in mehr als 200 Ländern. Für die Entwicklung von Recruiting-Tools, Marketingplattformen oder B2B-Anwendungen ist die LinkedIn API-Integration entscheidend, um die Zielgruppe effizient zu erreichen.

Manuelles Verwalten der LinkedIn-Präsenz kostet B2B-Marketer 15-20 Stunden pro Woche. Mit einer robusten LinkedIn API-Integration automatisierst du Inhaltsverteilung, Lead-Erfassung, Engagement-Analysen und Rekrutierungs-Workflows.

Dieser Leitfaden zeigt Schritt für Schritt, wie du OAuth 2.0-Authentifizierung, Profilzugriff, Content-Posting, Unternehmensseitenmanagement, Anzeigenintegration, Webhooks und Produktionsstrategien umsetzt. Ziel: eine produktionsreife LinkedIn-Integration.

💡 Apidog vereinfacht das Testen der API-Integration: Teste LinkedIn-Endpunkte, validiere OAuth-Flows, prüfe API-Antworten und debugge Berechtigungen in einer Umgebung. Importiere API-Spezifikationen, modelliere Antworten und teile Testszenarien mit deinem Team.

Was ist die LinkedIn API?

LinkedIn stellt RESTful- und GraphQL-APIs bereit, mit denen du auf Netzwerkdaten zugreifen kannst. Die API unterstützt:

  • Benutzerprofilinformationen (mit Zustimmung)
  • Unternehmensseiten und Updates
  • Beiträge, Kommentare und Reaktionen
  • Verbindungen (eingeschränkt)
  • Stellenanzeigen und Bewerbungen
  • LinkedIn Ads-Verwaltung
  • Lead-Generierungsformulare
  • Nachrichten (nur für ausgewählte Partner)

Hauptfunktionen

Funktion Beschreibung
RESTful + GraphQL Mehrere API-Stile
OAuth 2.0 Benutzerautorisierung erforderlich
Ratenbegrenzung 100-500 Anfragen/Tag pro App
Unternehmensseiten Vollständige CRUD-Operationen
Ads API Kampagnenverwaltung
Webhooks Echtzeit-Benachrichtigungen
Medien-Upload Bilder und Videos

API-Produkte

API Zugriffsebene Anwendungsfall
Anmelden mit LinkedIn Offen Benutzerauthentifizierung
Profil-API Partner Benutzerprofil lesen
Unternehmensadmin-API Partner Unternehmensseiten verwalten
Ads API Partner Anzeigenkampagnenverwaltung
Job Posting API Partner Stellenanzeigen veröffentlichen und verwalten
Marketing Developer Platform Partner Voller API-Zugriff

API-Versionen

Version Status Enddatum
v2 Aktuell Aktiv
v1 Veraltet Dezember 2023

Erste Schritte: Authentifizierungs-Setup

Schritt 1: LinkedIn-Entwicklerkonto erstellen

  1. Gehe zum LinkedIn Developer Portal
  2. Melde dich mit deinem LinkedIn-Konto an
  3. Klicke im My Apps-Dashboard auf App erstellen
  4. Fülle die App-Details (Name, Logo, Beschreibung) aus

Schritt 2: App-Einstellungen konfigurieren

Richte die App-Authentifizierung ein:

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;

// Diese Werte findest du im App-Dashboard
// https://www.linkedin.com/developers/apps/{appId}/auth
Enter fullscreen mode Exit fullscreen mode

Schritt 3: Erforderliche Berechtigungen anfordern

LinkedIn verlangt explizite Genehmigung für Berechtigungen:

Berechtigung Beschreibung Genehmigung erforderlich
r_liteprofile Basisches Profil (Name, Foto) Automatisch genehmigt
r_emailaddress E-Mail-Adresse Automatisch genehmigt
w_member_social Im Namen des Benutzers posten Partnerverifizierung
r_basicprofile Vollständiges Profil Partnerverifizierung
r_organization_social Zugriff auf Unternehmensseiten Partnerverifizierung
w_organization_social Auf Unternehmensseite posten Partnerverifizierung
rw_ads Anzeigenverwaltung Partnerverifizierung
r_ads_reporting Anzeigenanalysen Partnerverifizierung

Schritt 4: Autorisierungs-URL erstellen

Implementiere den OAuth 2.0-Flow:

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()}`;
};

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

Schritt 5: Code gegen Zugriffstoken tauschen

Verarbeite den OAuth-Callback:

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 Tage
  };
};

// Callback-Handler
app.get('/oauth/callback', async (req, res) => {
  const { code, state } = req.query;
  try {
    const tokens = await exchangeCodeForToken(code);
    // Token sicher speichern
    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-Fehler:', error);
    res.status(500).send('Authentifizierung fehlgeschlagen');
  }
});
Enter fullscreen mode Exit fullscreen mode

Schritt 6: Zugriffstoken aktualisieren

Tokens laufen nach 60 Tagen ab – implementiere eine Ablaufbenachrichtigung:

const refreshAccessToken = async (refreshToken) => {
  // LinkedIn gibt keine Refresh-Token aus
  // Nach 60 Tagen erneute Authentifizierung erforderlich
  // Ablaufbenachrichtigung implementieren
};

const ensureValidToken = async (userId) => {
  const user = await db.users.findById(userId);
  if (user.linkedin_token_expires < Date.now() + 86400000) { // 24h Vorwarnung
    await notifyUserToReauth(user.id);
    throw new Error('Token abgelaufen, bitte neu authentifizieren');
  }
  return user.linkedin_access_token;
};
Enter fullscreen mode Exit fullscreen mode

Schritt 7: Authentifizierte API-Aufrufe tätigen

Erstelle einen wiederverwendbaren API-Client:

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-Fehler: ${error.message}`);
  }
  return response.json();
};

// Beispiel: Profil abfragen
const profile = await linkedinRequest('/me');
console.log(`Hallo, ${profile.localizedFirstName} ${profile.localizedLastName}`);
Enter fullscreen mode Exit fullscreen mode

Profilzugriff

Benutzerprofil abrufen

Hole das Profil des authentifizierten Users:

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

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

E-Mail-Adresse abrufen

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

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

Verfügbare Profilfelder

Feld Berechtigung Beschreibung
id r_liteprofile LinkedIn-Mitglieds-ID
firstName r_liteprofile Vorname
lastName r_liteprofile Nachname
profilePicture r_liteprofile Profilfoto-URL
headline r_basicprofile Berufliche Überschrift
summary r_basicprofile Über-Mich-Bereich
positions r_basicprofile Berufserfahrung
educations r_basicprofile Ausbildungsgeschichte
emailAddress r_emailaddress Primäre E-Mail

Inhalte posten

Einen Beitrag erstellen

Textbeitrag posten:

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;
};

// Beispiel
const post = await createPost('urn:li:person:ABC123', {
  text: 'Excited to announce our new product launch! 🚀 #innovation #startup'
});
console.log(`Beitrag erstellt: ${post.id}`);
Enter fullscreen mode Exit fullscreen mode

Einen Beitrag mit Bild erstellen

Bild posten:

const createPostWithImage = async (authorUrn, postData) => {
  // 1. Upload registrieren
  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;

  // 2. Bild hochladen
  await fetch(uploadUrl, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + await getAccessToken(),
      'Content-Type': 'application/octet-stream'
    },
    body: postData.imageBuffer
  });

  // 3. Beitrag erstellen
  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

Einen Beitrag mit Video erstellen

Video posten:

const createPostWithVideo = async (authorUrn, postData) => {
  // Video-Upload registrieren
  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;

  // Video hochladen (Upload-Logik)
  // ...

  // Beitrag erstellen
  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

Medienspezifikationen

Medientyp Format Max. Größe Dauer
Bild JPG, PNG, GIF 8 MB N/A
Video MP4, MOV 5 GB max. 15 Min.
Dokument PDF, PPT, DOC 100 MB N/A

Unternehmensseitenverwaltung

Unternehmensinformationen abrufen

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;
};

// Beispiel
const company = await getCompanyInfo('1234567');
console.log(`Unternehmen: ${company.localizedName}`);
console.log(`Follower: ${company.followerCount}`);
console.log(`Webseite: ${company.website}`);
Enter fullscreen mode Exit fullscreen mode

Auf Unternehmensseite posten

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;
};

// Beispiel
const post = await createCompanyPost('urn:li:organization:1234567', {
  text: 'Wir stellen ein! Werden Sie Teil unseres wachsenden Teams. #karriere #einstellung'
});
Enter fullscreen mode Exit fullscreen mode

Follower des Unternehmens abrufen

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

Ratenbegrenzung

Ratenbegrenzungen verstehen

API Limit Fenster
Profil-API 100 Anfragen Pro Tag
UGC-Beiträge 50 Beiträge Pro Tag
Unternehmensadmin 500 Anfragen Pro Tag
Ads API 100 Anfragen Pro Minute

Ratenbegrenzungs-Header

Header Beschreibung
X-Restli-Quota-Remaining Verbleibende Anfragen
X-Restli-Quota-Reset Sekunden bis zum Zurücksetzen

Fehlerbehebung bei häufigen Problemen

Problem: 401 Nicht autorisiert

Lösungen:

  1. Zugriffstoken prüfen (Gültigkeit: 60 Tage)
  2. Scopes des Tokens validieren
  3. Header Authorization: Bearer {token} setzen

Problem: 403 Verboten

Lösungen:

  1. App-Berechtigungen prüfen
  2. Benutzerfreigabe der Scopes sicherstellen
  3. Partnerverifizierung ggf. abschließen

Problem: 429 Ratenbegrenzung erreicht

Lösungen:

  1. Anfragewarteschlange implementieren
  2. Antworten cachen und so API-Aufrufe reduzieren
  3. Webhooks statt Polling nutzen

Checkliste für die Produktionsbereitstellung

Vor dem Go-Live:

  • [ ] LinkedIn-Partnerverifizierung abgeschlossen
  • [ ] OAuth 2.0 mit sicherer Token-Speicherung eingebaut
  • [ ] Token-Ablaufbenachrichtigungen (60 Tage) integriert
  • [ ] Ratenbegrenzung und Warteschlange implementiert
  • [ ] Webhook-Endpunkte konfiguriert
  • [ ] Fehlerbehandlung abgedeckt
  • [ ] Logging aller API-Aufrufe
  • [ ] Überprüfung auf Markenrichtlinien-Konformität

Anwendungsfälle in der Praxis

Rekrutierungsplattform

  • Herausforderung: Manuelles Posten auf mehreren Kanälen
  • Lösung: LinkedIn Jobs API-Integration
  • Ergebnis: 80 % Zeitersparnis, 3x mehr Bewerbungen

B2B Marketing-Automatisierung

  • Herausforderung: Unregelmäßiger Veröffentlichungsplan
  • Lösung: Automatisiertes Posten via UGC API
  • Ergebnis: 5x mehr Engagement, konsistente Markenpräsenz

Fazit

Die LinkedIn API bietet umfassenden Zugriff auf professionelle Netzwerkfunktionen. Zu beachten:

  • OAuth 2.0-Authentifizierung mit 60-Tage-Tokens
  • APIs für Profil, Posting und Unternehmensseiten verfügbar
  • Ratenbegrenzungen (100-500/Tag) erfordern aktive Verwaltung
  • Partnerverifizierung für viele APIs nötig
  • Apidog optimiert API-Tests und Teamwork

FAQ-Bereich

Wie erhalte ich Zugang zur LinkedIn API?

Erstelle ein LinkedIn-Entwicklerkonto, eine App und beantrage die Partnerverifizierung für erweiterten API-Zugriff.

Kann ich automatisch auf LinkedIn posten?

Ja, per UGC API mit Berechtigung w_member_social (persönlich) bzw. w_organization_social (Unternehmensposts).

Was sind LinkedIn-Ratenbegrenzungen?

Je nach API zwischen 100 und 500 Anfragen pro Tag; Ads API: 100 pro Minute.

Wie lange sind LinkedIn-Tokens gültig?

Tokens sind 60 Tage gültig. Danach ist erneute Authentifizierung erforderlich.

Kann ich auf Benutzerverbindungen zugreifen?

Nein, LinkedIn hat API-Zugriff auf Verbindungen für die meisten Apps aus Datenschutzgründen entfernt.

Top comments (0)