DEV Community

Cover image for Como Usar a API do LinkedIn: Guia Completo de Integração Profissional (2026)
Lucas
Lucas

Posted on • Originally published at apidog.com

Como Usar a API do LinkedIn: Guia Completo de Integração Profissional (2026)

TL;DR

A API do LinkedIn permite integração programática com a rede profissional do LinkedIn via OAuth 2.0, endpoints RESTful e GraphQL para perfis, publicações, comentários, páginas de empresas e anúncios. Limites de 100-500 requisições/dia por app. Este guia mostra como autenticar, acessar perfis, publicar, gerenciar páginas, usar API de anúncios e preparar sua integração para produção.

Experimente o Apidog hoje

Introdução

O LinkedIn conta com mais de 900 milhões de profissionais globalmente. Se você desenvolve ferramentas de recrutamento, plataformas de marketing ou apps B2B, integrar a API do LinkedIn é essencial para atingir esse público.

Profissionais de marketing B2B gastam 15-20 horas semanais gerenciando LinkedIn manualmente. Automatize postagens, geração de leads, análise de engajamento e recrutamento via API.

Este guia cobre: OAuth 2.0, acesso a perfis, publicação, gerenciamento de páginas, anúncios, webhooks e estratégias de produção. Ao fim, você terá uma integração pronta para produção.

💡 Apidog simplifica o teste de integração de API. Teste seus endpoints do LinkedIn, valide fluxos OAuth, inspecione respostas da API e depure problemas de permissão em um único ambiente de trabalho. Importe especificações de API, simule respostas e compartilhe cenários de teste com sua equipe.

O Que É a API do LinkedIn?

O LinkedIn oferece APIs RESTful e GraphQL para acessar dados da rede profissional. Principais funcionalidades:

  • Informações de perfil (com consentimento)
  • Páginas de empresas e atualizações
  • Publicações, comentários, reações
  • Conexões (limitado)
  • Vagas e candidaturas
  • Gerenciamento de anúncios
  • Formulários de leads
  • Mensagens (acesso restrito)

Principais Recursos

Recurso Descrição
RESTful + GraphQL Múltiplos estilos de API
OAuth 2.0 Autorização do usuário necessária
Limite de Taxa 100-500 requisições/dia por aplicativo
Páginas de Empresas Operações CRUD completas
API de Anúncios Gerenciamento de campanhas
Webhooks Notificações em tempo real
Upload de Mídia Imagens e vídeos

Produtos da API

API Nível de Acesso Caso de Uso
Entrar com LinkedIn Aberto Autenticação de usuário
API de Perfil Parceiro Ler perfil de usuário
API de Administração de Empresas Parceiro Gerenciar páginas de empresas
API de Anúncios Parceiro Gerenciamento de campanhas de anúncios
API de Publicação de Vagas Parceiro Publicar e gerenciar vagas
Plataforma de Desenvolvedores de Marketing Parceiro Acesso completo à API

Versões da API

Versão Status Data de Término
v2 Atual Ativa
v1 Aposentada Dezembro de 2023

Primeiros Passos: Configuração de Autenticação

Passo 1: Criar Conta de Desenvolvedor LinkedIn

  1. Acesse o Portal de Desenvolvedores do LinkedIn
  2. Faça login
  3. Clique em Criar Aplicativo
  4. Preencha os detalhes do app (nome, logo, descrição)

Passo 2: Configurar Definições do Aplicativo

Configure variáveis de ambiente para autenticação:

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;
// Obtenha esses dados no painel do app
// https://www.linkedin.com/developers/apps/{appId}/auth
Enter fullscreen mode Exit fullscreen mode

Passo 3: Solicitar Permissões Necessárias

Solicite permissões apropriadas no painel. Veja tabela:

Permissão Descrição Aprovação Necessária
r_liteprofile Perfil básico (nome, foto) Aprovado automaticamente
r_emailaddress Endereço de e-mail Aprovado automaticamente
w_member_social Publicar em nome do usuário Verificação de parceiro
r_basicprofile Perfil completo Verificação de parceiro
r_organization_social Acesso à página da empresa Verificação de parceiro
w_organization_social Publicar na página da empresa Verificação de parceiro
rw_ads Gerenciamento de anúncios Verificação de parceiro
r_ads_reporting Análises de anúncios Verificação de parceiro

Passo 4: Construir URL de Autorização

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

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

Passo 5: Trocar Código por Token de Acesso

Lide com o callback 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 dias
  };
};

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

  try {
    const tokens = await exchangeCodeForToken(code);

    // Armazene tokens com segurança
    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('Autenticação falhou');
  }
});
Enter fullscreen mode Exit fullscreen mode

Passo 6: Atualizar Token de Acesso

Tokens expiram em 60 dias. Não há refresh token:

const refreshAccessToken = async (refreshToken) => {
  // LinkedIn não fornece refresh token.
  // Usuários devem reautenticar após 60 dias.
  // Implemente notificação de expiração.
};

// Antes de chamadas, valide token:
const ensureValidToken = async (userId) => {
  const user = await db.users.findById(userId);

  if (user.linkedin_token_expires < Date.now() + 86400000) { // 24 horas
    // Notifique usuário para reautenticar
    await notifyUserToReauth(user.id);
    throw new Error('Token expirado, por favor, reautentique');
  }

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

Passo 7: Fazer Chamadas de API Autenticadas

Crie um cliente reutilizável:

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(`Erro da API do LinkedIn: ${error.message}`);
  }

  return response.json();
};

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

