LinkedIn API for posting and scheduling
One authenticated POST publishes to a LinkedIn profile or company page. PostMCP owns the OAuth dance, the image upload handshake and the versioned LinkedIn REST calls underneath.
- Endpoint
- POST /api/tools/create_post
- Platform value
- "linkedin"
- Auth
- x-api-key or Bearer token
- Upstream
- LinkedIn REST /v2/posts
What the LinkedIn API gives you
Publishing to LinkedIn directly means registering a developer app, getting w_member_social approved, exchanging an authorization code, building a urn:li:person or urn:li:organization author URN, and running a three-request image upload before you can attach a single picture. The LinkedIn API surface is versioned, protocol-header sensitive, and unforgiving about author identity.
The PostMCP LinkedIn API collapses that into one endpoint. You send content, a schedule and an optional media URL; the engine resolves the right author URN for each connected account, uploads media through LinkedIn's initializeUpload flow, waits for asset processing, then posts to /v2/posts with the correct X-Restli-Protocol-Version header.
Personal profile posts
Text and image posts published as the authenticated member, authored against urn:li:person:{id}.
Company page posts
Connected organization pages publish under urn:li:organization:{id} with no change to your request body.
Native image attachments
Pass any public mediaUrl. PostMCP fetches the bytes and runs LinkedIn's three-step upload so the image renders natively, not as a link preview.
Scheduled publication
Queue a post for a future date and time, then edit, reschedule, force-publish or delete it before it goes out.
Per-profile targeting
Name the exact profiles in targetAccounts and only those receive the post. Passing platforms: ["linkedin"] instead is the opt-in fan-out to every connected LinkedIn account.
Cross-posting in one call
Add more values to platforms and the same copy lands on X, Facebook, Instagram, Threads and Bluesky simultaneously.
Common uses
- Publish a changelog to a company page every time a release tag lands.
- Let a Claude or Cursor agent draft and schedule a founder post without leaving the editor.
- Mirror a blog RSS feed into LinkedIn with a native image card.
- Queue a week of recruiting posts across several administered pages in one script.
Post to LinkedIn in three steps
Connect the account once, grab an API key, then send a single request. The same body works from a shell, a server, or an AI agent.
- 1
Connect your LinkedIn account
Open the dashboard, choose LinkedIn and complete the hosted connect flow. Credentials are encrypted into the user vault and never returned to your client.
- 2
Create an API key
Generate a key from the dashboard. Send it as
x-api-key, as anAuthorization: Bearerheader, or as anapikeyquery parameter on the MCP transport. - 3
Send your first post
POST to
/api/tools/create_postwithplatforms: ["linkedin"]. SetpublishImmediatelyto broadcast now, or supplyscheduleDateandscheduleTimeto queue it.
curl -X POST "https://api.postmcpai.com/api/tools/create_post" \
-H "Content-Type: application/json" \
-H "x-api-key: $POSTMCPAI_API_KEY" \
-d '{"content":"Shipping something new today. Built with PostMCP AI.","platforms":["linkedin"],"publishImmediately":true}'{
"success": true,
"message": "Post created and queued successfully",
"post": {
"id": "66a50c89e4b019a2b72f",
"content": "Shipping something new today. Built with PostMCP AI.",
"platforms": [
"linkedin"
],
"status": "published"
}
}LinkedIn API endpoints
Every endpoint is a POST against the base URL https://api.postmcpai.com. The same seven operations cover all connected networks — set the platform value to "linkedin" to target LinkedIn.
| Operation | Endpoint | What it does |
|---|---|---|
| preflight_post | POST/api/tools/preflight_post | Dry-run copy against limits, targets and credits before publishing. |
| create_post | POST/api/tools/create_post | Schedule a post or broadcast it immediately. |
| publish_post_now | POST/api/tools/publish_post_now | Force a queued post out ahead of its slot, or retry the profiles that failed. |
| list_posts | POST/api/tools/list_posts | Read the queue — scheduled, published, draft and failed — with counts. |
| get_post | POST/api/tools/get_post | Read one post, with per-profile delivery state and live URLs. |
| get_post_analytics | POST/api/tools/get_post_analytics | Read how a post did: views, likes, comments and shares per profile. |
| get_profile_analytics | POST/api/tools/get_profile_analytics | Read a profile’s followers, post count and views from its network. |
| update_post | POST/api/tools/update_post | Edit copy, targets, schedule or status before publication. |
| reschedule_post | POST/api/tools/reschedule_post | Move a post to another slot, keeping its copy and targets. |
| reset_stuck_post | POST/api/tools/reset_stuck_post | Release a post left stuck mid-publish so it can be retried. |
| delete_post | POST/api/tools/delete_post | Remove a scheduled or draft post from the queue. |
| get_connected_accounts | POST/api/tools/get_connected_accounts | List connected profiles, handles and page IDs per platform. |
| get_account_health | POST/api/tools/get_account_health | Find connections whose token expired or is about to. |
| generate_image | POST/api/tools/generate_image | Generate a post image and get back a hosted URL for mediaUrl. |
| list_workspaces | POST/api/tools/list_workspaces | List the workspaces on this key, with the id to scope other calls to. |
| get_user_info | POST/api/tools/get_user_info | Read plan tier and credit balance. |
create_post parameters
| Field | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Text body of the post. Truncation rules are enforced by the destination network, not by PostMCP. |
| targetAccounts | array[object] | Yes | The profiles that receive the post. Each entry takes platform and profileId (from get_connected_accounts). Only the profiles listed here are posted to. |
| platforms | array[string] | Optional | Shorthand for whole networks — linkedin, twitter, facebook, instagram, threads, bluesky, youtube. Each one expands to every connected profile on it, so prefer targetAccounts unless you mean that fan-out. Optional when targetAccounts is given. |
| publishImmediately | boolean | Optional | When true the post is broadcast on receipt. Defaults to false, which queues it. |
| scheduleDate | string | Optional | Publication date as YYYY-MM-DD. Required when publishImmediately is false. |
| scheduleTime | string | Optional | Publication time as HH:MM on a 24-hour clock. Required when publishImmediately is false. |
| timezone | string | Optional | IANA zone the schedule above is written in, e.g. Asia/Kolkata. Omit it and the wall-clock slot resolves as UTC, which is rarely what "10am" meant. |
| mediaUrl | string | Optional | Publicly reachable image or video URL. PostMCP fetches it and re-uploads it in the format the network expects. Required, and must be a video, when the post targets YouTube. |
| workspaceId | string | Optional | Workspace to post from, taken from list_workspaces. Omitted, the call resolves to the default workspace on the key. |
LinkedIn OAuth and API keys
Two layers of auth sit under every request: the LinkedIn credential you grant once during connect, and the PostMCP API key your code sends on each call.
Open the connect URL
Send the member to /connect/linkedin with their PostMCP session token. PostMCP signs a state JWT that carries the user and project ID.
LinkedIn consent screen
The member approves the member and organization scopes on linkedin.com/oauth/v2/authorization.
Callback and vault storage
LinkedIn redirects back with a code. PostMCP exchanges it for an access token, encrypts it and stores it in the user vault — the token never reaches your client.
Publish with your API key
From then on you authenticate with your own PostMCP API key. Rotate it from the dashboard without touching the LinkedIn connection.
Scopes requested from LinkedIn
| Scope | Why it is needed |
|---|---|
| openid | Identifies the member completing the OAuth flow. |
| profile | Reads the member name and profile ID used to build the author URN. |
| Matches the connected LinkedIn identity to your PostMCP workspace. | |
| w_member_social | Creates posts, comments and reactions as the member. |
| w_organization_social | Publishes posts on behalf of a company page. |
| rw_organization_admin | Lists the pages the member administers so they can be connected. |
Sending your API key
x-api-key: pmcp_sec_…Authorization: Bearer pmcp_sec_…/mcp?apikey=pmcp_sec_…How PostMCP publishes to LinkedIn
One request from you becomes this sequence server-side. Knowing the shape helps when you are debugging a failed broadcast.
- 1
Resolve the author URN
Organization accounts become
urn:li:organization:{profileId}; members becomeurn:li:person:{profileId}. - 2
Fetch the media
If
mediaUrlis set the engine downloads it into a buffer and fails loudly if the URL is not publicly reachable. - 3
Initialize the upload
initializeUploadis called with the author URN as owner, returning an upload URL and the image URN. - 4
PUT the binary and wait
Bytes are uploaded, then the engine pauses ~2.5s so LinkedIn finishes asset processing before the share references it.
- 5
Create the share
A single POST to
/v2/postscarries the commentary, lifecycle state PUBLISHED and the image URN when present. - 6
Record the result
The returned post ID (or
x-restli-idheader) is written back to the post record as a per-platform status.
Upstream LinkedIn calls
| Method | Endpoint | Purpose |
|---|---|---|
| POST | https://api.linkedin.com/v2/images?action=initializeUpload | Reserves an image asset and returns a signed upload URL plus an image URN. |
| PUT | {uploadUrl} | Streams the image bytes as application/octet-stream. |
| POST | https://api.linkedin.com/v2/posts | Creates the share with commentary, visibility PUBLIC and MAIN_FEED distribution. |
Direct LinkedIn API vs PostMCP
| Aspect | Calling LinkedIn directly | With PostMCP |
|---|---|---|
| Getting started | Developer app, product request, scope approval | One OAuth click, then an API key |
| Author identity | Build person or organization URNs yourself | Resolved per connected account automatically |
| Image posts | Three sequential calls plus a processing wait | One `mediaUrl` field |
| Multi-image posts | Upload each image, then the `multiImage` content shape | One `mediaUrls` array, up to 20 images |
| Scheduling | Not offered — you run your own scheduler | Built in, with edit and force-publish |
| Token handling | Your responsibility to store and refresh | Encrypted in the vault, refreshed for you |
LinkedIn limits and supported media
These ceilings are set by LinkedIn, not by PostMCP. Your content field is forwarded unchanged, so the network enforces them rather than silently truncating.
Common LinkedIn API errors
Failures are recorded per platform on the post record, so a multi-network broadcast that partially succeeds tells you exactly which leg failed and why.
| Code | Message | Likely cause | Fix |
|---|---|---|---|
| 401 | Access token for linkedin is missing or invalid | The stored token expired or the account was disconnected on LinkedIn's side. | Reconnect LinkedIn from the dashboard to mint a fresh token. |
| 403 | Not enough permissions to create posts | The member approved sign-in scopes but not w_member_social or w_organization_social. | Re-run the connect flow and accept the posting permissions. |
| 422 | LinkedIn Image Upload Initialization failed | The author URN does not own the asset, or the media URL returned a non-200 response. | Verify the media URL is public and that the page is still administered by the connected member. |
| 429 | Throttle limit reached | LinkedIn applies daily per-member and per-app share quotas. | Spread posts out with scheduling instead of bursting them. |
Post to LinkedIn from an AI agent
The same seven operations are exposed as MCP tools. Point Claude Desktop, Cursor, or any MCP client at the server and your agent can publish to LinkedIn directly.
{
"mcpServers": {
"postmcpai": {
"command": "npx",
"args": ["-y", "@postmcpai/server"],
"env": {
"POSTMCPAI_API_KEY": "pmcp_sec_YOUR_SECRET_KEY",
"POSTMCPAI_API_URL": "https://api.postmcpai.com"
}
}
}
}Prompt the agent directly
With the server connected, natural language is enough — the agent picks the tool and fills the arguments:
“Draft a LinkedIn post about today’s release and schedule it for 9:30am tomorrow.”
LinkedIn API questions
How do I post to the LinkedIn API programmatically?
Send a POST to https://api.postmcpai.com/api/tools/create_post with your API key in the x-api-key header and a JSON body containing content and targetAccounts: [{ platform: "linkedin", profileId: "…" }] — take the profileId from get_connected_accounts. Add publishImmediately: true to broadcast right away, or scheduleDate and scheduleTime to queue it.
Can I post to a LinkedIn company page instead of a personal profile?
Yes. Connect the page during the OAuth flow — rw_organization_admin lists the pages you administer. PostMCP then authors the share against urn:li:organization:{id} automatically. Use targetAccounts to pin a specific page when several are connected.
Does the LinkedIn API support scheduling posts?
LinkedIn's own REST API publishes immediately and has no scheduling primitive. PostMCP adds the queue: posts are stored with a date and time, then broadcast by the engine at the scheduled slot, and remain editable or deletable until they go out.
How are images attached to a LinkedIn post?
Pass a public mediaUrl. PostMCP downloads the file, calls initializeUpload, PUTs the binary to the signed URL, waits for LinkedIn to process the asset, then references the returned image URN in the share so it renders as a native image rather than a link preview.
What is the LinkedIn post character limit?
LinkedIn allows 3,000 characters in the post commentary. PostMCP passes your content through unchanged, so anything longer is rejected by LinkedIn rather than silently truncated.
Do I need my own LinkedIn developer app?
No. PostMCP holds the LinkedIn app registration and the approved products. You connect an account through the hosted OAuth flow and authenticate your own requests with a PostMCP API key.
Other social media APIs
Send one request and PostMCP handles Twitter API v2 for you — PKCE OAuth, the three-step chunked media upload, refresh tokens and the final tweet call.
Read the referencePublish text and photo posts to every Facebook Page you manage from one endpoint. PostMCP resolves page access tokens and calls Graph API v26.0 for you.
Read the referenceInstagram publishing is a two-phase asynchronous flow. PostMCP creates the media container, polls it to FINISHED and publishes it — you send a caption and a media URL.
Read the referenceThreads processes every post asynchronously, even plain text. PostMCP creates the container, polls it to FINISHED and publishes — one call from your side.
Read the referenceBluesky is not OAuth — it is a session against an AT Protocol server. PostMCP refreshes that session, uploads image blobs and writes the feed record for you.
Read the referenceYouTube is the one network here that will not take a URL. It wants the video bytes over a resumable session — PostMCP fetches, uploads and publishes them for you.
Read the referenceStart posting to LinkedIn today
Connect the account, take an API key and send your first request in under five minutes — from a shell, your backend, or an AI agent.
