Как публиковать посты в LinkedIn через API
Чтобы публиковать в LinkedIn через API от имени участника, подключите к приложению два открытых продукта — Sign In with LinkedIn using OpenID Connect и Share on LinkedIn, — запросите openid profile email w_member_social, получите sub участника из /v2/userinfo и отправьте POST на /rest/posts с автором urn:li:person:{sub} и заголовком LinkedIn-Version. Для страниц компаний нужен проверяемый Community Management API.
Обновлено:
Что нужно для публикации в LinkedIn через API?
Приложение разработчика LinkedIn с двумя открытыми продуктами, access token участника со scope w_member_social и person URN участника. Share on LinkedIn выдаёт w_member_social без специального одобрения; Sign In with LinkedIn using OpenID Connect даёт openid, profile и email, чтобы определить участника. Публикация от имени страницы компании — отдельная программа с проверкой.
LinkedIn называет Open Permissions единственными разрешениями, доступными всем разработчикам без специального одобрения. Для публикации это profile, email и w_member_social. Всё остальное — от постов организации до чтения активности участника — требует одобрения LinkedIn.
Открытые scopes для идентификации — openid, profile и email из OpenID Connect; данные участника берутся из endpoint'а /v2/userinfo.
Продукты и разрешения LinkedIn для публикации
| Продукт или программа | Разрешения | Доступ | Что даёт |
|---|---|---|---|
| Sign In with LinkedIn using OpenID Connect | openid, profile, email | Открытый, подключается во вкладке Products | Идентификация участника: sub, имя, фото, email |
| Share on LinkedIn | w_member_social | Открытый, подключается во вкладке Products | Посты, комментарии и лайки от имени участника |
| Community Management API | w_organization_social, r_organization_social и другие | С проверкой: сначала Development tier, затем Standard tier | Посты страниц компаний, комментарии, аналитика |
| Чтение постов участника | r_member_social | Закрыт — LinkedIn не принимает заявки | Посты, комментарии и лайки участника |
| Messages API | нет | Только для одобренных партнёров | Сообщения между участниками |
естьнетТаблицу можно прокрутить вбок
Lead Sync (лид-формы LinkedIn) — отдельная программа со своей заявкой. Socialift не предоставляет сообщения и лид-формы LinkedIn.
Как опубликовать первый пост в LinkedIn через API
Создайте приложение и подключите продукты
В LinkedIn Developer Portal откройте My Apps, создайте приложение и во вкладке Products добавьте Sign In with LinkedIn using OpenID Connect и Share on LinkedIn.
Настройте redirect URL
Во вкладке Auth возьмите Client ID и Client Secret и добавьте абсолютный HTTPS redirect URL. Query-параметры в нём LinkedIn игнорирует, а адреса с
#не принимает.Отправьте участника на авторизацию
Перенаправьте на
https://www.linkedin.com/oauth/v2/authorizationсresponse_type=code,client_id,redirect_uri,stateиscopeчерез пробел, напримерopenid profile email w_member_social.Обменяйте код в течение 30 минут
Проверьте
state, затем отправьте форму сgrant_type=authorization_code,code,client_id,client_secretиredirect_uriнаhttps://www.linkedin.com/oauth/v2/accessToken. Код живёт 30 минут.Получите person URN
Вызовите
GET https://api.linkedin.com/v2/userinfoс токеном. Полеsub— идентификатор участника; автор поста —urn:li:person:{sub}.Создайте пост
Отправьте POST на
https://api.linkedin.com/rest/postsс заголовкамиLinkedIn-Version: YYYYMMиX-Restli-Protocol-Version: 2.0.0. В ответе201ID поста приходит в заголовкеx-restli-id.
Вход и публикация на Python
Явно задайте api_version — поддерживаемый релиз YYYYMM: LinkedIn не подставляет последнюю версию автоматически.
import os
from socialift import LinkedIn
REDIRECT_URI = "https://app.example.com/oauth/linkedin/callback"
def client() -> LinkedIn:
return LinkedIn(
client_id=os.environ["LINKEDIN_CLIENT_ID"],
client_secret=os.environ["LINKEDIN_CLIENT_SECRET"],
api_version=os.environ.get("LINKEDIN_API_VERSION", "202609"),
)
async def authorize_url(state: str) -> str:
async with client() as li: # scopes по умолчанию: openid profile email w_member_social
return li.login_url(redirect_uri=REDIRECT_URI, state=state)
async def publish(code: str) -> str:
async with client() as li:
bundle = await li.exchange_code(code, redirect_uri=REDIRECT_URI)
me = await li.me(bundle.access_token)
post = await li.create_post(
bundle.access_token,
author=li.person_urn(me.id),
text="Опубликовали журнал изменений API за сентябрь.",
visibility="PUBLIC",
)
return post["id"] # urn:li:share:… или urn:li:ugcPost:…create_post принимает visibility со значением PUBLIC или CONNECTIONS и читает URN нового поста из заголовка ответа x-restli-id — в теле ответа его нет.
article_url= и article_title= прикрепляют ссылку на статью. Posts API не сканирует URL, поэтому пост покажет только то, что вы отправили: метод задаёт ссылку и заголовок, без миниатюры.
Posts API и устаревший ugcPosts
| Параметр | Posts API | ugcPosts (устаревший) |
|---|---|---|
| Endpoint | POST /rest/posts | POST /v2/ugcPosts |
| Статус | Актуальный; LinkedIn указывает, что он заменяет ugcPosts | Всё ещё приведён в гайде Share on LinkedIn |
| Заголовок версии | LinkedIn-Version: YYYYMM обязателен | Без версий |
| Заголовок протокола | X-Restli-Protocol-Version: 2.0.0 | X-Restli-Protocol-Version: 2.0.0 |
| Текст поста | commentary | specificContent → com.linkedin.ugc.ShareContent → shareCommentary |
| Медиа | URN из Images, Videos и Documents API; посты MultiImage и Poll | Ассеты через /v2/assets?action=registerUpload |
| ID созданного поста | Заголовок x-restli-id, 201 | Заголовок X-RestLi-Id, 201 |
Для новой интеграции выбирайте /rest/posts: у LinkedIn есть отдельное руководство по миграции с ugcPosts на Posts API.
Как работает заголовок LinkedIn-Version
Версионируемые API LinkedIn находятся под https://api.linkedin.com/rest/, и каждый запрос обязан содержать LinkedIn-Version в формате YYYYMM. Версии выходят ежемесячно, каждая поддерживается минимум год. На момент написания статьи последняя версия — 202609 (сентябрь 2026 года).
LinkedIn не переключает на новую версию сам: без заголовка или с выведенной из поддержки версией возвращается ошибка. Документация сейчас предупреждает, что версия 202510 будет отключена 15 октября 2026 года; более старых версий в списке поддерживаемых уже нет.
Endpoint'ы /v2/, например /v2/userinfo, не версионируются. В Socialift SDK версия задаётся один раз на клиент через api_version= (или LINKEDIN_API_VERSION при LinkedIn.from_env()) и отправляется с каждым запросом к /rest/ вместе с X-Restli-Protocol-Version: 2.0.0. Пересматривайте её хотя бы раз в год.
Токены LinkedIn: срок жизни и обновление
| Элемент | Поведение LinkedIn | Socialift SDK |
|---|---|---|
| Код авторизации | Живёт 30 минут; используйте сразу | exchange_code |
| Access token | 60 дней (expires_in = 5184000); около 500 символов, закладывайте хранение на 1000+ | Результат exchange_code |
| Программный refresh token | Только одобренным партнёрам (Marketing Developer Platform); действует 365 дней, при обновлении срок не сбрасывается | refresh |
| Refresh token нет | Повторите авторизацию; окно согласия пропускается, если участник залогинен в LinkedIn и токен ещё не истёк | login_url |
| Смена scopes | Запрос другого набора scopes аннулирует ранее выданные access token | нет |
| Статус токена | POST /oauth/v2/introspectToken возвращает active, status, expires_at, scope | introspect |
естьнет
Проверка токена, повторная авторизация и удаление поста
# client() и REDIRECT_URI — из linkedin_post.py
async def ensure_active(token: str, state: str) -> str | None:
async with client() as li:
info = await li.introspect(token)
if info.get("active"):
return None
return li.login_url(redirect_uri=REDIRECT_URI, state=state) # отправляем участника заново
async def remove_post(token: str, post_urn: str) -> None:
async with client() as li:
await li.delete_post(token, post_urn)delete_post кодирует URN в пути запроса, как требует LinkedIn. Удаление идемпотентно: повторное удаление уже удалённого поста снова вернёт 204.
Посты от имени страницы компании: Community Management API
Для публикации от имени организации автор — urn:li:organization:{id}, а токену нужен w_organization_social. Это разрешение ограничено участниками с ролью ADMINISTRATOR, DIRECT_SPONSORED_CONTENT_POSTER или CONTENT_ADMIN на странице и выдаётся только через Community Management API.
Доступ к Community Management API проверяется. Сейчас LinkedIn выдаёт его только зарегистрированным юридическим лицам для коммерческих сценариев: подтверждается рабочий email, указываются юридическое название, адрес, сайт и политика конфиденциальности, а супер-администратор страницы LinkedIn подтверждает приложение. Сначала выдаётся Development tier с ограниченным объёмом вызовов; для Standard tier нужна запись экрана по каждому сценарию. Заявку на Development tier подают для нового приложения без других API-продуктов.
После одобрения тот же вызов create_post работает с URN организации в author, а posts(token, author=...) со scope r_organization_social выводит посты организации.
Данные участников из этих API подпадают под Marketing API Terms LinkedIn: их нельзя использовать для продаж, рекрутинга или обогащения данных CRM, а данные об активности участников можно хранить не дольше 48 часов.
Чего LinkedIn API не даёт
Чтение собственных постов участника требует r_member_social, а LinkedIn обозначает это разрешение как закрытое и не принимает заявки. На практике для большинства приложений li.posts() с person URN вернёт 403; SDK превращает его в PermissionError с пояснением.
Отправка сообщений доступна только одобренным партнёрам, и даже тогда сообщение должно быть связано с конкретным действием участника — автоматическая или запланированная отправка запрещена. Данные лид-форм относятся к отдельной программе Lead Sync. Socialift не предоставляет сообщения и лид-формы LinkedIn.
Лимиты считаются по дням: в документации Share on LinkedIn указано 150 запросов в день на участника и 100 000 на приложение, сутки считаются по UTC.
Частые вопросы
Можно ли через Share on LinkedIn публиковать на странице компании?
Нет. Share on LinkedIn даёт w_member_social только для постов от имени участника. Для страницы компании нужен w_organization_social, который выдаётся через Community Management API участникам с ролью администратора или контент-менеджера страницы.
Сколько действует access token LinkedIn?
Сейчас все access token выдаются на 60 дней. Программные refresh token получают только одобренные партнёры; остальные повторяют авторизацию, и если участник залогинен в LinkedIn, а токен ещё действует, окно согласия пропускается.
ugcPosts API в LinkedIn устарел?
LinkedIn указывает, что Posts API заменяет ugcPosts API, и даёт руководство по миграции. Новые интеграции должны использовать /rest/posts с заголовком LinkedIn-Version.
Почему LinkedIn отклоняет запрос из-за версии?
В запросе к /rest/ нет заголовка LinkedIn-Version или указанная версия выведена из поддержки. Каждая версия поддерживается минимум год — обновите заголовок до поддерживаемого значения YYYYMM.
Можно ли читать свои посты или статистику LinkedIn через API?
Для чтения постов участника нужен r_member_social, а это закрытое разрешение. Статистика постов участников входит в сценарии проверяемого Community Management API.
Можно ли отправлять сообщения в LinkedIn через API?
Messages API доступен только одобренным партнёрам, и каждое сообщение должно следовать из конкретного действия участника. Socialift с сообщениями LinkedIn не работает.