TL;DR, Quick Answer
7 min readLinkedIn versions its Marketing APIs monthly under the /rest/ base path, and every call must name a version in the header, since the latest version is not applied by default. The value is six digits, YYYYMM, such as 202608. A missing header returns 400 VERSION_MISSING, and a sunset one returns 426 NONEXISTENT_VERSION. Each version is supported for a minimum of one year. The separate X-Restli-Protocol-Version header must carry 2.0.0, because a request without it falls back to protocol 1.0 and a different query syntax.
What is the LinkedIn-Version header?
Every call to https://api.linkedin.com/rest/ carries a LinkedIn-Version header, and LinkedIn accepts one value format for it: six digits, YYYYMM. The versioning reference puts it in one sentence: "Include a request header with the key Linkedin-Version and set the value to the version (format: YYYYMM) to correspond with the documentation version you are referencing."
The header exists because LinkedIn ships a new API version every month and refuses to guess which one you meant. From the same page: "LinkedIn expects every versioned API call to specify a version; the latest version is not applied by default."
A full request looks like this:
curl -X POST 'https://api.linkedin.com/rest/adCampaigns' \
-H 'X-Restli-Protocol-Version: 2.0.0' \
-H 'Authorization: Bearer {INSERT_TOKEN}' \
-H 'Content-Type: application/json' \
-H 'Linkedin-Version: 202601' \
--data '{
"account": "urn:li:sponsoredAccount:123212321",
"audienceExpansionEnabled": false
}'Versioning arrived with a new base path, not a new domain. LinkedIn dates it precisely: "LinkedIn's Marketing APIs first versioned API release was June 2022 under a new base path: https://api.linkedin.com/rest/." Anything still on https://api.linkedin.com/v2/ predates the scheme and behaves differently, which the last section covers.
What format does the version value take?
YYYYMM, four digit year followed by two digit month, with no separator and no day. 202601 means the version published in January 2026. The example LinkedIn gives for migrating one version to the next is a single string swap:
-H 'Linkedin-Version: 202501' to -H 'Linkedin-Version: 202601'Recent values, copied from the versioning page's own table:
| Version name | Header value |
|---|---|
| August 2026 | 202608 |
| November 2025 | "Linkedin-Version": "202511" |
| October 2025 | "Linkedin-Version": "202510" |
| September 2025 | "Linkedin-Version": "202509" |
August 2026, 202608, is the value the page lists under "Latest Version" as of its last update on 17 August 2026. Nothing about the format changes month to month, which is what makes the header safe to build a rolling upgrade around: one configuration value, six characters, one deploy.
One inconsistency to note, because it will confuse anyone matching on error text. The error for a dead version uses an eight character placeholder, "Requested version yyyymmdd is not active," while the format LinkedIn requires is six characters. The placeholder is the only place yyyymmdd appears. Treat it as a typo in the message template, not as a second accepted format.
Is it spelled LinkedIn-Version or Linkedin-Version?
LinkedIn's documentation spells it Linkedin-Version, with a lowercase i in the second syllable, on every page that mentions it. The versioning reference, the Images API, the Posts API, the Videos API and the error reference all use that spelling, and the error message itself says "by adding the Linkedin-Version header." The company name is capitalized LinkedIn everywhere else on those same pages.
HTTP header field names are not case sensitive, so LinkedIn-Version, Linkedin-Version and linkedin-version all reach the same header on the server. The spelling matters for a narrower reason: if you grep LinkedIn's documentation or a Postman collection for LinkedIn-Version, you will find nothing. Search for the documented spelling instead.
What happens when the header is missing or stale?
Two distinct failures with two distinct status codes, both documented with exact bodies.
| Condition | Status | Code | Message |
|---|---|---|---|
| Header absent | 400 | VERSION_MISSING | "A version must be present. Please specify a version by adding the Linkedin-Version header." |
| Version sunset | 426 | NONEXISTENT_VERSION | "Requested version yyyymmdd is not active" |
The 426 is the interesting one. HTTP 426 is Upgrade Required, and LinkedIn is using it literally: the request was understood, the version you named is gone, upgrade the header. It is not a 400, not a 410, and not a 404, so error handlers that only branch on 4xx ranges will route it somewhere useless.
Both failures happen before any business logic runs. Your payload can be perfect and your token fresh, and you still get a 400 if the header is absent. That is what makes a stale version header such a quiet failure mode in scheduled publishing: nothing changes in your code, a sunset date passes, and every call starts returning 426. Publishing that breaks for a whole account overnight, with no code change behind it, is worth checking against the list of causes in the piece on LinkedIn scheduled posts that stop working.

