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.
| Task | Tool |
|---|---|
| Send a message to a person | st.sendMessage with personUrl |
| Reply into an existing conversation | st.sendMessage with threadId |
| Archive, star, or mute a conversation | st.manageConversation |
| Receive new messages from everyone | st.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 enabled | st.syncConversation once for that person |
💡 For Sales Navigator, use the same flow with the
nv.actions:nv.sendMessagesends InMail to people you are not connected to, andnv.syncInbox,nv.syncConversationandnv.manageConversationwork like their standard counterparts. The same/inbox/pollendpoint returns both inboxes, tagged with atype.
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 advancingsince, 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.syncConversationfor 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/pollwithpersonUrl.
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:
{
"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.