npm package: @redonvn/linkedin-sdk
Description: Complete LinkedIn SDK for Consumer, Marketing, Sales, Talent, Learning, and Compliance APIs
Author: Pham Tung
Latest version: 1.2.0

# LinkedIn SDK v1.0.0 🚀

[![NPM Version](https://img.shields.io/npm/v/@redonvn/linkedin-sdk)](https://www.npmjs.com/package/@redonvn/linkedin-sdk)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.1-blue.svg)](https://www.typescriptlang.org/)
[![NestJS](https://img.shields.io/badge/NestJS-10.0-red.svg)](https://nestjs.com/)
[![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![API Coverage](https://img.shields.io/badge/API_Coverage-95%25-brightgreen.svg)]()
[![Downloads](https://img.shields.io/npm/dm/@redonvn/linkedin-sdk)](https://www.npmjs.com/package/@redonvn/linkedin-sdk)

**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
```bash
npm install @redonvn/linkedin-sdk
```

### Using yarn
```bash
yarn add @redonvn/linkedin-sdk
```

### Using pnpm
```bash
pnpm add @redonvn/linkedin-sdk
```

### Clone Repository
```bash
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:

1. **Create LinkedIn App**:
   - Go to [LinkedIn Developer Portal](https://developer.linkedin.com/)
   - 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

2. **Verify Your App**:
   - Phone number verification required
   - Email confirmation

3. **Configure Authentication**:
   - Go to **"Auth"** tab
   - Add **Authorized redirect URLs**:
     ```
     http://localhost:3000/auth/callback
     https://yourdomain.com/auth/callback
     ```

4. **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

### Step 2: OAuth 2.0 Flow Implementation

#### Complete OAuth Flow Example:

```typescript
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)

```typescript
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

```bash
# 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:

```env
# 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=debug
```

### Programmatic Configuration

```typescript
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
```typescript
// 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
```typescript
// 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

```typescript
// 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)

```typescript
// 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

```typescript
// 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

```typescript
// 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

```typescript
// 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: 'user@example.com', firstName: 'John', lastName: 'Doe' }
  ]
});

// Get profiles
const profiles = await linkedin.sales.getProfiles({
  keywords: 'software engineer',
  location: 'San Francisco'
});
```

### Talent Solutions API

```typescript
// 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

```typescript
// Get compliance activities
const activities = await linkedin.compliance.getActivities();
```

### Learning API

```typescript
// 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/health
```

### Authentication
```
GET  /api/v1/linkedin/auth/authorization-url?scopes=profile,email
POST /api/v1/linkedin/auth/token
POST /api/v1/linkedin/auth/refresh
```

### Consumer API
```
GET  /api/v1/linkedin/profile/basic
GET  /api/v1/linkedin/profile/email
POST /api/v1/linkedin/share
```

### Marketing 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/:id
```

### Company 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/reply
```

### Sales 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/profiles
```

### Talent API
```
POST /api/v1/linkedin/talent/jobs
POST /api/v1/linkedin/talent/apply
```

### Learning API
```
GET /api/v1/linkedin/learning/request-access
```

### Compliance API
```
GET /api/v1/linkedin/compliance/activities
```

## 🐳 Docker Deployment

### Development
```bash
docker-compose --profile dev up linkedin-sdk-dev
```

### Production
```bash
docker-compose up linkedin-sdk
```

### Custom Build
```bash
docker build -t linkedin-sdk .
docker run -p 3000:3000 --env-file .env linkedin-sdk
```

## 🧪 Testing

### Run All Tests
```bash
npm test
```

### Run Tests with Coverage
```bash
npm run test:cov
```

### Run Tests in Watch Mode
```bash
npm run test:watch
```

### Run E2E Tests
```bash
npm run test:e2e
```

## 🔐 Security

### Webhook Signature Verification

```typescript
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

```typescript
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 information
- `email` - Email address
- `w_member_social` - Share content

### Marketing API
- `r_ads` - Read ad accounts and campaigns
- `rw_ads` - Create and modify campaigns
- `r_ads_reporting` - Access reporting data

### Sales Navigator API
- `r_sales_nav_analytics` - Sales analytics
- `r_sales_nav_display` - Display data
- `r_sales_nav_validation` - CRM validation
- `r_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:

```typescript
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
```typescript
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
```typescript
// 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

1. Fork the repository
2. Create a feature branch: `git checkout -b feature/amazing-feature`
3. Commit your changes: `git commit -m 'Add amazing feature'`
4. Push to the branch: `git push origin feature/amazing-feature`
5. Open a pull request

### Development Setup

```bash
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](LICENSE) file for details.

## 📞 Support

- **Documentation**: Check the [Swagger API docs](http://localhost:3000/docs) when running the server
- **Issues**: [GitHub Issues](https://github.com/your-username/linkedin-sdk-v3/issues)
- **LinkedIn Developer Documentation**: [LinkedIn Developer Platform](https://developer.linkedin.com/)

## 🔗 Related Resources

- [LinkedIn Developer Platform](https://developer.linkedin.com/)
- [LinkedIn OAuth 2.0](https://docs.microsoft.com/en-us/linkedin/shared/authentication/authorization-code-flow)
- [LinkedIn Marketing API](https://docs.microsoft.com/en-us/linkedin/marketing/)
- [LinkedIn Sales Navigator API](https://docs.microsoft.com/en-us/linkedin/sales-solutions/)
- [NestJS Documentation](https://nestjs.com/)

---

**Made with ❤️ by Redon**

*LinkedIn SDK v3.0.0 - Empowering developers with comprehensive LinkedIn API integration*