The LinkedIn integration connects your Cognest assistant to the LinkedIn Marketing and Community Management APIs. Publish posts, share articles, manage company pages, monitor engagement, and respond to messages programmatically. Cognest handles the OAuth 2.0 three-legged flow, token refresh, and rate limiting transparently.
http://localhost:3000/auth/linkedin/callback to your app's OAuth 2.0 settings.LINKEDIN_CLIENT_ID=your_client_id
LINKEDIN_CLIENT_SECRET=your_client_secretOAuth 2.0 Flow
LinkedIn uses OAuth 2.0 with authorization code grant. Cognest will prompt you to complete the browser-based authorization on first use. Tokens are stored encrypted and refreshed automatically before expiry.
Add the LinkedIn integration to your cognest.config.yaml:
integrations:
linkedin:
enabled: true
credentials:
client_id: ${LINKEDIN_CLIENT_ID}
client_secret: ${LINKEDIN_CLIENT_SECRET}
settings:
# OAuth redirect URI (must match your LinkedIn app settings)
redirect_uri: http://localhost:3000/auth/linkedin/callback
# Scopes to request during authorization
scopes:
- openid
- profile
- email
- w_member_social
# Company page URN for organization-level posting (optional)
company_urn: "urn:li:organization:12345678"
# Poll interval for engagement and message checks (seconds)
poll_interval: 60import { Cognest } from '@cognest/sdk'
const cognest = new Cognest()
const linkedin = cognest.integration('linkedin')
// Post to your personal profile
await linkedin.createPost({
text: 'Excited to share our latest product update!',
visibility: 'PUBLIC',
})
await cognest.start()| Method | Parameters | Description |
|---|---|---|
| createPost(options) | { text, visibility?, mediaUrls?, companyUrn? } | Publish a text or media post. Defaults to the authenticated user's profile; pass companyUrn to post as a company page. |
| shareArticle(options) | { url, title?, description?, companyUrn? } | Share an article link with optional title and description. |
| getProfile(memberId?) | memberId?: string | Retrieve a LinkedIn profile. Defaults to the authenticated user. |
| getCompanyPage(urn) | urn: string | Fetch company page details including follower count, description, and admin list. |
| getConnections(options?) | options?: { start?, count? } | List connections of the authenticated user with pagination support. |
| sendMessage(options) | { recipientUrn, text, subject? } | Send a LinkedIn message to a 1st-degree connection. |
LinkedIn events are delivered via polling since the API does not support webhooks for most resources. Configure poll_interval in settings to control check frequency.
| Event | Payload | Description |
|---|---|---|
| post:engagement | { postUrn, type, actorUrn, actorName, createdAt } | Fired when someone likes, comments on, or shares one of your posts. The type field is 'like', 'comment', or 'share'. |
| message:received | { senderUrn, senderName, text, threadId, createdAt } | Fired when a new message is received in LinkedIn messaging. |
| connection:new | { memberUrn, memberName, connectedAt } | Fired when a new connection request is accepted. |
linkedin.on('post:engagement', async (event) => {
if (event.type === 'comment') {
console.log(`${event.actorName} commented on your post`)
}
})
linkedin.on('message:received', async (event) => {
console.log(`Message from ${event.senderName}: ${event.text}`)
})
linkedin.on('connection:new', async (event) => {
// Send a welcome message to new connections
await linkedin.sendMessage({
recipientUrn: event.memberUrn,
text: `Hi ${event.memberName}, thanks for connecting! Happy to be in your network.`,
})
})A complete example that automates thought-leadership posting and engagement monitoring for a company page:
import { Cognest } from '@cognest/sdk'
const cognest = new Cognest()
const linkedin = cognest.integration('linkedin')
const COMPANY_URN = 'urn:li:organization:12345678'
// Schedule daily thought-leadership posts
cognest.skill('daily-linkedin-post', {
schedule: '0 9 * * 1-5', // 9 AM, weekdays
handler: async () => {
// Generate a post using the AI engine
const post = await cognest.engine.run({
prompt: `Write a concise LinkedIn post (under 1300 characters) for a B2B SaaS company
that sells AI-powered workflow automation. The tone should be professional but
approachable. Include 2-3 relevant hashtags at the end. Topic: pick a trending
theme in AI automation this week.`,
})
await linkedin.createPost({
text: post.text,
visibility: 'PUBLIC',
companyUrn: COMPANY_URN,
})
console.log('Daily LinkedIn post published')
},
})
// Monitor engagement and auto-respond to comments
linkedin.on('post:engagement', async (event) => {
if (event.type !== 'comment') return
// Fetch the comment content using the API
const profile = await linkedin.getProfile()
console.log(`Engagement on post ${event.postUrn}: ${event.type} by ${event.actorName}`)
})
// Auto-welcome new connections with a personalized message
linkedin.on('connection:new', async (event) => {
const profile = await linkedin.getProfile(event.memberUrn)
const message = await cognest.engine.run({
prompt: `Write a short, professional LinkedIn welcome message (2-3 sentences)
for a new connection named ${event.memberName}. Mention that we'd love to
learn about their work and explore potential collaboration.`,
})
await linkedin.sendMessage({
recipientUrn: event.memberUrn,
text: message.text,
})
console.log(`Welcome message sent to ${event.memberName}`)
})
// Weekly content share: find and share relevant industry articles
cognest.skill('weekly-article-share', {
schedule: '0 14 * * 3', // 2 PM on Wednesdays
handler: async () => {
const article = await cognest.engine.run({
prompt: `Suggest one recent high-quality article URL about AI in enterprise
workflows. Return JSON: { "url": "...", "title": "...", "commentary": "..." }
where commentary is a 2-sentence take on the article.`,
responseFormat: 'json',
})
const { url, title, commentary } = JSON.parse(article.text)
await linkedin.shareArticle({
url,
title,
description: commentary,
companyUrn: COMPANY_URN,
})
console.log(`Shared article: ${title}`)
},
})
await cognest.start()
console.log('LinkedIn automation is running...')Common Issues
401 Unauthorized: Your OAuth tokens may have expired. LinkedIn access tokens expire after 60 days (or 365 days for refresh tokens). Cognest handles automatic refresh, but if the refresh token itself has expired, you will need to re-authorize through the OAuth flow. 403 Restricted: Posting to a company page requires the authenticated user to be a Super Admin of that page. Verify your admin status in the company page settings on LinkedIn. "Scope not authorized" error: Ensure your LinkedIn app has been approved for the required products (Share on LinkedIn, Community Management API). Product approval can take 1-5 business days. Rate limiting: LinkedIn allows approximately 100 API calls per day per user and 1,000 per day per app. Use poll_interval of 60 seconds or higher to avoid hitting limits.
Testing with a Test Company Page
LinkedIn provides a test company page for development. Use the "Test" toggle in your Developer Portal app settings to create posts that are only visible to app admins, avoiding any impact on your live company page during development.