Platforms
Publish text, article links, images, video and PDF documents to LinkedIn profiles and Company Pages.
Overview
The linkedin platform publishes with LinkedIn's versioned REST Posts API, to a personal profile or (with extra LinkedIn access) to Company Pages you administer. You can post:
- Text posts
- Link (article) posts with your own title and description
- 1–20 images
- 1 video
- A PDF document (LinkedIn is the only platform that accepts
"type": "document"media) - Company Page @mentions
Connect the account
In Integrations, choose LinkedIn and approve access.
App setup (self-hosted)
- In the LinkedIn Developer Portal, open your app's Auth tab and add the redirect URL
https://social-publish-kappa.vercel.app/api/integrations/linkedin/callback(override withLINKEDIN_REDIRECT_URI). - On the Products tab, add Sign In with LinkedIn using OpenID Connect and Share on LinkedIn. Both are self-serve.
- Set
LINKEDIN_CLIENT_IDandLINKEDIN_CLIENT_SECRET.
Scopes requested by default: openid, profile, w_member_social.
| Flag | Adds | Enables |
|---|---|---|
LINKEDIN_ORG_SCOPES=true | w_organization_social, r_organization_social, rw_organization_admin | Posting to Company Pages you administer, and Page post analytics |
LINKEDIN_MEMBER_ANALYTICS_SCOPES=true | r_member_postAnalytics | Impressions, clicks and saves on personal posts |
LINKEDIN_API_VERSION=YYYYMM | — | Overrides the LinkedIn API version sent with each request |
Only turn these flags on once LinkedIn has granted the matching product to the app behind LINKEDIN_CLIENT_ID. Requesting a scope the app doesn't have makes the whole consent screen fail with unauthorized_scope_error. Company Page posting needs the Community Management API product, which LinkedIn grants only after review and only to an app without other products, so it is usually a separate app. Members must reconnect after a flag is turned on.
LinkedIn access tokens last 60 days. Unless LinkedIn has issued your app refresh tokens, an expired token means the account must be reconnected.
Post types & media rules
| Rule | Limit |
|---|---|
| Text | 3,000 characters |
| Images | Up to 20; JPG, PNG or GIF; up to 50 MB each |
| Video | 1, MP4 only, up to 500 MB |
| Images and video | Can't be combined |
| Document | 1 PDF, up to 100 MB (LinkedIn also limits it to 300 pages); no other media and no link |
| Document title | Required: media[].title or options.documentTitle |
| Link post | articleUrl is only used when no media is attached |
| Visibility | CONNECTIONS is only available for personal profiles |
| Mentions | Up to 20 Company Page mentions; each text must appear exactly in the post content |
LinkedIn does not fetch the linked page for article posts, so set articleTitle (it defaults to the site name) and articleDescription yourself.
Options
| Option | Type | Required | Default | Description |
|---|---|---|---|---|
visibility | PUBLIC \ | CONNECTIONS | No | "PUBLIC" |
disableReshare | boolean | No | false | Disable resharing |
articleUrl | string (URL) | No | Link URL. Creates a link (article) post. Ignored when images or a video are attached. | |
articleTitle | string | No | Link title. Only used with a Link URL. LinkedIn does not fetch the page, so set the title yourself (defaults to the site name). | |
articleDescription | string | No | Link description. Only used with a Link URL. | |
documentTitle | string | No | Document title. Title shown on the PDF card (required when posting a PDF) | |
mentions | object[] | No | Mentions. Tag a company page. LinkedIn only supports mentioning company pages, not personal profiles. "Text to match" must appear exactly in your post content — it becomes the clickable @mention. Items: name, organization, text (max 20). | |
For mentions, organization accepts an organization URN (urn:li:organization:123), a numeric ID or a vanity name. The first occurrence of text in the post becomes the clickable mention; to mention the same text twice, repeat it in the post and add two mentions. |
Examples
PDF document post
curl -X POST https://social-publish-api.onrender.com/v1/posts \
-H "x-access-key: $RELAYCAST_API_KEY" \
-H "content-type: application/json" \
-d '{
"content": "Our 2026 hiring playbook, free to download.",
"media": [{
"url": "https://cdn.example.com/hiring-playbook.pdf",
"type": "document",
"title": "Hiring Playbook 2026"
}],
"targets": [{
"accountId": "3c8d1e2f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"options": { "visibility": "PUBLIC" }
}],
"publishNow": true
}'const res = await fetch("https://social-publish-api.onrender.com/v1/posts", {
method: "POST",
headers: {
"x-access-key": process.env.RELAYCAST_API_KEY!,
"content-type": "application/json",
},
body: JSON.stringify({
content: "Our 2026 hiring playbook, free to download.",
media: [
{ url: "https://cdn.example.com/hiring-playbook.pdf", type: "document", title: "Hiring Playbook 2026" },
],
targets: [{ accountId: "3c8d1e2f-5a6b-4c7d-8e9f-0a1b2c3d4e5f", options: { visibility: "PUBLIC" } }],
publishNow: true,
}),
});
const { data } = await res.json();import os, requests
res = requests.post(
"https://social-publish-api.onrender.com/v1/posts",
headers={"x-access-key": os.environ["RELAYCAST_API_KEY"]},
json={
"content": "Our 2026 hiring playbook, free to download.",
"media": [{
"url": "https://cdn.example.com/hiring-playbook.pdf",
"type": "document",
"title": "Hiring Playbook 2026",
}],
"targets": [{
"accountId": "3c8d1e2f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"options": {"visibility": "PUBLIC"},
}],
"publishNow": True,
},
)
data = res.json()["data"]A document can only go to LinkedIn accounts. If the same post also targets other platforms, they fail validation; send the PDF in a separate post.
Article link with a Company Page mention
{
"content": "Thanks to Microsoft for hosting our meetup. Recap on the blog.",
"targets": [{
"accountId": "3c8d1e2f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"options": {
"articleUrl": "https://example.com/blog/meetup-recap",
"articleTitle": "Meetup recap: October 2026",
"articleDescription": "Talks, slides and photos from the evening.",
"mentions": [{ "name": "Microsoft", "organization": "microsoft", "text": "Microsoft" }],
"disableReshare": false
}
}],
"scheduledFor": "2026-11-04T08:00:00Z"
}Analytics & comments
- Personal posts: likes and comments. Impressions, reshares, link clicks and saves need
r_member_postAnalytics(LINKEDIN_MEMBER_ANALYTICS_SCOPES=true). - Company Page posts: impressions, clicks, likes, comments and shares through the Community Management API.
Comments and messaging are not supported for LinkedIn.
Limitations & common errors
| Error | Cause |
|---|---|
LinkedIn posts allow 3000 characters | Text is too long. |
LinkedIn posts can have images or one video, not both | Mixed images and video. |
LinkedIn document posts can't include images or video | A PDF was combined with other media. |
LinkedIn document posts can't include a link | articleUrl set on a document post. |
Add a document title | No media[].title or documentTitle for a PDF. |
"…" must appear exactly in the post content | A mention's text isn't in the post. |
| Target fails: connections-only visibility | visibility: "CONNECTIONS" on a Company Page account. |
| Target fails: only MP4 / JPG, PNG and GIF | Unsupported media file type. |
| Target fails: duplicate post (HTTP 422) | LinkedIn rejected identical content. |
Consent screen shows unauthorized_scope_error | A LinkedIn flag is on without the product approved for the app. |
Account becomes reconnect_required | The 60-day token expired, or a 403 points at a missing product/permission. |
This page is also available as Markdown.