Перейти к содержимому
Socialift
Разделы документации
Справочник SDK

Клиент LinkedIn: OAuth, профиль и посты

LinkedIn — клиент LinkedIn API в Python SDK Socialift. Он подключает участника через 3-legged OAuth и OpenID Connect (openid, profile, email), обменивает, проверяет и при наличии доступа обновляет токен, получает профиль из userinfo, а также создаёт, читает и удаляет текстовые посты и посты со ссылкой от имени участника через Posts API. Личных сообщений LinkedIn и Lead Gen Forms в клиенте нет.

from socialift import LinkedInМетодов: 10по версии socialift 1.3.0Обновлено:

Как настроить клиент LinkedIn?

Клиент создаётся так: LinkedIn(client_id=..., client_secret=...). LinkedIn.from_env() читает значения из LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET и LINKEDIN_API_VERSION. Client ID и Client Secret находятся на вкладке Auth приложения в LinkedIn Developer Portal, там же добавляется redirect URL — подробно в руководстве «Настройка приложения LinkedIn».

Доступные scope зависят от продуктов, подключённых к приложению: «Sign In with LinkedIn using OpenID Connect» — openid, profile, email; «Share on LinkedIn» — w_member_social. По умолчанию SDK запрашивает эти четыре. Для чтения постов участника нужен r_member_social — LinkedIn выдаёт это ограниченное разрешение только одобренным пользователям.

