Programmatically Posting to LinkedIn Feed Using the UGC Posts API
Learn how to create LinkedIn feed updates programmatically using the UGC Posts API, from OAuth token setup to a working curl example and error handling.
20 Apr 2026, 23:17 UTC

Getting ready: app and token
Before you can create a LinkedIn update, your application must be approved for the w_member_social scope and you need a valid OAuth 2.0 access token. Only apps that have passed LinkedIn’s product review and are marked “Live” can request this scope; sandbox or development apps cannot post to real member feeds.
To obtain the token:
- Register the app in the LinkedIn Developer Portal and add
w_member_socialunder Authorized Scopes. - Start the authorization code flow (e.g., via a browser redirect) to get an authorization code.
- Exchange the code for an access token using your client ID and secret.
Store the token securely; treat it like a password because it grants posting rights on behalf of the member.
Crafting the UGC Posts payload
The Share API expects a JSON body that follows the LinkedIn UGC schema. The minimal fields for a plain‑text update are:
author– the URN of the member (e.g.,urn:li:person:{memberId}).lifecycleState– set toPUBLISHED.specificContent– an object with ashareContentblock containingshareCommentary(text) and optionallyshareMediaCategoryset toNONE.visibility– controls who sees the post;CONNECTIONSlimits it to the author’s 1st‑degree connections.
Example JSON:
{
"author": "urn:li:person:123456789",
"lifecycleState": "PUBLISHED",
"specificContent": {
"shareContent": {
"shareCommentary": {
"text": "Hello LinkedIn! This post was created via the UGC Posts API."
},
"shareMediaCategory": "NONE"
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "CONNECTIONS"
}
}
Posting with curl (example)
Run the following command in a terminal where you have the access token stored in an environment variable (replace placeholders with your actual values). This request creates the post and returns the new post URN.
curl -X POST 'https://api.linkedin.com/v2/ugcPosts' \
-H 'Authorization: Bearer $ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"author": "urn:li:person:123456789",
"lifecycleState": "PUBLISHED",
"specificContent": {
"shareContent": {
"shareCommentary": {
"text": "Hello LinkedIn! This post was created via the UGC Posts API."
},
"shareMediaCategory": "NONE"
}
},
"visibility": {
"com.linkedin.ugc.MemberNetworkVisibility": "CONNECTIONS"
}
}'
Where to run: Any shell with curl installed.
Permissions: The token must include w_member_social.
Expected check: A successful call returns HTTP 201 and a JSON body containing "id": "urn:li:ugcPost:…". That URN is the identifier for the newly created post.
Risks: Accidentally committing the access token to source control exposes your ability to post as the member. Keep it out of logs and use secret‑management tools.
Handling responses, limits, and limitations
If you exceed the default throttling quota, LinkedIn returns HTTP 429 with a Retry-After header. Implement exponential back‑off and respect that header to avoid being blocked.
The API does not support editing a post; to change content you must delete the existing post (using the DELETE /ugcPosts/{postUrn} endpoint) and create a new one. Deleted posts cannot be recovered.
Only Live apps can obtain w_member_social. During development you can test with a member who is an administrator of the app, but the post will still appear in their real feed.
Checking the result
To verify that the post is visible, retrieve it with a GET request:
curl -X GET 'https://api.linkedin.com/v2/ugcPosts/urn:li:ugcPost:987654321' \
-H 'Authorization: Bearer $ACCESS_TOKEN'
A 200 response includes the same fields you sent, confirming the content is stored. You can also view the post in the LinkedIn UI by navigating to the member’s feed.
Practical verification: Compare the returned text under specificContent.shareContent.shareCommentary with the string you submitted. If they match, the posting succeeded.
Actionable closing
To start posting programmatically:
- Ensure your LinkedIn app is Live and has
w_member_socialapproved. - Obtain a fresh access token via the OAuth 2.0 authorization code flow.
- Build the UGC Posts JSON payload with the member’s URN, desired text, and visibility.
- Send a POST to
https://api.linkedin.com/v2/ugcPostsand capture the returned URN. - Optionally retrieve the URN to confirm the content.
- Handle 429 responses with back‑off and remember that edits require a delete‑repost cycle.
Following these steps gives you a reliable way to feed LinkedIn updates from your own services while staying within the platform’s limits.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.