LinkedIn guide

Learn how to implement a custom LinkedIn authentication form inside your application using the postpress API.

If you are just starting your integration, we recommend the hosted auth wizard. It takes less time to ship. You can layer custom authentication on top later as a second step.

Step 1: Authenticate to LinkedIn

You have two options to initiate LinkedIn authentication.

Option A: username and password

Provide the LinkedIn username and password and POST them to the accounts endpoint, or call the equivalent SDK method.

curl --request POST \
     --url https://api.postpress.ai/v1/accounts \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "username": "email@outlook.com",
  "password": "********"
}'

Option B: cookies

This method reuses an existing LinkedIn session. You pass the li_at cookie collected from the user's browser as the access_token field. POST it to the accounts endpoint or call the SDK.

Collect the user agent from the browser where the cookie was captured and send it in the same payload. Mismatched user agents are one of the most common causes of an account disconnecting shortly after connection.
curl --request POST \
     --url https://api.postpress.ai/v1/accounts \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "access_token": "${LI_AT_COOKIE}",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
}'

Step 2: Handle checkpoints

LinkedIn authentication may present a checkpoint that the user needs to solve. The postpress API returns the checkpoint type along with a 202 response. Detect this in your flow and render a screen or form that lets the user resolve it.

At this point a new authentication intent starts. The intent lasts 5 minutes and every checkpoint must be solved inside that window.

The checkpoint response includes the type (one of 2FA, OTP, IN_APP_VALIDATION, CAPTCHA, or PHONE_REGISTER) and the account_id you need to address every follow-up request.

{
  "object": "Checkpoint",
  "account_id": "098dez89d",
  "checkpoint": {
    "type": "2FA"
  }
}

Step 3: Solve checkpoints

Solve 2FA and OTP

Some checkpoints, like 2FA and OTP, need user input. POST the code to the solve-checkpoint endpoint or call the SDK, passing the account_id returned by the first request.

curl --request POST \
     --url https://api.postpress.ai/v1/accounts/checkpoint \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "account_id": "098dez89d",
  "code": "***"
}'

The response confirms the account is connected, or returns a new checkpoint to solve the same way.

Handle in-app validation

The IN_APP_VALIDATION checkpoint asks the user to confirm the connection in their LinkedIn mobile app. Your application listens for an account status update to detect the user action. You have two options:

Option A: long request on get account status

Make a GET request to the account endpoint. The request only resolves when the account status changes to OK. Implement a long polling loop in your backend to handle this.

Option B: account status webhook

Configure an account status webhook to receive notifications when the status changes. This is the recommended path: the webhook fires when the LinkedIn connection is confirmed and your backend reacts without polling.

Switch from in-app validation to 2FA

If the user cannot approve the connection from the LinkedIn mobile app, ask LinkedIn to propose another checkpoint method. Call the solve-checkpoint endpoint again with code: "TRY_ANOTHER_WAY".

curl --request POST \
     --url https://api.postpress.ai/v1/accounts/checkpoint \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "account_id": "098dez89d",
  "code": "TRY_ANOTHER_WAY"
}'

The response either confirms the connection or returns a new checkpoint, typically 2FA or OTP. Handle it the same way as Solve 2FA and OTP.

Phone register

You may need to provide a mobile phone number to receive a 2FA code. Use the solve-checkpoint endpoint and pass the phone number as the code, preceded by the international dialing code in brackets, for example (+33)0612345678 for France.

Resend a checkpoint notification

If the user did not receive the code or notification, call the resend-checkpoint endpoint to trigger it again. This works for 2FA, OTP, and IN_APP_VALIDATION where supported.

curl --request POST \
     --url https://api.postpress.ai/v1/accounts/checkpoint/resend \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "account_id": "098dez89d"
}'

If the resend succeeds, the API returns a CheckpointResend object:

{
  "object": "CheckpointResend",
  "account_id": "098dez89d",
  "success": true
}

Handle captcha

In a small number of cases you will receive a CAPTCHA checkpoint. You must render the captcha for the end user and submit the answer. postpress can provide a helper library for this step on request.

Step 4: Handle intent timeout

If the user takes more than 5 minutes to solve a checkpoint, the account will not be connected. Any later request against that intent first returns a 408 Request Timeout, then a 400 Bad Request as the authentication intent self-destructs.

Connect through a proxy

On step 1 you can either:

  • Pass a custom proxy object to use your own proxy, or
  • Pass a top-level country or ip field to use the postpress default proxy system.

country and ip are part of the account connection payload itself, not fields inside the proxy object.

Use your own proxy

Pass a proxy object to connect a LinkedIn account through your own proxy.

curl --request POST \
     --url https://api.postpress.ai/v1/accounts \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "proxy": {
    "port": 1123,
    "host": "proxy.com",
    "username": "username",
    "password": "********"
  },
  "username": "email@outlook.com",
  "password": "********"
}'

Use the postpress default proxy system

If you do not want to provide your own proxy, postpress can pick one for the session. Pass either:

  • country: an ISO 3166-1 alpha-2 country code, for example FR or US.
  • ip: an IPv4 address used to infer the proxy location.

Example with country:

curl --request POST \
     --url https://api.postpress.ai/v1/accounts \
     --header 'X-API-KEY: ${POSTPRESS_API_KEY}' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "provider": "LINKEDIN",
  "country": "FR",
  "username": "email@outlook.com",
  "password": "********"
}'

You can also pass ip instead of country:

{
  "provider": "LINKEDIN",
  "ip": "203.0.113.10",
  "username": "email@outlook.com",
  "password": "********"
}

When you let postpress pick the proxy, make sure to handle the additional proxy-related errors documented in the solve checkpoint reference.

Infinite login

To enable automatic reconnection for your users, the customer must configure 2FA in Authenticator app mode on their LinkedIn account. Instead of using Google Authenticator or another third-party app, they pair the secret with your own built-in TOTP generator.

You must securely store:

  • The customer's login credentials (username and password).
  • The 2FA shared secret or setup key used to generate TOTP codes.

When the account disconnects, your backend starts a new login with the stored credentials using the custom authentication flow. If a 2FA checkpoint fires, generate the TOTP code from the stored secret and solve the checkpoint automatically, with no action from the end user.

Treat the credentials and TOTP secret as the most sensitive data in your system. Encrypt them at rest, restrict access to a single backend service, and rotate any shared secret immediately if it might have been exposed.
Updated May 2026