DEV Community

Cover image for Cómo Usar la API de LinkedIn: Guía Completa de Integración Profesional (2026)
Roobia
Roobia

Posted on • Originally published at apidog.com

Cómo Usar la API de LinkedIn: Guía Completa de Integración Profesional (2026)

TL;DR

La API de LinkedIn permite a los desarrolladores integrarse programáticamente con la red profesional de LinkedIn. Utiliza autenticación OAuth 2.0, puntos finales RESTful y GraphQL para perfiles, publicaciones, comentarios, páginas de empresa y anuncios, con límites de tasa de 100-500 solicitudes por día por aplicación. Esta guía cubre la configuración de la autenticación, el acceso al perfil, la publicación de contenido, la gestión de páginas de empresa, la API de anuncios y las estrategias de integración en producción.

Prueba Apidog hoy

Introducción

LinkedIn tiene más de 900 millones de usuarios profesionales en más de 200 países. Para los desarrolladores que crean herramientas de reclutamiento, plataformas de marketing o aplicaciones B2B, la integración de la API de LinkedIn es esencial para llegar a esta audiencia profesional.

Esta es la realidad: los especialistas en marketing B2B que gestionan manualmente la presencia en LinkedIn pierden de 15 a 20 horas semanales en la publicación, el seguimiento del engagement y la generación de leads. Una sólida integración de la API de LinkedIn automatiza la distribución de contenido, la captura de leads, el análisis del engagement y los flujos de trabajo de reclutamiento.

Esta guía le guiará a través del proceso completo de integración de la API de LinkedIn. Aprenderá sobre la autenticación OAuth 2.0, el acceso al perfil, la publicación de contenido, la gestión de páginas de empresa, la integración de anuncios, los webhooks y las estrategias de implementación en producción. Al final, tendrá una integración de LinkedIn lista para producción.

💡 Apidog simplifica las pruebas de integración de API. Pruebe sus puntos finales de LinkedIn, valide los flujos de OAuth, inspeccione las respuestas de la API y depure los problemas de permisos en un solo espacio de trabajo. Importe especificaciones de API, simule respuestas y comparta escenarios de prueba con su equipo.

¿Qué es la API de LinkedIn?

LinkedIn proporciona APIs RESTful y GraphQL para acceder a los datos de la red profesional. La API maneja:

  • Información del perfil de usuario (con consentimiento)
  • Páginas y actualizaciones de empresa
  • Publicaciones, comentarios y reacciones
  • Conexiones (limitado)
  • Publicaciones y solicitudes de empleo
  • Gestión de LinkedIn Ads
  • Formularios de generación de leads
  • Mensajería (solo socios limitados)

Características Clave

Característica Descripción
RESTful + GraphQL Múltiples estilos de API
OAuth 2.0 Requiere autorización de usuario
Límite de Tasa 100-500 solicitudes/día
Páginas de Empresa Operaciones CRUD completas
API de Anuncios Gestión de campañas
Webhooks Notificaciones en tiempo real
Carga de Medios Imágenes y vídeos

Productos de la API

API Nivel de Acceso Caso de Uso
Iniciar Sesión con LinkedIn Abierto Autenticación de usuario
API de Perfil Socio Leer perfil de usuario
API de Administración de Empresa Socio Gestionar páginas de empresa
API de Anuncios Socio Gestión de campañas publicitarias
API de Publicación de Empleos Socio Publicar y gestionar empleos
Plataforma de Desarrolladores de Marketing Socio Acceso completo a la API

Versiones de la API

Versión Estado Fecha de Finalización
v2 Actual Activa
v1 Retirada Diciembre de 2023

Primeros Pasos: Configuración de la Autenticación

Paso 1: Crear una Cuenta de Desarrollador de LinkedIn

  1. Visite el Portal de Desarrolladores de LinkedIn
  2. Inicie sesión con su cuenta de LinkedIn
  3. Haga clic en Crear Aplicación en el panel de Mis Aplicaciones
  4. Complete los detalles de la aplicación (nombre, logotipo, descripción)

Paso 2: Configurar los Ajustes de la Aplicación

Configure la autenticación:

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;

// Obtenga estos datos del panel de su aplicación
// https://www.linkedin.com/developers/apps/{appId}/auth
Enter fullscreen mode Exit fullscreen mode

Paso 3: Solicitar los Permisos Necesarios

Solicite y configure los permisos requeridos para su funcionalidad:

