LinkedIn API
Schedule and automate LinkedIn posts with Zernio API - Personal profiles, company pages, images, videos, documents, and multi-organization posting
Quick Reference
| Property | Value |
|---|---|
| Character limit | 3,000 |
| Images per post | 20 |
| Videos per post | 1 |
| Documents per post | 1 (PDF, PPT, PPTX, DOC, DOCX) |
| Image formats | JPEG, PNG, GIF |
| Image max size | 8 MB |
| Video formats | MP4, MOV, AVI |
| Video max size | 5 GB |
| Video max duration | 10 min (personal), 30 min (company page) |
| Post types | Text, Image, Multi-image, Video, Document |
| Scheduling | Yes |
| Inbox (Comments) | Yes (add-on, company pages only) |
| Inbox (DMs) | No (LinkedIn blocks third-party DM access) |
| Analytics | Yes |
Before You Start
LinkedIn actively suppresses posts containing external links. Your post's organic reach can drop 40-50% if you include a URL in the caption. Best practice: put your link in the first comment using the firstComment field. Also: LinkedIn rejects duplicate content with a 422 error. You cannot post the same text twice, even across different time periods.
Additional details:
- Works with personal profiles AND company pages
- Company pages: full analytics, 30-min video, comments API
- Personal profiles: limited analytics, 10-min video
- Cannot mix media types (images + videos or images + documents in the same post)
- First ~210 characters of your post are visible before the "see more" fold
Quick Start
Post to LinkedIn in under 60 seconds:
const { post } = await zernio.posts.createPost({
content: 'Excited to share our latest update!\n\nWe have been working hard on this feature...',
platforms: [
{ platform: 'linkedin', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Excited to share our latest update!\n\nWe have been working hard on this feature...",
platforms=[
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Excited to share our latest update!\n\nWe have been working hard on this feature...",
"platforms": [
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Content Types
Text-Only Post
Text posts get the highest organic reach on LinkedIn. The first ~210 characters appear before the "see more" fold, so lead with your hook. Up to 3,000 characters total.
const { post } = await zernio.posts.createPost({
content: 'I spent 3 years building the wrong product.\n\nHere is what I learned about validating ideas before writing code...',
platforms: [
{ platform: 'linkedin', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="I spent 3 years building the wrong product.\n\nHere is what I learned about validating ideas before writing code...",
platforms=[
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "I spent 3 years building the wrong product.\n\nHere is what I learned about validating ideas before writing code...",
"platforms": [
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Single Image Post
Attach one image to a post. Recommended size is 1200 x 627 px (landscape).
const { post } = await zernio.posts.createPost({
content: 'Our new office setup is looking great!',
mediaItems: [
{ type: 'image', url: 'https://cdn.example.com/office.jpg' }
],
platforms: [
{ platform: 'linkedin', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Our new office setup is looking great!",
media_items=[
{"type": "image", "url": "https://cdn.example.com/office.jpg"}
],
platforms=[
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Our new office setup is looking great!",
"mediaItems": [
{"type": "image", "url": "https://cdn.example.com/office.jpg"}
],
"platforms": [
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Multi-Image Post
LinkedIn supports up to 20 images in a single post. Cannot include videos or documents alongside images.
const { post } = await zernio.posts.createPost({
content: 'Highlights from our team retreat!',
mediaItems: [
{ type: 'image', url: 'https://cdn.example.com/photo1.jpg' },
{ type: 'image', url: 'https://cdn.example.com/photo2.jpg' },
{ type: 'image', url: 'https://cdn.example.com/photo3.jpg' }
],
platforms: [
{ platform: 'linkedin', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Highlights from our team retreat!",
media_items=[
{"type": "image", "url": "https://cdn.example.com/photo1.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo2.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo3.jpg"}
],
platforms=[
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Highlights from our team retreat!",
"mediaItems": [
{"type": "image", "url": "https://cdn.example.com/photo1.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo2.jpg"},
{"type": "image", "url": "https://cdn.example.com/photo3.jpg"}
],
"platforms": [
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Video Post
One video per post. Personal profiles support up to 10 minutes, company pages up to 30 minutes. MP4, MOV, and AVI formats. GIFs are converted to video and count against the 1-video limit.
const { post } = await zernio.posts.createPost({
content: 'Watch our latest product demo',
mediaItems: [
{ type: 'video', url: 'https://cdn.example.com/demo.mp4' }
],
platforms: [
{ platform: 'linkedin', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Watch our latest product demo",
media_items=[
{"type": "video", "url": "https://cdn.example.com/demo.mp4"}
],
platforms=[
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Watch our latest product demo",
"mediaItems": [
{"type": "video", "url": "https://cdn.example.com/demo.mp4"}
],
"platforms": [
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Document/Carousel Post
LinkedIn uniquely supports document uploads (PDF, PPT, PPTX, DOC, DOCX) that display as swipeable carousels. Max 100 MB, up to 300 pages. Cannot include images or videos alongside a document.
const { post } = await zernio.posts.createPost({
content: 'Download our 2024 Industry Report',
mediaItems: [
{ type: 'document', url: 'https://cdn.example.com/report.pdf' }
],
platforms: [
{ platform: 'linkedin', accountId: 'YOUR_ACCOUNT_ID' }
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Download our 2024 Industry Report",
media_items=[
{"type": "document", "url": "https://cdn.example.com/report.pdf"}
],
platforms=[
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Download our 2024 Industry Report",
"mediaItems": [
{"type": "document", "url": "https://cdn.example.com/report.pdf"}
],
"platforms": [
{"platform": "linkedin", "accountId": "YOUR_ACCOUNT_ID"}
],
"publishNow": true
}'Document tips:
- First page is the cover/preview -- design it to grab attention
- Design for mobile viewing (large fonts, minimal text per slide)
- Ideal length for engagement: 10-15 pages
- Password-protected PDFs will not work
Media Requirements
Images
| Property | Requirement |
|---|---|
| Max images | 20 per post |
| Formats | JPEG, PNG, GIF |
| Max file size | 8 MB per image |
| Recommended | 1200 x 627 px |
| Min dimensions | 552 x 276 px |
| Max dimensions | 8192 x 8192 px |
Aspect Ratios
| Type | Ratio | Dimensions | Use Case |
|---|---|---|---|
| Landscape | 1.91:1 | 1200 x 627 px | Link shares, standard |
| Square | 1:1 | 1080 x 1080 px | Engagement |
| Portrait | 1:1.25 | 1080 x 1350 px | Mobile feed |
Videos
| Property | Requirement |
|---|---|
| Max videos | 1 per post |
| Formats | MP4, MOV, AVI |
| Max file size | 5 GB |
| Max duration | 10 min (personal), 30 min (company page) |
| Min duration | 3 seconds |
| Resolution | 256 x 144 px to 4096 x 2304 px |
| Aspect ratio | 1:2.4 to 2.4:1 |
| Frame rate | 10-60 fps |
Recommended Video Specs
| Property | Recommended |
|---|---|
| Resolution | 1920 x 1080 px (1080p) |
| Aspect ratio | 16:9 (landscape) or 1:1 (square) |
| Frame rate | 30 fps |
| Codec | H.264 |
| Audio | AAC, 192 kbps |
| Bitrate | 10-30 Mbps |
Documents
| Property | Requirement |
|---|---|
| Max documents | 1 per post |
| Formats | PDF, PPT, PPTX, DOC, DOCX |
| Max file size | 100 MB |
| Max pages | 300 pages |
Platform-Specific Fields
All fields go inside platformSpecificData on the LinkedIn platform entry.
| Field | Type | Description |
|---|---|---|
documentTitle | string | Title displayed on LinkedIn document (PDF/carousel) posts. Required by LinkedIn for document posts. If omitted, falls back to the media item title, then the filename. |
organizationUrn | string | Post to a specific LinkedIn company page. Format: urn:li:organization:123456. Get available orgs via GET /v1/accounts/{accountId}/linkedin-organizations. If omitted, posts to default org or personal profile. |
firstComment | string | Auto-posted as first comment after publish. Best practice: put external links here since LinkedIn suppresses link posts by 40-50%. |
disableLinkPreview | boolean | Set to true to suppress the automatic URL preview card. Default: false. |
LinkedIn Document Titles
LinkedIn requires a title for document (PDF/carousel) posts. Set platformSpecificData.documentTitle to control the title shown on LinkedIn.
Note: If
documentTitleis omitted, Zernio falls back to the media itemtitle, then thefilename.
curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Download our 2024 Industry Report",
"mediaItems": [
{"type": "document", "url": "https://cdn.example.com/report.pdf"}
],
"platforms": [{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"documentTitle": "2024 Industry Report"
}
}],
"publishNow": true
}'const { post } = await zernio.posts.createPost({
content: 'Download our 2024 Industry Report',
mediaItems: [
{ type: 'document', url: 'https://cdn.example.com/report.pdf' }
],
platforms: [{
platform: 'linkedin',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
documentTitle: '2024 Industry Report'
}
}],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Download our 2024 Industry Report",
media_items=[
{"type": "document", "url": "https://cdn.example.com/report.pdf"}
],
platforms=[{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"documentTitle": "2024 Industry Report"
}
}],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")Multi-Organization Posting
If your connected LinkedIn account manages multiple organizations (company pages), you can post to different organizations from the same account connection.
List available organizations:
const organizations = await zernio.accounts.getLinkedInOrganizations('YOUR_ACCOUNT_ID');
console.log('Available organizations:', organizations);organizations = client.accounts.get_linkedin_organizations("YOUR_ACCOUNT_ID")
print("Available organizations:", organizations)curl -X GET https://zernio.com/api/v1/accounts/YOUR_ACCOUNT_ID/linkedin-organizations \
-H "Authorization: Bearer YOUR_API_KEY"Post to multiple organizations using the same accountId with different organizationUrn values:
const { post } = await zernio.posts.createPost({
content: 'Exciting updates from our organization!',
platforms: [
{
platform: 'linkedin',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: { organizationUrn: 'urn:li:organization:111111111' }
},
{
platform: 'linkedin',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: { organizationUrn: 'urn:li:organization:222222222' }
}
],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Exciting updates from our organization!",
platforms=[
{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {"organizationUrn": "urn:li:organization:111111111"}
},
{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {"organizationUrn": "urn:li:organization:222222222"}
}
],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Exciting updates from our organization!",
"platforms": [
{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"organizationUrn": "urn:li:organization:111111111"
}
},
{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"organizationUrn": "urn:li:organization:222222222"
}
}
],
"publishNow": true
}'The organizationUrn format is urn:li:organization: followed by the organization ID.
First Comment
Put external links in the first comment to avoid LinkedIn's link suppression algorithm:
const { post } = await zernio.posts.createPost({
content: 'We just published our guide to API design patterns.\n\nLink in the first comment.',
platforms: [{
platform: 'linkedin',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
firstComment: 'Read the full guide here: https://example.com/api-guide'
}
}],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="We just published our guide to API design patterns.\n\nLink in the first comment.",
platforms=[{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"firstComment": "Read the full guide here: https://example.com/api-guide"
}
}],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "We just published our guide to API design patterns.\n\nLink in the first comment.",
"platforms": [{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"firstComment": "Read the full guide here: https://example.com/api-guide"
}
}],
"publishNow": true
}'Disable Link Preview
When posting text with URLs and no media, LinkedIn auto-generates a link preview card. To suppress it:
const { post } = await zernio.posts.createPost({
content: 'Check out our latest blog post! https://example.com/blog/new-post',
platforms: [{
platform: 'linkedin',
accountId: 'YOUR_ACCOUNT_ID',
platformSpecificData: {
disableLinkPreview: true
}
}],
publishNow: true
});
console.log('Posted to LinkedIn!', post._id);result = client.posts.create(
content="Check out our latest blog post! https://example.com/blog/new-post",
platforms=[{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"disableLinkPreview": True
}
}],
publish_now=True
)
post = result.post
print(f"Posted to LinkedIn! {post['_id']}")curl -X POST https://zernio.com/api/v1/posts \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Check out our latest blog post! https://example.com/blog/new-post",
"platforms": [{
"platform": "linkedin",
"accountId": "YOUR_ACCOUNT_ID",
"platformSpecificData": {
"disableLinkPreview": true
}
}],
"publishNow": true
}'Media URL Requirements
These do not work as media URLs:
- Google Drive -- returns an HTML download page, not the file
- Dropbox -- returns an HTML preview page
- OneDrive / SharePoint -- returns HTML
- iCloud -- returns HTML
Test your URL in an incognito browser window. If you see a webpage instead of the raw image or video, it will not work.
Media URLs must be:
- Publicly accessible (no authentication required)
- Returning actual media bytes with the correct
Content-Typeheader - Not behind redirects that resolve to HTML pages
- Hosted on a fast, reliable CDN
Supabase URLs: Zernio auto-proxies Supabase storage URLs, so they work without additional configuration.
Analytics
Requires Analytics add-on
Available metrics via the Analytics API:
| Metric | Available |
|---|---|
| Impressions | ✅ |
| Reach | ✅ |
| Likes | ✅ |
| Comments | ✅ |
| Shares | ✅ |
| Clicks | ✅ |
| Views | ✅ (video posts only) |
LinkedIn also provides dedicated analytics endpoints for deeper insights:
- Aggregate Analytics -- Organization-level totals or daily time series across all posts
- Post Analytics -- Per-post metrics by URN
- Post Reactions -- Individual reactions with reactor profiles (organization accounts only)
const analytics = await zernio.analytics.getAnalytics({
platform: 'linkedin',
fromDate: '2024-01-01',
toDate: '2024-01-31'
});
console.log(analytics.posts);analytics = client.analytics.get(
platform="linkedin",
from_date="2024-01-01",
to_date="2024-01-31"
)
print(analytics["posts"])curl "https://zernio.com/api/v1/analytics?platform=linkedin&fromDate=2024-01-01&toDate=2024-01-31" \
-H "Authorization: Bearer YOUR_API_KEY"What You Can't Do
These features are not available through LinkedIn's API:
- Publish long-form articles (linkedin.com/article/new/)
- Create polls
- Create events
- Send InMail or DMs
- Create newsletters
- Boost or promote posts
- Add reactions to other posts
- Create hashtag-following or tag connections
- Mix media types (images + videos or images + documents in the same post)
- Post GIFs as images (GIFs are converted to video and count as video)
Common Errors
LinkedIn has a 9.5% failure rate across Zernio's platform (8,082 failures out of 85,512 attempts). Here are the most frequent errors and how to fix them:
| Error | What it means | How to fix |
|---|---|---|
| "Content is a duplicate of urn:li:share:XXXX" (422) | Identical or very similar content was already posted | Modify the text meaningfully. LinkedIn's duplicate detection is strict -- even minor rephrasing may not be enough. |
| "Publishing failed during preflight checks" | Rate limiting or validation caught an issue before publishing | Space posts further apart. Check account health in the dashboard. |
| "Publishing failed due to max retries reached" | All 3 retry attempts failed | Temporary issue. Retry manually or check LinkedIn's status page. |
| Token expired | OAuth access token has expired or been revoked | Reconnect the LinkedIn account. Subscribe to the account.disconnected webhook to catch this proactively. |
| "Cannot mix media types" | Post contains images + videos or images + documents | Use only one media type per post. GIFs count as video. |
| Video processing failed | Codec, duration, or aspect ratio is out of spec | Ensure codec is H.264, duration is within limits (10 min personal / 30 min company), and aspect ratio is between 1:2.4 and 2.4:1. |
| Link preview showing wrong image | Open Graph meta tags on the URL are incorrect or missing | Update the og:image tag on your website. LinkedIn caches previews -- use the LinkedIn Post Inspector to refresh. |
Inbox
Requires Inbox add-on — Build: +$10/mo · Accelerate: +$50/unit · Unlimited: +$1,000/mo
LinkedIn supports comments only (no DMs via API).
Comments
| Feature | Supported |
|---|---|
| List comments on posts | ✅ |
| Reply to comments | ✅ |
| Delete comments | ✅ |
| Like comments | ❌ (API restricted) |
Limitations
- No DMs - LinkedIn's messaging API is not available for third-party apps
- Organization accounts only - Comments require an organization (company page) account type
- No comment likes - Liking/reacting to comments via API is restricted. However, you can read post reactions via
GET /v1/accounts/{accountId}/linkedin-post-reactions(organization accounts only).
See Comments API Reference for endpoint details.
Related Endpoints
- Connect LinkedIn Account - OAuth flow
- Create Post - Post creation and scheduling
- Upload Media - Image and video uploads
- LinkedIn Organizations - List company pages
- LinkedIn Mentions - Track brand mentions
- LinkedIn Aggregate Analytics - Organization-level analytics
- LinkedIn Post Analytics - Post-level performance metrics
- LinkedIn Post Reactions - Who reacted to a post (organization accounts)
- Comments - Inbox API