Posts API (/rest/*) требует в каждом запросе заголовок LinkedIn-Version: YYYYMM; SDK берёт его из api_version. LinkedIn поддерживает каждую ежемесячную версию минимум год, а на выведенную из эксплуатации отвечает HTTP 426 — поэтому держите api_version или LINKEDIN_API_VERSION на активной версии.

python
import asyncio
import os

from socialift import LinkedIn

async def main():
    # 1) Явные аргументы
    li = LinkedIn(
        client_id=os.environ["LINKEDIN_CLIENT_ID"],
        client_secret=os.environ["LINKEDIN_CLIENT_SECRET"],
        api_version="202609",  # активная LinkedIn-Version (YYYYMM)
    )
    # 2) Или из окружения: LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET,
    #    LINKEDIN_API_VERSION
    # li = LinkedIn.from_env()

    async with li:
        me = await li.me(os.environ["LINKEDIN_TOKEN"])  # результат exchange_code()
        print(me.id, me.full_name, li.person_urn(me.id))

asyncio.run(main())

Клиент и вход

Создание клиента, ссылка авторизации и обмен code на токен.

exchange_codefrom_envlogin_url

Обменивает code из callback на access token в /oauth/v2/accessToken (form-urlencoded) и возвращает TokenBundle.

await li.exchange_code(code: str, *, redirect_uri: str) -> socialift.models.TokenBundle
  • Правило LinkedIn: code живёт 30 минут; redirect_uri должен совпадать с указанным в запросе авторизации.
  • Access token действует 60 дней; refresh_token приходит, только если для приложения включены программные refresh token.
  • Если в ответе нет access_token, будет ApiError.

from_env

classmethod

Создаёт клиент из переменных окружения LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET и LINKEDIN_API_VERSION, чтобы ключи не хранились в коде.

LinkedIn.from_env(**kwargs) -> LinkedIn
  • Пустые значения конструктор не проверяет: отсутствие client_id проявится как ConfigurationError в login_url.
  • Без LINKEDIN_API_VERSION используется версия SDK по умолчанию — проверьте, что она ещё активна в LinkedIn.

Формирует ссылку на страницу авторизации LinkedIn (/oauth/v2/authorization); запросов не отправляет. Scope разделяются пробелом, по умолчанию: openid, profile, email, w_member_social.

li.login_url(
    *,
    redirect_uri: str,
    state: Optional[str] = None,
    scopes: Optional[list[str]] = None,
) -> str
  • Без client_id будет ConfigurationError.
  • state защищает от CSRF: если значение в callback не совпадает с отправленным, отклоните запрос (рекомендация LinkedIn). SDK его не хранит.
  • Правило LinkedIn: участник не может выбрать отдельные scope; если запросить scope, отличный от ранее выданного, все прежние access token аннулируются.
  • redirect_uri должен совпадать с одним из redirect URL на вкладке Auth приложения.
Пример — python
url = li.login_url(redirect_uri="https://siz.uz/cb", state=state)

Управление токенами

Обновление через refresh token и проверка состояния токена.

introspectrefresh

Проверяет токен через /oauth/v2/introspectToken и возвращает ответ LinkedIn словарём: active, status, expires_at, scope, auth_type и другие поля. Помогает понять, жив ли токен и когда он истечёт.

await li.introspect(token: str) -> dict
  • status: active, expired или revoked; scope возвращается только для токенов 3-legged OAuth.
  • Правило LinkedIn: если ключи верны, но токен принадлежит другому приложению, ответ будет 200 с active: false — исключения нет.
Пример — python
info = await li.introspect(token)

refresh

async

Получает новый access token по refresh token (grant_type=refresh_token) и возвращает TokenBundle. Нужен, чтобы не отправлять участника на повторный вход после истечения токена.

await li.refresh(refresh_token: str) -> socialift.models.TokenBundle
  • LinkedIn выдаёт программные refresh token только одобренным партнёрам Marketing Developer Platform; без них участник проходит авторизацию заново.
  • Refresh token действует 365 дней, и обновление не продлевает этот срок; новый access token — на 60 дней.
  • Если в ответе нет access_token, будет ApiError.
Пример — python
bundle = await li.refresh(refresh_token)

Профиль

Профиль OpenID Connect и URN автора.

meperson_urn

me

async

Возвращает профиль участника из OpenID Connect userinfo (/v2/userinfo) в виде Profile: id (= sub), имя, фото и email. sub нужен для URN автора поста.

await li.me(token: str) -> socialift.models.Profile
  • Нужны scope openid и profile, для email — email; по документации LinkedIn поле email необязательное и может отсутствовать.
  • Profile.username — email, а если его нет — sub; в Profile.raw есть дополнительное поле language из locale.

Нужные разрешения:openidprofileemail

Пример — python
me = await li.me(token)

person_urn

staticmethod

Преобразует sub в urn:li:person:{sub} — значение author для posts и create_post. Статический метод без запросов.

LinkedIn.person_urn(sub: str) -> str
  • create_post и posts сами оборачивают так значение, не начинающееся с urn:.

Нужные разрешения:r_member_socialw_member_social

Пример — python
posts = await li.posts(token, author=li.person_urn(sub), count=10)
Пример — python
post = await li.create_post(token, author=li.person_urn(sub), text="Yangiliklar!",
                             article_url="https://siz.uz/blog")

Посты

Posts API: чтение, создание и удаление постов участника.

create_postdelete_postposts

Создаёт от имени участника текстовый пост (при необходимости со ссылкой) через Posts API и возвращает {id, body}; id — URN поста из заголовка x-restli-id. visibility: PUBLIC или CONNECTIONS.

await li.create_post(
    token: str,
    *,
    author: str,
    text: str,
    visibility: str = 'PUBLIC',
    article_url: Optional[str] = None,
    article_title: Optional[str] = None,
) -> dict
  • Нужен w_member_social (продукт Share on LinkedIn).
  • Для ссылки SDK заполняет content.article полями source и title (по умолчанию — сам URL). Posts API не сканирует URL, поэтому превью и описание автоматически не появятся.
  • Другое значение visibility вызывает ConfigurationError.
  • Загрузки изображений, видео и документов в этом методе нет.

Нужные разрешения:w_member_social

Пример — python
post = await li.create_post(token, author=li.person_urn(sub), text="Yangiliklar!",
                             article_url="https://siz.uz/blog")

Удаляет пост по URN (urn:li:share:... или urn:li:ugcPost:...) и возвращает {deleted: True, urn}. URN полностью кодируется в пути запроса.

await li.delete_post(token: str, post_urn: str) -> dict
  • Правило LinkedIn: удаление идемпотентно — для уже удалённого поста тоже вернётся 204; пакетного удаления нет.
  • Нужен w_member_social; действие необратимо.

Нужные разрешения:w_member_social

Пример — python
await li.delete_post(token, post_urn)

posts

async

Читает посты автора запросом q=author к Posts API и возвращает ответ LinkedIn (elements, paging). Пагинация через start и count.

await li.posts(token: str, *, author: str, start: int = 0, count: int = 10) -> dict
  • Для постов участника нужен r_member_social — ограниченное разрешение LinkedIn только для одобренных пользователей; при 403 SDK выбрасывает PermissionError с пояснением.
  • Правило LinkedIn: count по умолчанию 10, максимум 100; результаты отсортированы по времени последнего изменения от новых к старым.
  • На странице может прийти меньше count элементов, даже если постов больше, — следующую страницу определяйте по paging.links.

Нужные разрешения:r_member_social

Пример — python
posts = await li.posts(token, author=li.person_urn(sub), count=10)

Общие методы всех клиентов

У каждого HTTP-клиента (Telegram, Facebook, Instagram, LinkedIn, TikTok, Ads) есть эти низкоуровневые методы: чтобы вызвать эндпоинт, для которого в SDK ещё нет обёртки, или читать данные постранично. По завершении блока async with соединение закрывается автоматически.

request

async

Отправляет произвольный HTTP-запрос и возвращает JSON-ответ — для эндпоинта, у которого в SDK пока нет отдельного метода. Токен и параметры подписи (access_token, для Meta — appsecret_proof через socialift.crypto.appsecret_proof) вы передаёте сами в params или headers.

await li.request(
    method: str,
    url: str,
    *,
    params: Optional[Mapping[str, Any]] = None,
    data: Optional[Any] = None,
    json: Optional[Any] = None,
    headers: Optional[Mapping[str, str]] = None,
) -> Any
  • Значения None в params не отправляются.
  • При лимите (RateLimitError) и временных ошибках сервера (HTTP 429, 500, 502, 503, 504) запрос повторяется по RetryPolicy; если есть заголовок Retry-After, SDK ждёт указанное время. Обрыв сети выбрасывается как TransportError.

get

async

Короткая форма request("GET", ...).

await li.get(url: str, **kw) -> Any

post

async

Короткая форма request("POST", ...).

await li.post(url: str, **kw) -> Any

delete

async

Короткая форма request("DELETE", ...).

await li.delete(url: str, **kw) -> Any

Проходит по курсорной пагинации Meta (paging.next) и возвращает все элементы data одним списком.

await li.paginate(
    url: str,
    *,
    params: Optional[Mapping[str, Any]] = None,
    max_items: int = 500,
    page_size: int = 100,
) -> list[dict]
  • max_items (по умолчанию 500) — защитный предел: у крупного аккаунта могут быть десятки тысяч записей. page_size — limit одного запроса.

close

async

Закрывает HTTP-сессию, созданную самим SDK (переданную извне сессию не трогает). При использовании async with Client(...) вызывается автоматически.

await li.close() -> None

Частые вопросы

Сколько действует access token LinkedIn?

По документации LinkedIn сейчас все access token выдаются на 60 дней (expires_in). Программные refresh token доступны только одобренным партнёрам Marketing Developer Platform и действуют 365 дней; их использование не продлевает срок самого refresh token. Без refresh token участнику нужно снова пройти авторизацию.

Почему при чтении постов LinkedIn возвращается 403?

posts() читает посты автора через q=author, а для постов участника нужно разрешение r_member_social. LinkedIn относит его к ограниченным и выдаёт только одобренным пользователям. Без него SDK выбрасывает PermissionError с понятным пояснением.

Что означает ошибка 426 в LinkedIn API?

Заголовок LinkedIn-Version в запросе к /rest/* указывает на неактивную версию. LinkedIn поддерживает каждую версию минимум год, а затем отвечает 426 с кодом NONEXISTENT_VERSION. Обновите api_version или LINKEDIN_API_VERSION в SDK до активного значения YYYYMM.

Как указать автора поста в LinkedIn API?

Автор личного поста задаётся как urn:li:person:{sub}, где sub — Profile.id из me(). person_urn(sub) собирает эту строку, а create_post и posts сами оборачивают значение, если оно не начинается с urn:.

Работает ли Socialift с сообщениями LinkedIn или Lead Gen Forms?

Нет. Клиент LinkedIn охватывает только вход, токены, профиль и посты. Методов для личных сообщений и Lead Gen Forms в SDK нет.

Источники

  1. LinkedIn: Authorization Code Flow (3-legged OAuth)
  2. LinkedIn: Programmatic refresh tokens
  3. LinkedIn: Token introspection
  4. LinkedIn: Sign In with LinkedIn using OpenID Connect
  5. LinkedIn: Posts API
  6. LinkedIn: API versioning

Связанные страницы