Overview

Messaging in Linked API covers two things: sending messages and reading them. For reading, start with the inbox – it catches every new message on the account; load a person's earlier history only once, when you need it.

TaskTool
Send a message to a personst.sendMessage with personUrl
Reply into an existing conversationst.sendMessage with threadId
Archive, star, or mute a conversationst.manageConversation
Receive new messages from everyonest.syncInbox once per account, then /inbox/poll or inbox.* webhook events
Read the whole conversation with one person/inbox/poll with personUrl
Get a person's messages from before the inbox was enabledst.syncConversation once for that person

💡 For Sales Navigator, use the same flow with the nv. actions: nv.sendMessage sends InMail to people you are not connected to, and nv.syncInbox, nv.syncConversation and nv.manageConversation work like their standard counterparts. The same /inbox/poll endpoint returns both inboxes, tagged with a type.

Sending

st.sendMessage sends a message from your account, the same way you would in LinkedIn. Address it by the person's personUrl to message a 1st-degree connection, or by a threadId from inbox polling to reply into a conversation you already have – no profile URL needed. To archive, star, or mute the conversation right after sending, add st.manageConversation as a child action; on its own, it manages any conversation by threadId.

See Sending messages for examples.

Reading

Everything you read comes from one endpoint, /inbox/poll. It draws on two sources:

  • Inbox. Enable monitoring once per account with st.syncInbox. From that moment, a periodic sync captures every new message in every conversation, both incoming and the ones you send. Poll them with an advancing since, or receive them as webhook events. See Monitoring inbox.
  • History. The inbox does not import anything from before it was enabled. When you need earlier messages with a specific person, run st.syncConversation for them once. It is a one-time load, not a way to check for new messages – those keep arriving through the inbox. See Loading conversation history.

Pass personUrl to /inbox/poll to get the whole known conversation with one person from both sources, each message once. Its threads tell you how far back the history goes: if historyComplete is false and you need more, that is when to load the history.

💡 /conversations/poll, the previous way to read loaded conversations, keeps working, but new code should use /inbox/poll with personUrl.

Did this lead reply?

A common check after outreach: did the person answer your message? Enable inbox monitoring before you send – it captures only messages that arrive after it is turned on, so a reply that came earlier will not be there. Then poll /inbox/poll with their personUrl and since set a few minutes before you sent your message:

json
{
  "personUrl": "https://www.linkedin.com/in/person1",
  "since": "2023-03-14T10:20:00Z"
}

Message times are whole minutes, so a reply sent in the same minute as your message can carry a time earlier than the exact moment you sent yours. Pass the type of your message (st or nv) and take the earliest message with sender us in the result – the one you sent; later messages of yours, such as follow-ups, must not move this point. Treat a message whose sender is them and whose time is not earlier than it as the reply. If your message is not in the result yet, the periodic sync has not captured it, and the answer is not known yet – not "no reply". A them message in the same minute as yours is ambiguous: with minute precision it may have been sent just before yours. If you store people by public URL, see which URL to pass. A reply appears only after the periodic sync captures it, so an empty result means there is no reply yet – poll again later, or subscribe to the inbox.messageReceived webhook event instead of polling.

For a walkthrough of the whole flow from the first message to the reply, see How to automate LinkedIn messages.