This is a cross-post — the original (and any updates) live at broke2builtai.com.
Every scheduled-posting tool for LinkedIn wants a subscription for what is, underneath, four HTTP requests. I assumed the DIY route was gated behind a partner-program application and weeks of waiting — that's the reputation. Then I actually did it today, and the whole thing — app creation to a verified working token — took about fifteen minutes, because the two products a personal posting script needs are instant self-serve checkboxes. Here's the exact walkthrough, including the one place LinkedIn tried to trip me.
Step 1: Create the app (you need a company page)
Go to linkedin.com/developers/apps and create an app. The one real prerequisite: LinkedIn requires a company page to verify the app against. If the page is yours, this is a non-event — you approve the verification request as the page admin and it's verified instantly.
Don't let the company-page requirement confuse you about what you're building: the app is verified against the page, but with the scopes below you'll be posting as yourself, to your own member feed.
Step 2: Request the two instant products
On the app's Products tab, request:
-
Share on LinkedIn — this is what grants the
w_member_socialscope, the permission to create posts as a member. -
Sign In with LinkedIn using OpenID Connect — this grants
openid profile email, which you need to fetch your own member id.
Both are instant self-serve grants: tick the checkbox, accept the LinkedIn API Terms, done. No review queue, no application essay.
One boundary I hit while poking around: the Community Management API — the product that lets you post as an organization/page rather than as yourself — cannot share an app with other products. It demands its own dedicated app. So if page-posting is in your future, plan on a second app; don't try to bolt it onto this one.
Step 3: Add a redirect URL (it can literally 404)
On the Auth tab, add an authorized redirect URL. Here's the part that saves you from standing up a server: any https URL on a domain you control works — even one that returns a 404.
Why: LinkedIn's OAuth flow ends by redirecting your browser to that URL with ?code=... appended. For a one-time personal-token setup, you don't need the page to do anything — you just need to read the code parameter out of the address bar after the redirect lands. A dead path on a domain you own is a perfectly valid OAuth redirect target for this purpose.
While you're on the Auth tab, note your Client ID and Client Secret — and keep the secret out of your repo. Same rule as giving credentials to a scheduled cloud agent: secrets live in environment variables or server-side stores, never in git.
Step 4: The consent URL
Build this URL (one line) and open it in a browser where you're logged in to LinkedIn:
https://www.linkedin.com/oauth/v2/authorization
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URL
&scope=openid%20profile%20email%20w_member_social
&state=SOME_RANDOM_STRING
Approve the consent screen, and LinkedIn bounces you to your redirect URL with ?code=... in the query string. Copy that code — it's single-use and short-lived, so move straight to the exchange.
The gotcha that got me: LinkedIn may interrupt the consent flow with a security checkpoint asking you to verify your email if the login looks unusual to it. It's not a bug in your setup — complete the verification and the flow resumes.
Step 5: Exchange the code for a token
Form-encoded POST:
curl -X POST https://www.linkedin.com/oauth/v2/accessToken \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=THE_CODE_FROM_THE_REDIRECT \
-d redirect_uri=YOUR_REDIRECT_URL \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET
The response gives you access_token, expires_in: 5184000, an id_token, and the granted scope. That expires_in is the quiet headline: 5,184,000 seconds is two months. For a personal script, that means re-doing this dance six times a year, not building refresh-token plumbing on day one.
Step 6: Verify the token and get your member id
curl https://api.linkedin.com/v2/userinfo \
-H "Authorization: Bearer <your-access-token>"
This returns your name plus a sub field — your member id. Your author URN for posting is urn:li:person:<sub>. If this call returns your own name, the OAuth leg is done and verified.
Step 7: The post call (per LinkedIn's docs)
Honesty checkpoint: everything above this line I ran today and watched succeed, through the userinfo verification. The post call itself I'm giving you as documented by LinkedIn — I validated the token and URN, not an actual published post yet.
Per the docs, posting is:
curl -X POST https://api.linkedin.com/rest/posts \
-H "Authorization: Bearer <your-access-token>" \
-H "X-Restli-Protocol-Version: 2.0.0" \
-H "LinkedIn-Version: YYYYMM" \
-H "Content-Type: application/json" \
-d '{
"author": "urn:li:person:YOUR_SUB",
"commentary": "Posted from a script.",
"visibility": "PUBLIC",
"distribution": { "feedDistribution": "MAIN_FEED" },
"lifecycleState": "PUBLISHED"
}'
Two headers people miss: X-Restli-Protocol-Version: 2.0.0 is required, and LinkedIn-Version must be a valid YYYYMM API version string — check LinkedIn's versioning docs for the current active version and substitute it for the placeholder above.
Where this goes next
A two-month token plus a four-request flow is exactly the shape of thing you hand to an agent. Mine drafts in a cheap lane — I run bulk generation on the z.ai GLM Coding Plan (that's a referral link, it helps fund our compute, and the plan costs the same with or without it; setup in how to set up Claude Code with the GLM API) — and the posting step is just this walkthrough's step 7 wearing a cron. If you want the whole loop hands-off, the same pattern as scheduling Claude Code to run daily in the cloud applies: keep the LinkedIn token server-side, let the scheduled job call a narrow relay. And if the script needs richer context than "write a post" — your voice, your topics, your rules — that's a job for a proper instruction stack, the kind you build once with something like an MCP server feeding your agent real data and a prompt written like it has to survive unattended. Meta-Prompt Architect is my tool for exactly that last part: turning "post good stuff to LinkedIn" into instructions precise enough that the 2-month token is the only thing you ever have to touch.
Broke to Built is one broke human + AI agents building real software with no budget, writing down every step. This site's tools run on free GLM — z.ai's Coding Plan is the referral that funds our compute (disclosed affiliate).
Top comments (0)