How long does a LinkedIn API version last?
A minimum of one year. The cadence page states it twice: "LinkedIn Marketing API Program publishes new versions monthly, and those versions are supported for a minimum of one (1) year," and "These API versions are supported and stable for a minimum of one year before sunset."
AdaptlyPost
Start Your 7-Day Free Trial
All-platform analytics
Social Inbox
AI-powered assistant
The deprecation banner running across the marketing documentation is a live example of that clock: "The Marketing Version 202508 (Marketing August 2025) will be sunset on August 17, 2026." Twelve months and change, announced in advance, on every page.
The one year floor comes with a stated exception. LinkedIn "reserves the right to release a patch version to any API if required for any critical security, privacy issues, or bug fixes," describing the likelihood as minimal. So the guarantee is that a version stays available for a year, not that its behaviour is frozen for a year.
What that means in practice is a calendar entry rather than an architecture decision. Pin the version explicitly, review it once a year, and jump to the newest version when you do, since LinkedIn's own guidance is that migrating to the latest buys you "the option to wait up to one year before having to migrate again." The API surface that sits on top of this, and what each version actually governs, is covered in the overview of the LinkedIn Marketing API.
What is the X-Restli-Protocol-Version header for?
A different job entirely, and it is required alongside the version header rather than instead of it. The Posts API states both in one breath: "All APIs require the request header Linkedin-Version: {Version in YYYYMM format}. All APIs require the request header X-Restli-Protocol-Version: 2.0.0."
LinkedIn-Version picks which month's API behaviour you get. X-Restli-Protocol-Version picks how your URLs and query parameters are encoded, because LinkedIn's APIs are built on Rest.li. The protocol page is blunt about the default: "To use version 2.0, you must pass X-Restli-Protocol-Version: 2.0.0 as the header in your API requests. If you don't pass a header, your call will default to version 1.0."
Falling back to 1.0 does not throw an error. It changes the syntax the server expects, which is worse:
| What you are doing | Protocol 1.0 | Protocol 2.0 |
|---|---|---|
| Batch get by ids | ?ids=1&ids=2&ids=3 | ?ids=List(1,2,3) |
| A resource key with a URN | Unencoded urn:li:... | urn%3Ali%3A... with ( as %28 |
| A list parameter | param.aList[0]=foo¶m.aList[1]=bar | param=(aList:List(foo,bar,baz)) |
So a request missing the protocol header gets parsed by rules your client is not writing to, and the resulting errors point at your parameters rather than at the missing header. LinkedIn also notes it "plans to deprecate protocol version 1.0 in the near future" without naming a date. Send 2.0.0 on every call and the question never comes up.
Which LinkedIn endpoints need the version header?
The ones under /rest/. The older /v2/ endpoints do not take it, and that split explains most of the confusion in integrations that predate 2022.
| Base path | Linkedin-Version | X-Restli-Protocol-Version |
|---|---|---|
https://api.linkedin.com/rest/ | Required | Required, 2.0.0 |
https://api.linkedin.com/v2/ | Not documented | Required, 2.0.0 |
The consumer Share on LinkedIn guide, which still documents POST https://api.linkedin.com/v2/ugcPosts and POST https://api.linkedin.com/v2/assets?action=registerUpload, lists exactly one required header: "All requests require the following header: X-Restli-Protocol-Version: 2.0.0." No version header appears on that page at all.
Every versioned image and post call needs both, which is why the header shows up in each sample request in the walkthrough of how initializeUpload turns a file into an image URN, and why the schema rows that document limits like the 4,086 character alt text ceiling live on versioned pages that change month to month. Read a limit off a version you are not sending, and you are reading the wrong contract.
Frequently asked questions

What is the correct format for the LinkedIn-Version header?
Six digits in YYYYMM form, such as Linkedin-Version: 202608. LinkedIn describes the value as corresponding "to the documentation version you are referencing," so the header value and the documentation page you are reading should name the same month.
What error does LinkedIn return if the version header is missing?
400 with the code VERSION_MISSING and the message "A version must be present. Please specify a version by adding the Linkedin-Version header." The check runs before the request body is evaluated.
What is HTTP 426 NONEXISTENT_VERSION on the LinkedIn API?
The response to a version that has been sunset. The documented body is {"status": 426, "code": "NONEXISTENT_VERSION", "message": "Requested version yyyymmdd is not active"}, and 426 is the Upgrade Required status, which here means upgrade the header value.
How often does LinkedIn release a new API version?
Monthly. LinkedIn publishes a new version each month and supports each one "for a minimum of one (1) year," with a changelog per version listing which resources changed.
AdaptlyPost
Start Your 7-Day Free Trial
All-platform analytics
Social Inbox
AI-powered assistant
Do you need both LinkedIn-Version and X-Restli-Protocol-Version?
Yes, on /rest/ endpoints. The Posts API states that all APIs require Linkedin-Version in YYYYMM format and all APIs require X-Restli-Protocol-Version: 2.0.0, and a request without the second one silently falls back to protocol 1.0 and its different query syntax.
Is the header spelled LinkedIn-Version or Linkedin-Version?
LinkedIn's documentation uses Linkedin-Version everywhere, including inside the error message. HTTP field names are not case sensitive, so either spelling reaches the server, but only the documented one will match a search of LinkedIn's own pages.
Does the LinkedIn-Version header work on the older v2 endpoints?
No, that requirement is scoped to the base path. Linkedin-Version applies to calls under https://api.linkedin.com/rest/, the path LinkedIn introduced in June 2022. The older https://api.linkedin.com/v2/ endpoints, like POST /v2/ugcPosts, don't document that header at all, only X-Restli-Protocol-Version.
Can LinkedIn change how a version behaves after it ships?
LinkedIn can, within limits. It reserves the right to release a patch to a version for critical security, privacy, or bug fixes, though it calls that likelihood minimal. The one-year support window promises that the version stays reachable, not that its behavior stays frozen for that year.
What changed about the LinkedIn API in June 2022?
LinkedIn's Marketing APIs got their first versioned release that month, under a new base path, https://api.linkedin.com/rest/. Anything still running against the older https://api.linkedin.com/v2/ path predates that change, follows different rules, and skips the Linkedin-Version header entirely.
Why would a working LinkedIn integration suddenly start failing overnight?
The most common silent cause is a sunset version header. Nothing in your code changes, but once a version's one-year support window ends, every call naming it starts returning 426 NONEXISTENT_VERSION instead of succeeding. Scheduled publishing is especially exposed, since the header often gets set once and never revisited.
Put this into practice with AdaptlyPost
Was This Article Helpful?
Let us know what you think!
See us more often in Google
One click marks AdaptlyPost as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.
Before you go...
AdaptlyPost
Schedule your content across all platforms
Manage all your social media accounts in one place with AdaptlyPost.
All-platform analytics
Social Inbox
AI-powered assistant
Related Glossary Terms


How LinkedIn initializeUpload Turns a File Into an Image URN
The LinkedIn initializeUpload action returns an image URN and an upload URL. Here is the PUT, the post that references the URN, and the errors at each step.


Where the LinkedIn Alt Text Character Limit Is Actually Written
The LinkedIn alt text character limit is 4,086 characters on the API altText field, and LinkedIn publishes no limit at all for the alt text box in the app.


How a Bluesky threadgate Decides Who Can Reply to a Post
A Bluesky threadgate limits replies to mentioned users, followers, people you follow or a list. How the record works, and the postgate that stops quotes.
Related Articles


Why 429 Retry-After Is Missing From Most Social Media APIs
The 429 Retry-After pair is HTTP's way of saying wait. X, Meta, LinkedIn, TikTok and YouTube document no Retry-After, so here is what each sends instead.


Why Your Social Media Scheduler Keeps Disconnecting Accounts
A social media scheduler keeps disconnecting when a token expires or dies early. Token lifetimes for Meta, LinkedIn, X and TikTok, and what kills them.


What Instagram's content_publishing_limit Endpoint Returns
Instagram's content_publishing_limit endpoint returns quota_usage plus a config block holding quota_total 50 and quota_duration 86400 seconds.