Permiso Descripción Aprobación Requerida
r_liteprofile Perfil básico (nombre, foto) Automática
r_emailaddress Dirección de correo electrónico Automática
w_member_social Publicar en nombre del usuario Verificación de socio
r_basicprofile Perfil completo Verificación de socio
r_organization_social Acceso a página de empresa Verificación de socio
w_organization_social Publicar en página de empresa Verificación de socio
rw_ads Gestión de anuncios Verificación de socio
r_ads_reporting Análisis de anuncios Verificación de socio

Paso 4: Construir la URL de Autorización

Implemente el flujo OAuth 2.0 para obtener el consentimiento del usuario:

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

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

Paso 5: Intercambiar el Código por un Token de Acceso

Implemente el endpoint de callback para intercambiar el código de autorización por un token de acceso:

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 días
  };
};

// Manejar la devolución de llamada
app.get('/oauth/callback', async (req, res) => {
  const { code, state } = req.query;

  try {
    const tokens = await exchangeCodeForToken(code);

    // Almacenar tokens de forma segura
    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('Error de OAuth:', error);
    res.status(500).send('Autenticación fallida');
  }
});
Enter fullscreen mode Exit fullscreen mode

Paso 6: Refrescar el Token de Acceso

LinkedIn no ofrece tokens de refresco. Debe implementar notificaciones de caducidad y pedir que el usuario vuelva a autenticarse cada 60 días.

const refreshAccessToken = async (refreshToken) => {
  // Nota: LinkedIn no proporciona tokens de refresco
  // Los usuarios deben volver a autenticarse después de 60 días
  // Implementar notificación de caducidad
};

// Verificar la caducidad del token antes de las llamadas a la API
const ensureValidToken = async (userId) => {
  const user = await db.users.findById(userId);

  if (user.linkedin_token_expires < Date.now() + 86400000) { // 24 horas
    // Notificar al usuario para que vuelva a autenticarse
    await notifyUserToReauth(user.id);
    throw new Error('Token expirado, por favor, vuelva a autenticarse');
  }

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

Paso 7: Realizar Llamadas Autenticadas a la API

Cree un cliente de API reutilizable para gestionar las solicitudes autenticadas:

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(`Error de la API de LinkedIn: ${error.message}`);
  }

  return response.json();
};

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

Acceso al Perfil

Obtener el Perfil del Usuario

Obtenga el perfil autenticado:

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

// Uso
const profile = await getUserProfile();

