How to Post to LinkedIn API (The Easy Way)
LinkedIn's API is notoriously complex. Here's how to skip the OAuth headaches and post to LinkedIn programmatically in a single API call.

LinkedIn's API is one of the most developer-hostile in the industry. OAuth 2.0 setup, a LinkedIn app that needs product access approval, three separate endpoints to compose a single post, and documentation that reads like it was written by a compliance lawyer.
Key takeaways
- LinkedIn's native API needs a LinkedIn app, approved product access, and OAuth 2.0 before you can post.
- With the OmniSocials API you connect LinkedIn once in the dashboard and post with one API key, using the linkedin channel for a profile or linkedin_page for a Company Page.
- Add a future scheduled_at timestamp to schedule a post, or leave it out to save a draft.
- The OmniSocials API allows 100 requests per minute per key and sends signed webhooks when a post publishes or fails.
- OmniSocials costs $10 per seat a month billed yearly, while Ayrshare's cheapest plan is $149 a month (checked October 18, 2026).
On this page
- Key takeaways
- What Does It Take to Post to LinkedIn's Native API?
- How to Post to LinkedIn Using the OmniSocials API
- What is the OmniSocials API?
- Step 1: Get Your API Key
- Step 2: Make the API Call
- JavaScript
- Python
- Step 3: Post with an Image
- JavaScript
- Python
- Step 4: Handle the Response
- Post to LinkedIn and Other Platforms at Once
- How to Use the LinkedIn API with Python
- OmniSocials API vs. LinkedIn Native API
- Common Pitfalls
- 1. Passing a file path to mediaurls
- 2. Scheduling a time in the past
- 3. LinkedIn account not connected
- 4. Rate limit errors (429)
- 5. Expecting instant publish confirmation
- Frequently Asked Questions
- Sources
Most developers waste a full day just getting authentication working.
There's a faster path. The OmniSocials API wraps LinkedIn's entire API surface into a single authenticated endpoint. One request, one API key, no app review process. Here's how it works.
What Does It Take to Post to LinkedIn's Native API?
Before showing the easy way, it's worth understanding why the native approach is so painful.
LinkedIn's native posting API requires:
- Creating a LinkedIn app in their developer portal
- Requesting product access for the Share on LinkedIn or UGC Posts product (manual review, can take days)
- Implementing OAuth 2.0 with scopes like
w_member_social - Exchanging and storing tokens (access tokens expire; refresh tokens are limited)
- Making a POST to
/v2/ugcPostswith a heavily nested JSON payload
Here's what a minimal LinkedIn UGC post payload looks like:
{
"author": "urn:li:person:{personId}",
"lifecycleState": "PUBLISHED",
"specificContent": {
"com.linkedin.ugc.ShareContent": {
"shareCommentary": {
"text": "Hello, LinkedIn."
},
"shareMediaCategory": "NONE"
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "PUBLIC"
}
}
That payload is just for a plain text post. Add an image and you're looking at a separate media upload step with its own endpoint, followed by registering the asset, then referencing it in your post request.
It's three API calls to post one image to LinkedIn. Every time.
How to Post to LinkedIn Using the OmniSocials API
What is the OmniSocials API?
The OmniSocials API is a unified social media publishing API that covers 13 platforms, including LinkedIn, Instagram, TikTok, X, Bluesky, and more. You connect your accounts once through the OmniSocials dashboard, and all posting goes through a single endpoint with a single API key. No OAuth per platform. No app reviews. No token management.
At $10 per seat a month (billed yearly), it's also significantly cheaper than alternatives like Ayrshare, whose cheapest plan is $149/mo, or $129/mo billed yearly (prices checked October 18, 2026).
Step 1: Get Your API Key
Sign up at omnisocials.com and start a free 14-day trial.
Once you're in:
- Connect your LinkedIn profile or Company Page in the dashboard (takes about 30 seconds, standard OAuth flow, done once)
- Go to Settings > API
- Click Create API Key and copy the key. It starts with
omsk_live_and is shown once. Store it asOMNISOCIALS_API_KEY.
That's it. OmniSocials handles the LinkedIn app layer. You don't need to register anything with LinkedIn directly.
[Screenshot: OmniSocials Settings > API page showing API key generation and connected LinkedIn account]
Step 2: Make the API Call
With your key in hand, posting to LinkedIn is one call. The examples use the official SDKs for Node.js (npm install @omnisocials/sdk) and Python (pip install omnisocials), which both read OMNISOCIALS_API_KEY from the environment.
JavaScript
import { OmniSocials } from '@omnisocials/sdk';
const client = new OmniSocials(); // reads OMNISOCIALS_API_KEY
const { data: post } = await client.posts.create({
content: 'Just shipped a new feature. Here is what changed and why.',
channels: ['linkedin'],
scheduled_at: '2027-03-02T09:00:00Z',
});
console.log(post.id, post.status); // "1019" "scheduled"
Python
from omnisocials import OmniSocials
client = OmniSocials() # reads OMNISOCIALS_API_KEY
post = client.posts.create(
content="Just shipped a new feature. Here is what changed and why.",
channels=["linkedin"],
scheduled_at="2027-03-02T09:00:00Z",
)
print(post["data"]["id"]) # 1019
print(post["data"]["status"]) # scheduled
linkedin posts to your personal profile. Use linkedin_page for a Company Page. Leave out scheduled_at and the post is saved as a draft; to publish immediately, call createAndPublish (Node) or create_and_publish (Python) with the same arguments.
Step 3: Post with an Image
Posting an image to LinkedIn natively requires uploading the asset to LinkedIn's media API first, registering it, then referencing it in the post. With OmniSocials, you pass the image URL directly in media_urls.
JavaScript
const { data: post } = await client.posts.create({
content: 'Q1 results are in. Sharing our key metrics below.',
channels: ['linkedin'],
media_urls: ['https://yourcdn.com/q1-results.jpg'],
scheduled_at: '2027-03-02T09:00:00Z',
});
Python
post = client.posts.create(
content="Q1 results are in. Sharing our key metrics below.",
channels=["linkedin"],
media_urls=["https://yourcdn.com/q1-results.jpg"],
scheduled_at="2027-03-02T09:00:00Z",
)
OmniSocials downloads the file and handles the upload and registration on LinkedIn's end. One request on your side. A PDF URL works too: it publishes as a swipeable LinkedIn document.
Step 4: Handle the Response
The OmniSocials API returns the same JSON structure regardless of which platforms you post to. After the post goes live, it looks like this (trimmed):
{
"data": {
"id": "1019",
"status": "published",
"type": "post",
"content": { "default": "Q1 results are in. Sharing our key metrics below." },
"schedule_at": "2027-03-02T09:00:00.000Z",
"published_urls": {
"linkedin": "https://www.linkedin.com/feed/update/urn:li:share:..."
},
"errors": null
}
}
Status values you'll see:
draft: saved, not scheduledscheduled: waiting for itsscheduled_attimeposting: being published right nowpublished: live on LinkedIn, with the link inpublished_urlsfailedorwarning: every platform, or some platforms, failed. The reason is inerrors(usually an expired connection or a content policy issue).
To check on a post later, fetch it by id:
const { data: latest } = await client.posts.get('1019');
console.log(latest.status, latest.published_urls.linkedin);
For real-time updates, subscribe to the post.published and post.failed webhooks (see our webhooks guide).
Post to LinkedIn and Other Platforms at Once
This is where the OmniSocials API earns its keep for teams managing multiple channels. Add more platforms to channels and OmniSocials handles the cross-posting.
await client.posts.create({
content: 'Just published a new article. Link in the first comment.',
channels: ['linkedin', 'instagram', 'bluesky', 'x'],
media_urls: ['https://yourcdn.com/article-cover.jpg'], // Instagram needs media
scheduled_at: '2027-03-02T08:00:00Z',
});
Replicating this natively would take four separate integrations. Here it's four strings in an array.
How to Use the LinkedIn API with Python
Steps 2 and 3 show single Python calls. Here's a complete script to copy. It posts a PDF to a Company Page as a swipeable document, adds the link as the first comment, and prints the result. It uses the official OmniSocials Python SDK: pip install omnisocials, Python 3.9 or newer.
from omnisocials import OmniSocials, ValidationError
client = OmniSocials() # reads OMNISOCIALS_API_KEY
try:
post = client.posts.create(
content="Our Q1 report in 8 slides. Swipe through for the numbers.",
channels=["linkedin_page"],
media_urls=["https://yourcdn.com/q1-report.pdf"],
linkedin_page={"first_comment": "Full report: https://yourcdn.com/q1"},
scheduled_at="2027-03-02T09:00:00Z",
)
print(post["data"]["id"], post["data"]["status"]) # 1019 scheduled
except ValidationError as err:
# platform_not_connected: no Company Page in this workspace
print(err.code, err.message)
- The PDF becomes a document. OmniSocials turns its pages into slides, and LinkedIn shows them as a swipeable document.
- Posting as yourself? Use
channels=["linkedin"]andlinkedin={"first_comment": ...}for your personal profile. - Text or image post: drop
media_urlsfor a text post, or pass a JPG or PNG URL instead of the PDF.
Once the post is live, client.posts.get(post_id)["data"]["published_urls"] holds the LinkedIn link.
OmniSocials API vs. LinkedIn Native API
| OmniSocials API | LinkedIn Native API | |
|---|---|---|
| Auth setup | OmniSocials API: One API key | LinkedIn Native API: OAuth 2.0 per app |
| App review required | OmniSocials API: No | LinkedIn Native API: Yes |
| Text post | OmniSocials API: 1 API call | LinkedIn Native API: 1 API call |
| Image post | OmniSocials API: 1 API call | LinkedIn Native API: 3 API calls |
| Cross-platform posting | OmniSocials API: Yes (13 platforms) | LinkedIn Native API: LinkedIn only |
| Scheduling | OmniSocials API: Built-in | LinkedIn Native API: Manual (you build it) |
| Token management | OmniSocials API: Handled for you | LinkedIn Native API: Your responsibility |
| Price | OmniSocials API: $10 per seat/mo (billed yearly) | LinkedIn Native API: Free (LinkedIn tier) |
Common Pitfalls
1. Passing a file path to media_urls
media_urls expects publicly accessible URLs, not local paths. If you're working with files on disk, upload them first and pass the returned id in media_ids:
const { data: image } = await client.media.upload({
file: './q1-results.jpg', // a path, Buffer, or Blob, up to 100 MB
});
await client.posts.create({
content: 'Q1 results are in.',
channels: ['linkedin'],
media_ids: [image.id],
scheduled_at: '2027-03-02T09:00:00Z',
});
2. Scheduling a time in the past
If scheduled_at is earlier than the current time, the API returns a 400 validation error. Always use ISO 8601 format and include the timezone (a trailing Z means UTC).
3. LinkedIn account not connected
If you get a 400 with the code platform_not_connected, your LinkedIn account isn't connected in the workspace that owns your API key. Connect it in the OmniSocials dashboard. This is a one-time step. Also check that you picked the right channel: linkedin for a profile, linkedin_page for a Company Page.
4. Rate limit errors (429)
The OmniSocials API allows 100 requests per minute per API key. The SDKs retry a 429 automatically after the Retry-After delay. If you call the REST API directly, wait for the Retry-After header value before retrying, and spread bulk jobs over time.
5. Expecting instant publish confirmation
A post marked posting or scheduled hasn't confirmed yet. Publishing happens asynchronously, so use webhooks or poll GET /v1/posts/:id rather than assuming the post went live.
Frequently Asked Questions
Can you post to LinkedIn via API?
Yes. LinkedIn has a native API (the UGC Posts and Share APIs), but it requires OAuth 2.0, a verified LinkedIn app, and several API calls per post. A simpler option is the OmniSocials API, which wraps LinkedIn's API into a single authenticated request using one API key, with no app review process.
Does LinkedIn API require app review?
Yes. LinkedIn's native API requires requesting product access through their developer portal, which involves a manual review that can take days or weeks. Using the OmniSocials API bypasses this entirely. You connect your LinkedIn account in the OmniSocials dashboard once, and OmniSocials handles the verified app layer for you.
How do I schedule a LinkedIn post via API?
With the OmniSocials API, add a scheduled_at field (a future ISO 8601 timestamp) to your POST /v1/posts request. Example: "scheduled_at": "2027-03-02T09:00:00Z". OmniSocials queues the post and publishes it automatically at the specified UTC time.
What is the LinkedIn API rate limit?
LinkedIn's native API caps the Share API at around 100 calls per day per user token. The OmniSocials API allows up to 100 requests per minute per API key and handles LinkedIn's underlying rate limits for you.
Can I post to LinkedIn and other platforms in one API call?
Not with LinkedIn's native API. With the OmniSocials API, you can post to LinkedIn, Instagram, Bluesky, X, TikTok, and 7 other platforms in a single request by listing them in the channels array.
How do I use the LinkedIn API with Python?
The native route is a LinkedIn app with OAuth 2.0 and approved product access, then a POST to the UGC Posts API with requests. The shorter route is the OmniSocials Python SDK: pip install omnisocials, connect LinkedIn once in the dashboard, set OMNISOCIALS_API_KEY, and call client.posts.create() with channels=["linkedin"] for a profile or ["linkedin_page"] for a Company Page.
Sources
- LinkedIn Developer Documentation: UGC Posts API: Official LinkedIn UGC Posts API reference covering endpoints, auth, and payload structure
- LinkedIn API Rate Limits: Official LinkedIn rate limit documentation for API calls
- OAuth 2.0 Authorization Code Flow (LinkedIn): LinkedIn's official OAuth 2.0 implementation guide
- OmniSocials API Documentation: Full reference for OmniSocials API endpoints, authentication, and webhooks
Try OmniSocials for 14 days
Plan, schedule and answer on 13 platforms from one calendar, or let your AI agent do it. The first charge comes when the trial ends.


