Guide
How to send LinkedIn messages with an API
LinkedIn has no general API for messages. There are two official routes, both for approved partners only, and one unofficial route that works from a member's own account. Here is each, with what it takes and the code for the last.
By Lempile · Updated
The two official routes
| Route | What it covers | Who can use it |
|---|---|---|
| Page messaging | A Company Page's messages, through the Marketing APIs | Marketing apps LinkedIn approves |
| Sales Navigator (SNAP) | Connecting and messaging leads, InMail included, inside a CRM | Approved partners; no new partners accepted |
Neither lets an ordinary app send a member's own one-to-one messages, and LinkedIn offers no official API for connection invitations. See Does LinkedIn have an API? for the full list of what's open.
The unofficial route: the member's own account
APIs like Lempile and Unipile send messages from the member's own LinkedIn account. The member connects it once, through a hosted link, and your code then starts conversations and replies as them. Lempile answers Unipile's paths, so the same code works with both.
1. Connect the account
Create a hosted auth link (POST /api/v1/hosted/accounts/link), send it to your user, and keep the account_id you get back. Details in Authentication and accounts.
2. Start a conversation
curl -X POST "https://direct.lempile.com/api/v1/chats" \
-H "X-API-KEY: $LEMPILE_KEY" \
-H "Idempotency-Key: first-message-bob" \
-H "Content-Type: application/json" \
-d '{
"account_id": "'"$ACCOUNT_ID"'",
"attendees_ids": ["https://www.linkedin.com/in/bob-buyer"],
"text": "Hi Bob, quick question about your post."
}'
# 201 { "object": "ChatStarted", "chat_id": "2-QUFB…", "message_id": "2-_vpt…" }attendees_ids takes one person, as a profile URL, a public identifier or LinkedIn's member id. The Idempotency-Key means a retry never sends the message twice.
3. Reply in a conversation
curl -X POST "https://direct.lempile.com/api/v1/chats/$CHAT_ID/messages" \
-H "X-API-KEY: $LEMPILE_KEY" \
-H "Idempotency-Key: reply-42" \
-H "Content-Type: application/json" \
-d '{ "account_id": "'"$ACCOUNT_ID"'", "text": "Thanks, Tuesday works for me." }'
# 201 { "object": "MessageSent", "message_id": "2-_vpt…" }4. Get replies as they arrive
Register a messaging webhook: Lempile keeps LinkedIn's own live connection open for the account and posts each new message, read receipt or reaction to your URL within seconds. See Webhooks.
Who you can message
LinkedIn decides, and Lempile checks the profile's “Message” option first, as LinkedIn's own page does:
| Case | What happens |
|---|---|
| A connection, an open profile, or someone who wrote first | The message is sent |
| Anyone else | 422 no_connection_with_recipient, or an InMail if you ask for one and the account has credit |
| The account itself | 422 invalid_recipient |
Limits and safeguards
- A message takes up to 8,000 characters.
- Each account sends one call at a time, 1.5 to 3 seconds apart, and at most 150 writes (messages, invitations, posts, comments) in any 24 hours.
- Add
?dry_run=trueto see exactly what LinkedIn would receive, without sending it. - Every newly connected account starts with writes off; Lempile turns them on per account, and dry runs work meanwhile.
Details in Errors and limits.
The risk to know about
LinkedIn's User Agreement asks members not to use bots or other unauthorized automated methods to send messages, and lets LinkedIn restrict accounts. Sending from a member's own account carries that risk, with Lempile as with any other tool. Pacing, one session and one IP per account, and messages people expect keep it low; no API can remove it.