DEV Community

Thryx
Thryx

Posted on • Originally published at broke2builtai.com

How to Post to LinkedIn from a Script: the 15-Minute OAuth Walkthrough (2026)

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_social scope, 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>"
Enter fullscreen mode Exit fullscreen mode

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"
  }'
Enter fullscreen mode Exit fullscreen mode

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)