Guide
LinkedIn in n8n: profiles, invitations and new connections by API
n8n's own LinkedIn node only creates posts, but its HTTP Request and Webhook nodes can drive a LinkedIn API. Here is how to set that up with Lempile, node by node: a credential, a workflow that reacts when someone accepts an invitation and waits for a person's OK in Slack before writing, and a paced list of invitations.
By Lempile · Updated
1. Connect an account and add the credential
Connect the LinkedIn account in Lempile first, from the dashboard or with a hosted auth link your user opens, and note its account_id. Then, in n8n, create one credential every HTTP Request node will share:
| Setting | Value |
|---|---|
| Authentication | Generic credential type |
| Generic Auth Type | Header Auth |
| Name | X-API-KEY |
| Value | Your Lempile API key |
Every call below goes to https://direct.lempile.com/api/v1 and takes the account's account_id.
2. When someone accepts an invitation, read their profile
Start the workflow with a Webhook node: method POST, a path such as linkedin-new-connection, and Authentication set to Header Auth with a header name and secret of your own. n8n gives the node a Test URL, live while you listen for a test event, and a Production URL, live once the workflow is published. Register the Production URL with Lempile once, sending your secret as a header with every delivery:
curl -sS -X POST "https://direct.lempile.com/api/v1/webhooks" \
-H "X-API-KEY: $LEMPILE_KEY" \
-H "Content-Type: application/json" \
-d '{
"request_url": "https://your-n8n.example.com/webhook/linkedin-new-connection",
"source": "users",
"name": "new-connections",
"headers": [{ "key": "x-webhook-secret", "value": "a-long-random-secret" }]
}'From then on, every accepted invitation, sent or received, starts the workflow with this payload: often within about a minute, when LinkedIn notifies the account, and otherwise at the next regular check, every 30 to 60 minutes. The Webhook node puts it under body:
{
"event": "new_relation",
"account_id": "00000000-0000-4000-8000-0000000000a1",
"webhook_name": "new-connections",
"user_full_name": "Bob Buyer",
"user_provider_id": "ACoAAAzyxwvutsrqponml",
"user_public_identifier": "bob-buyer",
"user_profile_url": "https://www.linkedin.com/in/bob-buyer/",
"timestamp": 1793260931000
}Add an HTTP Request node, GET, with the credential above, to read the new connection's profile and current job:
https://direct.lempile.com/api/v1/users/{{ $json.body.user_provider_id }}
?account_id={{ $json.body.account_id }}&linkedin_sections=experienceIt answers the profile with headline, location and work_experience; every field is in LinkedIn profile API and the profiles docs.
3. Wait for a person's OK, then send
Keep a person in the loop for anything that writes. Draft the welcome message from the profile, then add a Slack node with the operation Send and Wait for Response: n8n posts the draft and holds the workflow until someone answers, right in Slack. Route the answer with an IF node, and on approval send the message with one more HTTP Request node, POST to /chats, JSON body:
{
"account_id": "{{ $('Webhook').item.json.body.account_id }}",
"attendees_ids": ["{{ $('Webhook').item.json.body.user_provider_id }}"],
"text": "Thanks for connecting, {{ $('Webhook').item.json.body.user_full_name.split(' ')[0] }}!"
}- Add the header
Idempotency-Key, for examplewelcome-followed by the provider id. If n8n retries the node, LinkedIn still gets one message. - While you build, add
?dry_run=trueto the URL: Lempile answers with exactly what LinkedIn would receive and sends nothing. Remove it when the output looks right.
4. Send invitations from a list, paced
For a list of people, a Google Sheet for example, loop over the rows and send each invitation with an HTTP Request node, POST to /users/invite:
{
"account_id": "{{ $json.account_id }}",
"provider_id": "{{ $json.profile_url }}",
"message": "{{ $json.note }}"
}provider_idtakes a profile URL, a public identifier or a provider id. Keep the note under 200 characters, LinkedIn's own limit for connection notes (LinkedIn character limits).- Someone already connected or already invited answers
422with a cleartype, such aserrors/already_connected, so set the node's On Error to continue with the error output and log those rows instead of stopping. - Space the calls with the HTTP Request node's Batching option (Items per Batch 1 and a Batch Interval), and remember LinkedIn's own pace: LinkedIn connection and invitation limits.
Pacing and errors
Lempile paces each account itself: one LinkedIn call at a time, 1.5 to 3 seconds apart, at most 1,500 calls and 150 writes a day, and a 15-minute rest when LinkedIn asks the account to slow down. A call over a limit answers 429 with retry_after. Turn on the node's Retry On Fail for those, and keep the Idempotency-Key on every write so a retry never sends twice. The full list is in the errors and limits docs.
Coming from Unipile
Lempile answers Unipile's LinkedIn paths, fields, status codes and error types, and sends Unipile's webhook payloads. HTTP Request nodes built for Unipile keep working once their base URL and key point at Lempile; the migration guide lists the differences.