How to Post to LinkedIn via API
The request flow for publishing to LinkedIn programmatically, from OAuth connection to publish confirmation.
To post to LinkedIn via API: the member authorizes your app through OAuth (PostGate requests openid profile w_member_social — personal profile posting is self-serve, no LinkedIn app review needed), attach media if any, then send one POST /api/posts request with the body, target profile, and options.linkedin, and confirm delivery via polling or webhooks since LinkedIn publishes asynchronously.
Posting to LinkedIn through an API means four things happen in order: a member authorizes your app, you attach media if any, you send the post, and you confirm it actually landed. This walks through all four with PostGate, which sits in front of LinkedIn's own REST API and its OAuth flow so your integration doesn't maintain a LinkedIn app of its own.
1. Connect the LinkedIn account
Start a connection and redirect the member to LinkedIn's consent screen. PostGate requests openid profile w_member_social — enough to identify the member and post, comment, and like on their behalf. Nothing about company pages is requested at this step; personal profile posting is self-serve and needs no LinkedIn app review on your side.
curl -X POST https://postgate.studio/api/profiles/connect \
-H "Authorization: Bearer $POSTGATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platform": "linkedin",
"profile_group_id": "grp_acme123",
"return_url": "https://app.example.com/settings/social"
}'2. Attach media, if any
Pass a public HTTPS URL, a base64 data URL, or a pre-uploaded media ID under the post's media array — PostGate fetches, validates the MIME type, and probes dimensions or duration before handing the asset to LinkedIn. Large or reused files should go through the media endpoint first so validation happens ahead of the scheduled publish, not during it.
3. Send the post
One request carries the body, the target profile, media, and any LinkedIn-specific fields under post.options.linkedin. Include an Idempotency-Key so a dropped connection and a client retry can never produce two posts.
curl -X POST "https://postgate.studio/api/posts?profile_group_id=grp_acme123" \
-H "Authorization: Bearer $POSTGATE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: linkedin-launch-002" \
-d '{
"post": {
"body": "Announcing our Series A.",
"options": {
"linkedin": { "visibility": "PUBLIC", "disable_reshare": false }
}
},
"profiles": ["pro_linkedin456"],
"media": ["https://cdn.example.com/announcement.jpg"]
}'4. Confirm delivery
The response you get back from step 3 is acceptance, not proof of publication — LinkedIn delivery happens asynchronously. Poll GET /api/posts/{id} or, better, subscribe to webhooks for the terminal state of the LinkedIn target: published (with permalink), failed (with a structured, retryable-or-not error code), or skipped.
curl https://postgate.studio/api/posts/post_01JXYZ \
-H "Authorization: Bearer $POSTGATE_API_KEY"5. Handle the errors that are specific to LinkedIn
profile_disconnected means the standard access token expired — LinkedIn typically issues these for roughly 60 days — and the member needs to reconnect. rate_limited means LinkedIn's daily application or per-member throttle was hit; see LinkedIn API Rate Limit. platform_content_rejected usually means the post text or an unsupported media type (WEBP images and non-MP4 video are rejected by LinkedIn, not by PostGate) needs to change.
Frequently asked questions
Do I need LinkedIn app review to post to a personal profile?
No — personal profile posting is self-serve and needs no LinkedIn app review on your side. PostGate requests openid profile w_member_social, enough to identify the member and post, comment, and like on their behalf. Nothing about company pages is requested at that step.
How long do LinkedIn access tokens last?
LinkedIn typically issues standard access tokens for roughly 60 days. When one expires you’ll see profile_disconnected on the target, and the member needs to reconnect the account.
What media formats does LinkedIn reject?
WEBP images and non-MP4 video are rejected by LinkedIn itself, not by PostGate — a platform_content_rejected error usually means the post text or an unsupported media type needs to change. You can pass a public HTTPS URL, a base64 data URL, or a pre-uploaded media ID; PostGate fetches, validates the MIME type, and probes dimensions or duration before handing the asset to LinkedIn.
How do I confirm a LinkedIn post actually published?
The response to the create call is acceptance, not proof of publication — LinkedIn delivery happens asynchronously. Poll GET /api/posts/{id} or, better, subscribe to webhooks for the terminal state of the LinkedIn target: published (with permalink), failed (with a structured, retryable-or-not error code), or skipped.