Acesso ao Perfil

Obtendo Perfil do Usuário

Busque o 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(`Nome: ${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

Obtendo Endereço de E-mail

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

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

Campos de Perfil Disponíveis

Campo Permissão Descrição
id r_liteprofile ID de membro do LinkedIn
firstName r_liteprofile Primeiro nome
lastName r_liteprofile Sobrenome
profilePicture r_liteprofile URL da foto de perfil
headline r_basicprofile Título profissional
summary r_basicprofile Seção "Sobre"
positions r_basicprofile Histórico de trabalho
educations r_basicprofile Histórico educacional
emailAddress r_emailaddress E-mail principal

Publicação de Conteúdo

Criando uma Publicação

Publique texto no feed do usuário:

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: 'Animados para anunciar o lançamento do nosso novo produto! 🚀 #inovação #startup'
});

console.log(`Publicação criada: ${post.id}`);
Enter fullscreen mode Exit fullscreen mode

Criando uma Publicação com Imagem

const createPostWithImage = async (authorUrn, postData) => {
  // Passo 1: Registrar upload da imagem
  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;

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

  // Passo 3: Criar publicação com a imagem
  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

Criando uma Publicação com Vídeo

const createPostWithVideo = async (authorUrn, postData) => {
  // Registrar upload do 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;

  // Upload do vídeo (usar URLs pré-assinadas)
  // ... lógica de upload ...

  // Criar publicação
  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

Especificações de Mídia

Tipo de Mídia Formato Tamanho Máximo Duração
Imagem JPG, PNG, GIF 8MB N/A
Vídeo MP4, MOV 5GB 15 min no máximo
Documento PDF, PPT, DOC 100MB N/A

Gerenciamento de Páginas de Empresas

Obtendo Informações da Empresa

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(`Site: ${company.website}`);
Enter fullscreen mode Exit fullscreen mode

Publicando em Páginas de Empresas

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! Junte-se à nossa equipe em crescimento. #carreiras #contratação'
});
Enter fullscreen mode Exit fullscreen mode

Obtendo Seguidores da 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

Limite de Taxa

Entendendo os Limites de Taxa

API Limite Janela
API de Perfil 100 requisições Por dia
Publicações UGC 50 publicações Por dia
Administração de Empresas 500 requisições Por dia
API de Anúncios 100 requisições Por minuto

Cabeçalhos de Limite de Taxa

Cabeçalho Descrição
X-Restli-Quota-Remaining Requisições restantes
X-Restli-Quota-Reset Segundos até a redefinição

Resolução de Problemas Comuns

Problema: 401 Não Autorizado

Soluções:

  1. Verifique se o token de acesso não expirou (60 dias)
  2. Confira se o escopo do token é suficiente para o recurso
  3. Confirme o cabeçalho Authorization: Bearer {token}

Problema: 403 Proibido

Soluções:

  1. Confira permissões do aplicativo
  2. Garanta que o usuário aprovou os escopos
  3. Verificação de parceiro pode ser necessária

Problema: 429 Limite de Taxa Atingido

Soluções:

  1. Implemente filas de requisições
  2. Use cache para reduzir chamadas
  3. Prefira webhooks em vez de polling

Checklist de Implantação em Produção

Antes de liberar sua integração:

  • [ ] Finalize verificação de Parceiro do LinkedIn
  • [ ] Implemente OAuth 2.0 com armazenamento seguro
  • [ ] Notifique usuários sobre expiração de token (60 dias)
  • [ ] Implemente controle de limite de taxa/filas
  • [ ] Configure endpoints de webhook
  • [ ] Trate erros de forma abrangente
  • [ ] Faça log de todas as chamadas de API
  • [ ] Revise conformidade com diretrizes de marca

Casos de Uso Reais

Plataforma de Recrutamento

  • Desafio: Publicação manual em múltiplos canais
  • Solução: Integração com API de Vagas
  • Resultado: 80% menos tempo, 3x candidaturas

Automação de Marketing B2B

  • Desafio: Agendamento inconsistente
  • Solução: Publicação automatizada via API UGC
  • Resultado: 5x mais engajamento, marca consistente

Conclusão

A API do LinkedIn oferece acesso amplo à rede profissional. Pontos-chave:

  • OAuth 2.0 com validade de token de 60 dias
  • APIs de perfil, publicação e empresas disponíveis
  • Limites de taxa requerem controle rigoroso
  • Verificação de parceiro necessária para APIs avançadas
  • Apidog simplifica testes de API e colaboração

Seção de Perguntas Frequentes (FAQ)

Como faço para obter acesso à API do LinkedIn?

Crie uma conta de Desenvolvedor, um aplicativo e conclua a verificação de Parceiro para acesso avançado.

Posso publicar no LinkedIn automaticamente?

Sim, utilize a API UGC com permissão w_member_social para postagens pessoais ou w_organization_social para empresas.

Quais são os limites de taxa do LinkedIn?

De 100 a 500 requisições/dia por API. API de Anúncios: 100/min.

Quanto tempo duram os tokens do LinkedIn?

60 dias. O usuário precisa reautenticar após isso.

Posso acessar as conexões do usuário?

Não. O LinkedIn restringiu o acesso a conexões para a maioria dos apps devido a privacidade.

Top comments (0)