@redonvn/linkedin-sdk
v1.2.0
Published
Complete LinkedIn SDK for Consumer, Marketing, Sales, Talent, Learning, and Compliance APIs
Readme
LinkedIn SDK v1.0.0 🚀
The most comprehensive and production-ready LinkedIn API SDK for TypeScript/JavaScript
A complete, enterprise-grade TypeScript SDK for LinkedIn APIs, built with NestJS and featuring full support for all major LinkedIn API products:
- 🏢 Consumer API - Profile, Sharing, Authentication
- 📈 Marketing API - Ads, Campaigns, Analytics, Company Pages
- 💼 Sales Navigator API - Analytics, CRM Validation, Lead Search
- 🎯 Talent Solutions API - Job Posting, Applications Management
- 📚 LinkedIn Learning API - Content Management
- 🔒 Compliance API - Activity Monitoring & Data Export
🚀 Features
- ✅ Complete TypeScript Support - Full type definitions and IntelliSense
- ✅ OAuth 2.0 Authentication - Secure token management
- ✅ NestJS Integration - Ready-to-use REST API server
- ✅ Docker Support - Containerized deployment ready
- ✅ Comprehensive Testing - Unit and integration tests
- ✅ Error Handling - Robust error management and logging
- ✅ Swagger Documentation - Auto-generated API docs
- ✅ Webhook Utilities - Challenge validation and signature verification
- ✅ Environment Configuration - Flexible setup options
📦 Installation
Using npm
npm install @redonvn/linkedin-sdkUsing yarn
yarn add @redonvn/linkedin-sdkUsing pnpm
pnpm add @redonvn/linkedin-sdkClone Repository
git clone https://github.com/phamtung86/linkedin-sdk.git
cd linkedin-sdk
npm install🔐 Authentication & Setup
Step 1: LinkedIn App Setup
Before using the SDK, you need to create a LinkedIn App:
Create LinkedIn App:
- Go to LinkedIn Developer Portal
- Click "Create app"
- Fill in required information:
- App name: Your application name
- LinkedIn Page: Associate with company page (required)
- Privacy policy URL: Your privacy policy
- App logo: Upload your logo
Verify Your App:
- Phone number verification required
- Email confirmation
Configure Authentication:
- Go to "Auth" tab
- Add Authorized redirect URLs:
http://localhost:3000/auth/callback https://yourdomain.com/auth/callback
Request Permissions:
- Default Tier (No review needed):
profile,email,openid - Standard Tier (Basic review):
w_member_social,r_ads,rw_ads,w_organization_social - Development Tier (Partner review): Advanced Marketing APIs
- Default Tier (No review needed):
Step 2: OAuth 2.0 Flow Implementation
Complete OAuth Flow Example:
import express from 'express';
import { createLinkedInSDK } from '@redonvn/linkedin-sdk';
const app = express();
const linkedin = createLinkedInSDK({
clientId: process.env.LINKEDIN_CLIENT_ID!,
clientSecret: process.env.LINKEDIN_CLIENT_SECRET!,
redirectUri: process.env.LINKEDIN_REDIRECT_URI!
});
// Step 1: Redirect to LinkedIn for authorization
app.get('/auth/linkedin', (req, res) => {
const scopes = ['profile', 'email', 'w_member_social', 'w_organization_social'];
const authUrl = linkedin.consumer.getAuthUrl(scopes);
res.redirect(authUrl);
});
// Step 2: Handle callback and exchange code for token
app.get('/auth/callback', async (req, res) => {
try {
const { code } = req.query;
// Exchange authorization code for access token
const tokenResponse = await linkedin.consumer.getAccessToken(code as string);
// Store token securely (session, database, etc.)
req.session.linkedinToken = tokenResponse;
// Set token for subsequent API calls
linkedin.setAccessToken(tokenResponse.access_token);
res.redirect('/dashboard');
} catch (error) {
console.error('Authentication failed:', error);
res.status(500).send('Authentication failed');
}
});
// Step 3: Use authenticated APIs
app.get('/profile', async (req, res) => {
try {
const token = req.session.linkedinToken;
if (!token) {
return res.redirect('/auth/linkedin');
}
linkedin.setAccessToken(token.access_token);
const profile = await linkedin.consumer.getProfile();
res.json(profile);
} catch (error) {
console.error('Get profile failed:', error);
res.status(500).json({ error: 'Failed to get profile' });
}
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});⚡ Quick Start
Option A: Use as NPM Library (Recommended)
import { createLinkedInSDK, LinkedInConfig } from '@redonvn/linkedin-sdk';
// Initialize SDK
const config: LinkedInConfig = {
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
redirectUri: 'http://localhost:3000/callback'
};
const linkedin = createLinkedInSDK(config);
// OAuth Flow
const authUrl = linkedin.consumer.getAuthUrl(['profile', 'email']);
// ... redirect user, get code from callback ...
const token = await linkedin.consumer.getAccessToken(code);
linkedin.setAccessToken(token.access_token);
// Use APIs
const profile = await linkedin.consumer.getProfile();
const email = await linkedin.consumer.getEmail();
// Share content
await linkedin.consumer.shareContent({
text: 'Hello LinkedIn! 🚀',
url: 'https://example.com'
});Option B: Use as NestJS Server
# Clone repository
git clone https://github.com/phamtung86/linkedin-sdk.git
cd linkedin-sdk
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Edit .env with your LinkedIn app credentials
# Build and start
npm run build
npm run start:prod
# Or start in development mode
npm run dev
# Visit API documentation
# http://localhost:3000/docs🔧 Configuration
Environment Variables
Create a .env file in your project root:
# LinkedIn API Configuration
LINKEDIN_CLIENT_ID=your_linkedin_client_id
LINKEDIN_CLIENT_SECRET=your_linkedin_client_secret
LINKEDIN_REDIRECT_URI=http://localhost:3000/api/v1/linkedin/auth/callback
# API Configuration (Optional - defaults provided)
LINKEDIN_BASE_URL=https://api.linkedin.com/v2
LINKEDIN_AUTH_URL=https://www.linkedin.com/oauth/v2/authorization
LINKEDIN_TOKEN_URL=https://www.linkedin.com/oauth/v2/accessToken
# Server Configuration
PORT=3000
NODE_ENV=development
LOG_LEVEL=debugProgrammatic Configuration
import { LinkedInConfig } from 'linkedin-sdk-v3';
const config: LinkedInConfig = {
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
redirectUri: 'http://localhost:3000/callback',
baseUrl: 'https://api.linkedin.com/v2', // Optional
authUrl: 'https://www.linkedin.com/oauth/v2/authorization', // Optional
tokenUrl: 'https://www.linkedin.com/oauth/v2/accessToken' // Optional
};📚 API Reference
Consumer API
Authentication
// Generate authorization URL
const authUrl = linkedin.consumer.getAuthUrl(['profile', 'email'], 'optional-state');
// Exchange authorization code for access token
const token = await linkedin.consumer.getAccessToken(code);
// Refresh expired token
const newToken = await linkedin.consumer.refreshAccessToken(refreshToken);Profile & Content
// Get basic profile
const profile = await linkedin.consumer.getProfile();
// Get email address
const email = await linkedin.consumer.getEmail();
// Share content
const shareResult = await linkedin.consumer.shareContent({
text: 'Hello LinkedIn!',
url: 'https://example.com', // Optional
imageUrn: 'urn:li:image:12345' // Optional
});Marketing API
// Get ad accounts
const accounts = await linkedin.marketing.getAdAccounts();
// Create campaign
const campaign = await linkedin.marketing.createCampaign({
name: 'My Campaign',
account: 'urn:li:sponsoredAccount:12345'
// ... other campaign data
});
// Get analytics
const analytics = await linkedin.marketing.getAnalytics({
campaigns: ['urn:li:sponsoredCampaign:12345'],
dateRange: {
start: '2023-01-01',
end: '2023-01-31'
}
});🏢 Company Page Management
Organic Content Posting (Free)
// Create organic post for company page
const organicPost = await linkedin.marketing.createOrganicPost({
author: 'urn:li:organization:123456789', // Your company page ID
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text: '🚀 Exciting company news! We just launched our new feature.'
},
shareMediaCategory: 'NONE'
}
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
}
}, token);
// Create post with image
const imagePost = await linkedin.marketing.createOrganicPost({
author: 'urn:li:organization:123456789',
lifecycleState: 'PUBLISHED',
specificContent: {
'com.linkedin.ugc.ShareContent': {
shareCommentary: {
text: 'Check out our latest product showcase! 📸'
},
shareMediaCategory: 'IMAGE',
media: [{
status: 'READY',
media: imageUrn, // From uploadImage()
title: { text: 'Product Showcase' },
description: { text: 'Our latest innovation' }
}]
}
},
visibility: {
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC'
}
}, token);Page Analytics & Management
// Get company page information
const companyPage = await linkedin.marketing.getCompanyPage('123456789', token);
// Get page followers count
const followers = await linkedin.marketing.getPageFollowers('123456789', token);
// Get all organic posts
const posts = await linkedin.marketing.getOrganicPosts(
'urn:li:organization:123456789',
token
);
// Upload media for posts
const fs = require('fs');
const imageBuffer = fs.readFileSync('company-announcement.jpg');
const uploadResult = await linkedin.marketing.uploadImage(imageBuffer, token);
const imageUrn = uploadResult.image;Community Management
// Get comments on a post
const comments = await linkedin.marketing.getComments(postId, token);
// Reply to comments
for (const comment of comments) {
if (comment.text.includes('@yourcompany')) {
await linkedin.marketing.replyToComment(comment.id, {
text: `Thank you for your interest, ${comment.author.name}! We'll be in touch soon.`
}, token);
}
}
// Get mentions and interactions
const interactions = await linkedin.marketing.getCommunityInteractions({
pageId: 'urn:li:organization:123456789',
dateRange: { start: '2024-01-01', end: '2024-01-31' }
}, token);Sales Navigator API
// Get analytics
const salesAnalytics = await linkedin.sales.getAnalytics();
// Get display data
const displayData = await linkedin.sales.getDisplayData();
// Validate CRM data
const validation = await linkedin.sales.validateCrmData({
contacts: [
{ email: '[email protected]', firstName: 'John', lastName: 'Doe' }
]
});
// Get profiles
const profiles = await linkedin.sales.getProfiles({
keywords: 'software engineer',
location: 'San Francisco'
});Talent Solutions API
// Post a job
const job = await linkedin.talent.postJob({
title: 'Software Engineer',
company: 'urn:li:organization:12345',
location: 'San Francisco, CA',
description: 'We are looking for...'
});
// Submit job application
const application = await linkedin.talent.submitApply({
job: 'urn:li:job:12345',
applicant: 'urn:li:person:67890'
});Compliance API
// Get compliance activities
const activities = await linkedin.compliance.getActivities();Learning API
// Request access (displays information)
linkedin.learning.requestAccess();
// Note: LinkedIn Learning API requires manual approval🌐 REST API Endpoints
When running as a server, the following endpoints are available:
Health Check
GET /api/v1/linkedin/test/healthAuthentication
GET /api/v1/linkedin/auth/authorization-url?scopes=profile,email
POST /api/v1/linkedin/auth/token
POST /api/v1/linkedin/auth/refreshConsumer API
GET /api/v1/linkedin/profile/basic
GET /api/v1/linkedin/profile/email
POST /api/v1/linkedin/shareMarketing API
GET /api/v1/linkedin/marketing/ad-accounts
POST /api/v1/linkedin/marketing/campaigns
GET /api/v1/linkedin/marketing/analytics
POST /api/v1/linkedin/marketing/organic-posts
GET /api/v1/linkedin/marketing/company-page/:id
GET /api/v1/linkedin/marketing/page-followers/:idCompany Page Management
POST /api/v1/linkedin/marketing/organic-posts
GET /api/v1/linkedin/marketing/organic-posts/:authorUrn
POST /api/v1/linkedin/marketing/upload-image
POST /api/v1/linkedin/marketing/upload-video
GET /api/v1/linkedin/comments/:postId
POST /api/v1/linkedin/comments/:commentId/replySales API
GET /api/v1/linkedin/sales/analytics
GET /api/v1/linkedin/sales/display-data
POST /api/v1/linkedin/sales/validate-crm
GET /api/v1/linkedin/sales/profilesTalent API
POST /api/v1/linkedin/talent/jobs
POST /api/v1/linkedin/talent/applyLearning API
GET /api/v1/linkedin/learning/request-accessCompliance API
GET /api/v1/linkedin/compliance/activities🐳 Docker Deployment
Development
docker-compose --profile dev up linkedin-sdk-devProduction
docker-compose up linkedin-sdkCustom Build
docker build -t linkedin-sdk .
docker run -p 3000:3000 --env-file .env linkedin-sdk🧪 Testing
Run All Tests
npm testRun Tests with Coverage
npm run test:covRun Tests in Watch Mode
npm run test:watchRun E2E Tests
npm run test:e2e🔐 Security
Webhook Signature Verification
import { verifyWebhookSignature } from 'linkedin-sdk-v3';
// Verify webhook signature
const isValid = verifyWebhookSignature(
rawBodyString,
request.headers['x-li-signature'],
clientSecret
);
if (!isValid) {
throw new Error('Invalid webhook signature');
}Challenge Response for Webhook Setup
import { computeChallengeResponse } from 'linkedin-sdk-v3';
const response = computeChallengeResponse(challengeCode, clientSecret);📖 LinkedIn API Permissions
Different endpoints require different permissions. Make sure to request the appropriate scopes:
Consumer API
profile- Basic profile informationemail- Email addressw_member_social- Share content
Marketing API
r_ads- Read ad accounts and campaignsrw_ads- Create and modify campaignsr_ads_reporting- Access reporting data
Sales Navigator API
r_sales_nav_analytics- Sales analyticsr_sales_nav_display- Display datar_sales_nav_validation- CRM validationr_sales_nav_profiles- Profile access
Talent Solutions API
Requires participation in LinkedIn's partner programs.
Learning API
Requires manual approval from LinkedIn.
Compliance API
r_compliance- Compliance activities
🚨 Error Handling
The SDK provides comprehensive error handling:
import { LinkedInApiError } from 'linkedin-sdk-v3';
try {
const profile = await linkedin.consumer.getProfile();
} catch (error) {
if (error instanceof LinkedInApiError) {
console.error('LinkedIn API Error:', error.message);
console.error('Status:', error.status);
console.error('Service Error Code:', error.serviceErrorCode);
} else {
console.error('Unexpected error:', error);
}
}📝 Examples
Complete OAuth Flow
import express from 'express';
import { createLinkedInSDK } from 'linkedin-sdk-v3';
const app = express();
const linkedin = createLinkedInSDK({
clientId: process.env.LINKEDIN_CLIENT_ID!,
clientSecret: process.env.LINKEDIN_CLIENT_SECRET!,
redirectUri: 'http://localhost:3000/callback'
});
// Start OAuth flow
app.get('/auth', (req, res) => {
const authUrl = linkedin.consumer.getAuthUrl(['profile', 'email']);
res.redirect(authUrl);
});
// Handle callback
app.get('/callback', async (req, res) => {
try {
const { code } = req.query;
const token = await linkedin.consumer.getAccessToken(code as string);
// Store token securely (session, database, etc.)
req.session.linkedinToken = token;
res.redirect('/profile');
} catch (error) {
res.status(500).send('Authentication failed');
}
});
// Get profile
app.get('/profile', async (req, res) => {
try {
const profile = await linkedin.consumer.getProfile();
res.json(profile);
} catch (error) {
res.status(500).send('Failed to get profile');
}
});
app.listen(3000);Batch Operations
// Get multiple marketing metrics
const promises = [
linkedin.marketing.getAdAccounts(),
linkedin.marketing.getAnalytics({ dateRange: { start: '2023-01-01', end: '2023-01-31' } })
];
const [accounts, analytics] = await Promise.all(promises);🤝 Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a pull request
Development Setup
git clone https://github.com/your-username/linkedin-sdk-v3.git
cd linkedin-sdk-v3
npm install
cp .env.example .env
# Add your LinkedIn app credentials to .env
npm run dev📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
📞 Support
- Documentation: Check the Swagger API docs when running the server
- Issues: GitHub Issues
- LinkedIn Developer Documentation: LinkedIn Developer Platform
🔗 Related Resources
- LinkedIn Developer Platform
- LinkedIn OAuth 2.0
- LinkedIn Marketing API
- LinkedIn Sales Navigator API
- NestJS Documentation
Made with ❤️ by Redon
LinkedIn SDK v3.0.0 - Empowering developers with comprehensive LinkedIn API integration
