LinkedIn Posts API video post body: the fields and a Python builder
A LinkedIn video post needs author, commentary, visibility, distribution, a urn:li:video media id and lifecycleState PUBLISHED. Version 202510 sunsets Oct 15.

A LinkedIn video post is one POST https://api.linkedin.com/rest/posts whose content.media.id is a urn:li:video: URN from the Videos API. A successful call returns 201 and the post id in the x-restli-id response header. Every call needs a Linkedin-Version header in YYYYMM form and X-Restli-Protocol-Version: 2.0.0. The page also warns that Marketing version 202510 is sunset on October 15, 2026, so send a newer version string.
| Field | Value in the example | Note |
|---|---|---|
| author | urn:li:organization:5515715 | Organization or person URN |
| commentary | Sample video Post | The post text |
| visibility | PUBLIC | |
| distribution.feedDistribution | MAIN_FEED | NONE is used for dark posts |
| distribution.targetEntities | [] | Empty means no targeting |
| content.media.title | title of the video | |
| content.media.id | urn:li:video:... | From the Videos API |
| lifecycleState | PUBLISHED | The only accepted value on create |
| isReshareDisabledByAuthor | false |
Permissions and the video it points to
Posting for a company page needs w_organization_social and a page role of administrator, direct sponsored content poster or content admin. Posting as a member needs w_member_social. The video must exist first: initialize an upload, send the parts, finalize, and wait for the asset to become AVAILABLE. The Videos API lists MP4, three seconds to 30 minutes, and 75 KB to 500 MB for standard video.
If you produce the MP4 with Sume, the file comes from a finished job result rather than from the Sume API directly into LinkedIn. Sume has no LinkedIn publishing endpoint in its public docs, so the hand-off is: download the video_url, upload to LinkedIn, then post.
A builder you can run
The function below assembles the JSON body and prints it. It makes no network call, so you can diff it against the page example before wiring in a token. Replace the URN with the one your upload returned.
import json
def video_post(author, video_urn, text, title):
return {
"author": author,
"commentary": text,
"visibility": "PUBLIC",
"distribution": {
"feedDistribution": "MAIN_FEED",
"targetEntities": [],
"thirdPartyDistributionChannels": [],
},
"content": {"media": {"title": title, "id": video_urn}},
"lifecycleState": "PUBLISHED",
"isReshareDisabledByAuthor": False,
}
print(json.dumps(video_post(
"urn:li:organization:5515715",
"urn:li:video:C5F10AQGKQg_6y2a4sQ",
"Sample video Post",
"title of the video"), indent=2))Sources
Related posts
More in Developers
- LinkedIn video post stuck in processing: two status ladders to poll
LinkedIn tracks a video asset (PROCESSING, AVAILABLE) and a post (PUBLISH_REQUESTED, PUBLISHED) separately. Poll both, then compare with a Sume job poll.
- MAI-Transcribe-2 on OpenRouter: wav, base64, transcript JSON
OpenRouter exposes microsoft/mai-transcribe-2 at POST /api/v1/audio/transcriptions with base64 audio and returns JSON with transcript and usage.
- MAI-Voice-2.1 on OpenRouter: audio/speech call, mp3 or pcm
OpenRouter serves microsoft/mai-voice-2.1 at POST /api/v1/audio/speech and returns raw audio bytes, mp3 or pcm. Here is the call and how Sume jobs differ.
- Decision-1 returns 429: back off, then fail closed before Sume
Microsoft says retry a Decision-1 429 with exponential backoff. Cap the retries, then route the brief to review so a throttled gate never renders.
Written by Sume