Skip to content

Get LinkedIn posting credentials

Set up a LinkedIn app so keryx auth linkedin can capture an access token and keryx publish linkedin can post a rendered reel as a video share to your feed, or an announcement post as an article card (the link, title and description, with the post's image as the thumbnail) since 0060 D14. LinkedIn is a standard OAuth2 provider, so auth is the same loopback flow as YouTube — the wrinkle is the token model: a standard app gets a ~60-day access token and no refresh token, so you re-authorize every ~60 days (refresh tokens need Marketing Developer Platform approval — see the spec 0009-linkedin.md §3.1).

Status: app-registration steps (§1–§4) are ready to follow now.

What you need

  • A LinkedIn account and a LinkedIn Company Page (apps must be linked to a Page; create one at https://www.linkedin.com/company/setup/new/ if needed).
  • ~15 minutes. No per-post audit (unlike TikTok) — w_member_social member posting is available once the product is added.

1. Create the app

  1. Go to LinkedIn Developers → https://www.linkedin.com/developers/apps → Create app.
  2. Associate it with your Company Page and verify the Page (the portal walks you through a verification link).
  3. From the Auth tab, note the Client ID and Client Secret:
  4. platforms.linkedin.client_id (non-secret) — goes in keryx config.
  5. LINKEDIN_CLIENT_SECRET (secret) — env var / keychain, never committed.

2. Add the products

On the Products tab, add:

  • Share on LinkedIn — grants w_member_social (post on behalf of the member).
  • Sign In with LinkedIn using OpenID Connect — grants openid + profile (so keryx can read your Person URN, the post author).

Both are self-serve and usually approved instantly.

3. Register the redirect URI

On the Auth tab → Authorized redirect URLs, add the loopback block keryx uses (LinkedIn exact-matches, no wildcard ports):

http://127.0.0.1:3764/
http://127.0.0.1:3765/
… up to http://127.0.0.1:3769/

keryx picks the first free one, the same block as every other platform, so one ssh forward serves every auth. --redirect overrides it. If LinkedIn rejects http, register an https:// URL and pass that instead (keryx serves a self-signed loopback in that case).

4. Token model & the ~60-day re-auth

  • Standard apps get a ~60-day access token, no refresh token. keryx stores the token + its expiry; when it expires, keryx publish linkedin fails with a clear "re-run keryx auth linkedin" message. Just re-authorize.
  • Refresh tokens (no re-auth) require Marketing Developer Platform approval — an advertising/marketing program, overkill for personal posting. keryx auto-uses a refresh token if one is ever returned, so no code change is needed if you later get MDP access.

Official references

  • LinkedIn — Share on LinkedIn, Sign In with LinkedIn using OpenID Connect.
  • LinkedIn — Posts API and Videos API (versioned).
  • LinkedIn — Refresh Tokens with OAuth 2.0 (MDP-only).

5. Authorise keryx

With the client id in config (platforms.linkedin.client_id) and the secret in the environment (LINKEDIN_CLIENT_SECRET):

keryx auth linkedin

It opens the authorize URL, captures the code on the loopback (paste fallback for headless boxes), reads your Person URN, and stores the access token. platforms.linkedin.enabled flips true. Then keryx publish linkedin posts a reel as a video share, or a post as an article card.

6. What a post looks like there

  • With a link (every announcement has one): an article card carrying the link, the title and the card description, with the post's image uploaded through the Images API as its thumbnail. LinkedIn does not scrape the page, so the card is only as good as those three fields. The commentary carries the text and hashtags; the link is on the card, not repeated.
  • With an image and no link: an image share, alt text included.
  • With neither: plain commentary.
  • The copy is sent exactly as written. LinkedIn reads commentary in its little text format, so keryx escapes its reserved characters (( ) * _ ~ @ # and the rest) on the way out. A #word at the start of a word stays a hashtag. Write the copy for people; never escape it by hand, or the backslashes will show.
  • The Images API has no status to poll and a w_member_social token cannot read it back, so the URN is used as soon as the upload returns.

Note on visibility: LinkedIn has no private ("only me") option — a post is PUBLIC or CONNECTIONS. For a first live test, set platforms.linkedin.visibility: CONNECTIONS (or delete the test post after), since it will be visible. Video must be MP4, 3 s–30 min, 75 KB–500 MB.