console.log(`Nombre: ${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

Obtener la Dirección de Correo Electrónico

Acceda al correo electrónico del usuario autenticado:

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

// Uso
const email = await getUserEmail();
console.log(`Correo electrónico: ${email.elements?.[0]?.emailAddress}`);
Enter fullscreen mode Exit fullscreen mode

Campos de Perfil Disponibles

Campo Permiso Descripción
id r_liteprofile ID de miembro de LinkedIn
firstName r_liteprofile Nombre
lastName r_liteprofile Apellido
profilePicture r_liteprofile URL de la foto de perfil
headline r_basicprofile Titular profesional
summary r_basicprofile Sección "Acerca de"
positions r_basicprofile Historial laboral
educations r_basicprofile Historial educativo
emailAddress r_emailaddress Correo electrónico principal

Publicación de Contenido

Crear una Publicación

Comparta una publicación de texto en el feed del usuario:

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

// Uso
const post = await createPost('urn:li:person:ABC123', {
  text: '¡Emocionados de anunciar el lanzamiento de nuestro nuevo producto! 🚀 #innovación #startup'
});

console.log(`Publicación creada: ${post.id}`);
Enter fullscreen mode Exit fullscreen mode

Crear una Publicación con Imagen

Use el flujo de carga de medios para agregar imágenes a las publicaciones:

const createPostWithImage = async (authorUrn, postData) => {
  // Paso 1: Registrar la carga de medios
  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;

  // Paso 2: Subir imagen a la URL proporcionada
  await fetch(uploadUrl, {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + await getAccessToken(),
      'Content-Type': 'application/octet-stream'
    },
    body: postData.imageBuffer
  });

  // Paso 3: Crear publicación con la imagen subida
  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

Crear una Publicación con Vídeo

Para compartir vídeos, registre primero la carga y luego publique:

const createPostWithVideo = async (authorUrn, postData) => {
  // Registrar la carga de vídeo
  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;

  // Subir vídeo (usar URLs de carga pre-firmadas de la respuesta)
  // ... lógica de carga ...

  // Crear publicación
  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

Especificaciones de Medios

Tipo de Medio Formato Tamaño Máx. Duración
Imagen JPG, PNG, GIF 8MB N/A
Vídeo MP4, MOV 5GB 15 min máx.
Documento PDF, PPT, DOC 100MB N/A

Gestión de Páginas de Empresa

Obtener Información de la Empresa

Consulte datos de la página de empresa por ID:

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

// Uso
const company = await getCompanyInfo('1234567');
console.log(`Empresa: ${company.localizedName}`);
console.log(`Seguidores: ${company.followerCount}`);
console.log(`Sitio web: ${company.website}`);
Enter fullscreen mode Exit fullscreen mode

Publicar en la Página de Empresa

Cree publicaciones como organización:

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

// Uso
const post = await createCompanyPost('urn:li:organization:1234567', {
  text: '¡Estamos contratando! Únase a nuestro creciente equipo. #carreras #contratación'
});
Enter fullscreen mode Exit fullscreen mode

Obtener Seguidores de la Empresa

Obtenga el conteo de seguidores de la página de empresa:

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

Límites de Tasa

Comprendiendo los Límites de Tasa

API Límite Ventana
API de Perfil 100 solicitudes Por día
Publicaciones UGC 50 publicaciones Por día
Administración Empresa 500 solicitudes Por día
API de Anuncios 100 solicitudes Por minuto

Cabeceras de Límite de Tasa

Cabecera Descripción
X-Restli-Quota-Remaining Solicitudes restantes
X-Restli-Quota-Reset Segundos hasta reinicio

Resolución de Problemas Comunes

Problema: 401 No Autorizado

Soluciones:

  1. Verifique que el token de acceso no haya expirado (60 días)
  2. Compruebe que el alcance del token incluye el recurso solicitado
  3. Asegúrese de que la cabecera Authorization: Bearer {token} esté presente

Problema: 403 Prohibido

Soluciones:

  1. Verifique que la aplicación tenga los permisos necesarios
  2. Compruebe que el usuario aprobó los ámbitos solicitados
  3. Puede ser necesaria la verificación de socio

Problema: 429 Límite de Tasa Alcanzado

Soluciones:

  1. Implemente cola de solicitudes
  2. Almacene en caché las respuestas para reducir llamadas
  3. Use webhooks en lugar de sondeo

Lista de Verificación de Implementación en Producción

Antes de salir en vivo, asegúrese de:

  • [ ] Completar la verificación de socio de LinkedIn
  • [ ] Implementar OAuth 2.0 con almacenamiento seguro de tokens
  • [ ] Añadir notificaciones de caducidad de tokens (60 días)
  • [ ] Configurar límites de tasa y cola
  • [ ] Configurar puntos finales de webhook
  • [ ] Implementar un manejo de errores exhaustivo
  • [ ] Añadir registro para todas las llamadas a la API
  • [ ] Crear revisión de cumplimiento de directrices de marca

Casos de Uso en el Mundo Real

Plataforma de Reclutamiento

Automatice publicaciones de empleo:

  • Desafío: Publicación manual en múltiples canales
  • Solución: Integración con la API de Empleos de LinkedIn
  • Resultado: 80% de ahorro de tiempo, 3x más solicitudes

Automatización de Marketing B2B

Automatice la programación de contenido:

  • Desafío: Horario de publicación inconsistente
  • Solución: Publicación automatizada vía API UGC
  • Resultado: 5x más engagement, presencia de marca consistente

Conclusión

La API de LinkedIn proporciona acceso completo a las características de la red profesional. Puntos clave:

  • Autenticación OAuth 2.0 con tokens de 60 días
  • APIs de perfil, publicación y página de empresa disponibles
  • Los límites de tasa requieren una gestión cuidadosa (100-500/día)
  • Verificación de socio requerida para la mayoría de las APIs
  • Apidog agiliza las pruebas de API y la colaboración en equipo

Sección de Preguntas Frecuentes

¿Cómo obtengo acceso a la API de LinkedIn?

Cree una cuenta de desarrollador de LinkedIn, cree una aplicación y complete la verificación de socio para obtener acceso avanzado a la API.

¿Puedo publicar en LinkedIn automáticamente?

Sí, utilice la API UGC (Contenido Generado por el Usuario) con el permiso w_member_social para publicaciones personales o w_organization_social para publicaciones de empresa.

¿Cuáles son los límites de tasa de LinkedIn?

Los límites de tasa varían de 100 a 500 solicitudes por día, dependiendo de la API. La API de Anuncios permite 100 solicitudes por minuto.

¿Cuánto tiempo duran los tokens de LinkedIn?

Los tokens de acceso expiran después de 60 días. Los usuarios deben volver a autenticarse para continuar con el acceso a la API.

¿Puedo acceder a las conexiones de los usuarios?

No, LinkedIn eliminó el acceso a la API de conexiones para la mayoría de las aplicaciones debido a cambios de privacidad.

Top comments (0)