Platforms
Publish text, images, video, documents, polls and reposts to LinkedIn profiles and company pages, target page audiences, edit posts and read analytics.
One LinkedIn connection can post as the member's personal profile or as any company page they administer. You can publish text, images, video, PDF and slide documents, polls and reposts, tag people and companies, target page posts at specific audiences, and edit the text after publishing. The platform id is linkedin.
#What you can do
| Capability | Supported | Where |
|---|---|---|
| Publish | Text, up to 20 images, one video, one document, polls, reposts | Create a post |
| Schedule | Yes | Scheduling |
| Edit after publishing | Text, no time limit. Unpublish removes the post. | Edit published posts |
| Mentions | People and companies by profile URL | Mentions |
| Analytics | Post metrics for profiles and pages, page follower and visitor stats, demographics, reactions | Platform insights |
| Comments | Company pages: list, reply, delete. Reactions on comments and posts from either account type. | Comments |
| DMs | No. LinkedIn does not open messaging to third-party apps. | |
| Ads | Through a LinkedIn Ads connection | LinkedIn Ads |
#Connect
Start with GET /v1/connect/linkedin and a profileId. After LinkedIn's consent screen, the user chooses whether this account posts as their personal profile or as one of the company pages they administer. Pozy hosts that choice by default; headless mode lets you build it with List LinkedIn orgs and Select LinkedIn org.
To switch an existing account between personal and page posting later, without another login, call Switch LinkedIn account type.
The two account types behave differently:
| Personal profile | Company page | |
|---|---|---|
| Video length | Up to 10 minutes | Up to 30 minutes |
| Analytics | Posts published through Pozy only, plus saves and sends | Every post, clicks, follower and page-view stats |
| Comments API | Reactions only | Read, reply, delete |
| Audience targeting and geo-restriction | No | Yes |
LinkedIn asks for a broad set of permissions because one connection covers profile posting, pages and ads. Accounts connected before Pozy added the comment and reaction permissions get 403 linkedin_reconnect_required on those calls until they reconnect.
#Post types
A plain request makes a text post. Media in mediaItems makes an image, video or document post. A post carries one media type only.
curl -X POST https://api.pozy.ai/v1/posts \
-H "Authorization: Bearer $POZY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "We cut our onboarding from 14 steps to 4.\n\nThe three things that mattered most are in the comments.",
"platforms": [{
"platform": "linkedin",
"accountId": "6720c1a94f3b2e0018d4a7f5",
"platformSpecificData": {
"firstComment": "Full write-up: https://example.com/blog/onboarding"
}
}],
"publishNow": true
}'const res = await fetch("https://api.pozy.ai/v1/posts", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "We cut our onboarding from 14 steps to 4.\n\nThe three things that mattered most are in the comments.",
platforms: [{
platform: "linkedin",
accountId: "6720c1a94f3b2e0018d4a7f5",
platformSpecificData: { firstComment: "Full write-up: https://example.com/blog/onboarding" },
}],
publishNow: true,
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.post.platforms[0].platformPostUrl);import os, requests
resp = requests.post(
"https://api.pozy.ai/v1/posts",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
json={
"content": "We cut our onboarding from 14 steps to 4.\n\nThe three things that mattered most are in the comments.",
"platforms": [{
"platform": "linkedin",
"accountId": "6720c1a94f3b2e0018d4a7f5",
"platformSpecificData": {"firstComment": "Full write-up: https://example.com/blog/onboarding"},
}],
"publishNow": True,
},
)
print(resp.json()["post"]["platforms"][0]["platformPostUrl"])Putting links in firstComment rather than the post body is a common LinkedIn habit, because posts with links in the text tend to get less reach.
| Post type | How to send it |
|---|---|
| Text | content, up to 3,000 characters. A URL with no media gets a preview card unless disableLinkPreview: true. |
| Images | 1 to 20 images in mediaItems |
| Video | One video. Optional thumbnail on the item (best effort). |
| Document | One PDF, PPT, PPTX, DOC or DOCX as type: "document", shown as a swipeable carousel. Set documentTitle. |
| Poll | poll with a question and 2 to 4 options. No media. |
| Repost | reshareUrl with the post link or URN. No media. |
#Document post
LinkedIn requires a title on documents. Pozy uses documentTitle, then the media item's title, then the filename. The first page is the cover. Password-protected PDFs do not work.
"mediaItems": [{ "type": "document", "url": "https://cdn.example.com/2027-benchmarks.pdf" }],
"platforms": [{
"platform": "linkedin",
"accountId": "6720c1a94f3b2e0018d4a7f5",
"platformSpecificData": { "documentTitle": "2027 hiring benchmarks" }
}]#Poll
A question of 1 to 140 characters, 2 to 4 options of up to 30 characters each, and a duration of ONE_DAY, THREE_DAYS, SEVEN_DAYS (default) or FOURTEEN_DAYS. Polls cannot be edited after publishing and cannot be promoted as ads.
"platformSpecificData": {
"poll": {
"question": "How does your team run standups?",
"options": ["Daily, live", "Async in chat", "We don't"],
"duration": "THREE_DAYS"
}
}#Repost
reshareUrl takes a post link (from "Copy link to post") or a urn:li:share, urn:li:ugcPost or urn:li:groupPost URN. Your content becomes the commentary on top; with no text it is a plain reshare. The repost is always authored by your account with the original embedded. LinkedIn's API cannot produce the one-click repost where the original author stays the author.
#Post to several company pages
List the pages the member administers with List LinkedIn orgs, then repeat the entry with the same accountId and a different organizationUrn (urn:li:organization: plus the id). Entries without organizationUrn go to the account's default.
#Audience targeting and geo-restriction
On company pages, audience limits who sees the post: by country, region, industry, job function, seniority, company size, interface language, degree, field of study or school. Values inside one facet are combined with OR, and facets are combined with AND. LinkedIn rejects the post if the target audience is under 300 members. Find ids with Search targeting options using platform=linkedin.
"platformSpecificData": {
"organizationUrn": "urn:li:organization:84512033",
"audience": {
"countries": ["ES", "DE"],
"jobFunctions": ["urn:li:function:8"],
"seniorities": ["urn:li:seniority:6"],
"staffCountRanges": ["SIZE_51_TO_200", "SIZE_201_TO_500"]
}
}geoRestriction.countries (up to 25 ISO codes) is the simpler form: only followers in those countries see the post. It is merged with audience.countries, and codes LinkedIn cannot map are skipped.
#Platform fields
Schema: LinkedInPlatformData.
| Field | Notes |
|---|---|
organizationUrn |
Company page to post as. |
documentTitle |
Title for document posts. |
firstComment |
Comment posted right after publishing. Mentions in it are posted as plain names. |
disableLinkPreview |
true suppresses the automatic link card. |
poll |
{ question, options, duration }. Not with media or reshareUrl. |
reshareUrl |
Post link or URN to repost. Not with media. |
audience |
Page audience targeting (see above). |
geoRestriction |
{ countries }, pages only. |
#Mentions
Write a mention as a profile or company URL inside @[...] in content or in the LinkedIn entry's customContent:
Thanks to @[https://www.linkedin.com/in/maria-lopez] and the team at @[https://www.linkedin.com/company/acme] for the help.Pozy resolves each URL and publishes LinkedIn's own name as the link text. You can choose the visible text with @[Maria](https://www.linkedin.com/in/maria-lopez), but it must be the person's first, last or full name (or the company's exact name), case-sensitive; anything else is replaced and a warnings entry comes back.
- To resolve ahead of time, call Resolve LinkedIn mention and paste the returned
@[Name](urn:li:person:...)markup, which is published exactly as written. - Looking up a person by URL needs one of your LinkedIn accounts to administer a page. Company lookups do not.
- A post can resolve up to 10 mentions (
linkedin_mentions_limit_exceeded). An unresolvable URL rejects a scheduled or published post withlinkedin_mentions_invalidand details per mention; drafts save and return warnings instead. - Other platforms in the same post get plain text: the vanity name, or your custom text.
#Edit a published post
Edit published post with platform: "linkedin" replaces the text of a live post on a profile or page. Up to 3,000 characters, no time window, no edit limit. The post keeps its id and LinkedIn shows an "edited" marker. Media, polls and repost targets cannot change. Pass accountId when the post went to several LinkedIn accounts.
curl -X POST https://api.pozy.ai/v1/posts/6721a3b84f3b2e0018d4b902/edit \
-H "Authorization: Bearer $POZY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "platform": "linkedin", "accountId": "6720c1a94f3b2e0018d4a7f5", "content": "We cut our onboarding from 14 steps to 4 (updated with Q3 numbers)." }'#Media requirements
Use direct file URLs; sharing links from cloud drives return a web page and fail.
Images: JPEG, PNG or GIF, up to 8 MB each, up to 20 per post, 552 x 276 to 8192 x 8192 px. Good sizes are 1200 x 627 (landscape), 1080 x 1080 (square) and 1080 x 1350 (portrait).
Video
| Property | Requirement |
|---|---|
| Formats | MP4, MOV, AVI |
| Max size | 5 GB |
| Duration | 3 seconds to 10 minutes (profile) or 30 minutes (page) |
| Resolution | 256 x 144 to 4096 x 2304 |
| Aspect ratio | 1:2.4 to 2.4:1 |
| Frame rate | 10 to 60 fps |
| Recommended | 1920 x 1080, 30 fps, H.264, AAC 192 kbps |
Documents: PDF, PPT, PPTX, DOC or DOCX, up to 100 MB and 300 pages, one per post.
#Limits
| Limit | Value |
|---|---|
| Post text | 3,000 characters |
| Images per post | 20 |
| Mentions resolved per post | 10 |
| Poll question / option | 140 / 30 characters |
| Minimum targeted audience | 300 members |
LinkedIn rejects duplicate content with 422, even when the earlier post is weeks old, and a light rephrase is often not enough. The API cannot publish long-form articles, newsletters or events, send InMail, or mix images with a video or document.
#Analytics
GET /v1/analytics?platform=linkedin returns impressions, reach, likes, comments and shares for every post. saves (and sends) exist for personal profiles only, clicks for pages only, and views for video posts only. For personal profiles LinkedIn only reports posts the member published through Pozy.
| Endpoint | What you get |
|---|---|
| LinkedIn aggregate stats | Totals or a daily series across a personal profile's posts. |
| LinkedIn org analytics | Page impressions, clicks, reactions, engagement rate, organic and paid follower gains, page views. The member must be a page administrator. |
| LinkedIn post stats | Per-post metrics by URN, for either account type. |
| Post reactions | Individual reactions with reactor profiles. Pages only. |
| Follower demographics | Page follower demographics, one breakdown per call. |
#Inbox
There are no LinkedIn DMs. On company pages you can list comments, reply and delete through Comments. Like comment takes the comment URN the comments endpoints return, plus an optional reactionType instead of the default like. Like post reacts to any post from any connected LinkedIn account, so a founder's profile can react to the company's post.
Comments are picked up by polling, so a comment automation reply can lag by a few minutes.
#Errors you may see
| Message | Cause | Fix |
|---|---|---|
Content is a duplicate of urn:li:share:... (422) |
Same or very similar text already posted | Change the text substantially. |
| Cannot mix media types | Images with a video or a document | One media type per post. |
| Video processing failed | Codec, length or shape out of range | H.264, within the duration limit, ratio between 1:2.4 and 2.4:1. |
linkedin_reconnect_required (403) |
Account connected before reaction permissions existed | Reconnect. |
linkedin_mentions_invalid |
A mention URL could not be resolved | Check the URLs in details.mentions. |
| Publishing failed during preflight checks | Posting too fast, or a validation problem | Space posts out and check account health. |
A rejected publishNow: true post returns 207 with post.status: "failed" and the reason in platforms[].errorMessage.
#Endpoints
| Endpoint | What it does |
|---|---|
GET /v1/accounts/{accountId}/linkedin-mentions |
Resolve LinkedIn mention |
GET /v1/connect/linkedin/organizations |
List LinkedIn orgs |
POST /v1/connect/linkedin/select-organization |
Select LinkedIn org |
GET /v1/accounts/{accountId}/linkedin-organizations |
List LinkedIn orgs |
PUT /v1/accounts/{accountId}/linkedin-organization |
Switch LinkedIn account type |
GET /v1/accounts/{accountId}/linkedin-aggregate-analytics |
Get LinkedIn aggregate stats |
GET /v1/analytics/linkedin/org-aggregate-analytics |
Get LinkedIn org analytics |
GET /v1/accounts/{accountId}/linkedin-post-analytics |
Get LinkedIn post stats |
GET /v1/accounts/{accountId}/linkedin-post-reactions |
Get LinkedIn post reactions |
GET /v1/analytics/linkedin/demographics |
Get LinkedIn organization follower demographics |
POST /v1/posts/{postId}/edit |
Edit published post |
POST /v1/inbox/comments/{postId}/{commentId}/like |
Like comment |
POST /v1/inbox/posts/{postId}/like |
Like post |
#Webhook events
| Event | When it fires |
|---|---|
post.published |
Post published. |
post.failed |
Post failed. |
post.platform.published |
Post platform published. |
post.platform.failed |
Post platform failed. |
post.platform.deleted |
Post platform deleted. |
account.disconnected |
Account disconnected. |
comment.received |
Comment received. |