New Messages
Salesflow’s New Messages Webhook notifies your system whenever an inbox synchronization is performed. This allows you to receive updates when needed and keep your internal messaging system.
Prerequisites
-
You configured a webhook via the Webhooks page in Salesflow. Once set up, the system will send a POST request to your webhook URL when you’re requesting synchronization.
-
Your webhook endpoint is reachable over HTTPS.
-
You verify the secret on every delivery (
X-Webhook-Secret
). -
You trigger a sync via:
-
Inbox Sync:
POST /conversations/sync
— walks from the newest items down to the dates you pass (from-dates) and stops. -
Specific Conversation Sync:
POST /conversations/{id}/sync
— walks the entire conversation from newest to the start (no date window).
-
See: Messaging & Chats → Sync Inbox or Specific Conversation
https://salesflow.apidocumentation.com/documentation/messaging-chats/sync-inbox-or-specific-conversation
How it works (single trigger → streamed webhooks)
You call the sync endpoint once. Our backend then runs a paginated crawl and streams results to your webhook in this order:
Inbox Sync run (newest → down to your dates)
For each inbox page:
-
Stage A — CONVERSATIONS
We fetch one page of conversations (with metadata) and send a webhook withSyncType: "CONVERSATIONS"
containing that page.
→ Persist these conversations byConversationId
. -
Stage B — MESSAGES (per conversation)
For each conversation from that page, we fetch messages page-by-page (newest → older) and send one webhook per message page withSyncType: "MESSAGES"
.
We continue paging messages until we reach the from-dates you provided for this run.
Only after we finish all conversations from the current inbox page do we move to the next inbox page, and repeat (A→B) — until the stop dates are reached.
Specific Conversation Sync run
-
We do only Stage B for the requested conversation: stream
MESSAGES
pages (newest → older) until the beginning of the thread (full history).
Important: deliveries are asynchronous. A MESSAGES
webhook can arrive before its CONVERSATIONS
page for the same ConversationId
. Design for out-of-order.
You do not need to re-call the sync endpoint to get subsequent pages — the run continues until finished (we’ll indicate completion).
Security & Response
-
Verify
X-Webhook-Secret
on every request; reject if missing/invalid. -
Respond quickly: return HTTP 200 OK within a few seconds; process asynchronously.
-
Deliveries are at-least-once; on non-2xx/timeouts we may retry.
General webhook payload example (top level)
{
"EventType": "NEW_MESSAGE",
"Payload": {
"Data": {...},
"Error": {...},
"SyncFinished": null
},
"LinkedInAccountId": 1234,
"LinkedInEmail": "linkedin@account.email"
}
Property |
Type |
Description |
---|---|---|
|
string |
Indicates the type of event — in this case, |
|
object |
Contains the main event data. |
└ |
object | null |
If present - data with subscription or messages information |
└ |
object | null |
If present - Sync failed. Also will be present information with data to try resync again |
└ |
boolean | null |
If true - sync is finished. |
|
int64 |
Account Id |
|
string |
Account email |
Variant A — SyncType: "CONVERSATIONS"
(one inbox page)
Payload.Data
:
{
"SyncType": "CONVERSATIONS",
"Conversations": {
"MemberParticipants": [
{
"LinkedInMemberId": 111,
"ProfileId": "AAA",
"FirstName": "Volodimir",
"LastName": "Dem",
"Headline": ".NET Developer",
"Distance": "DISTANCE_1"
},
{
"LinkedInMemberId": 222,
"ProfileId": "BBB",
"FirstName": "Josiane",
"LastName": "Delport",
"Headline": "DK Group Development Manager",
"Distance": "SELF",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 333,
"ProfileId": "CCC",
"FirstName": "Franklin",
"LastName": "Tab",
"Headline": "Senior Growth Manager @ LinkedIn | Brand Marketing",
"Distance": "DISTANCE_3",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 444,
"ProfileId": "DDD",
"FirstName": "Tiffany",
"LastName": "Lab",
"Headline": "Chargé de recrutement / Consultant en recrutement / Acquisition de talents",
"Distance": "DISTANCE_2",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 555,
"ProfileId": "EEE",
"FirstName": "Ilya",
"LastName": "Chukhn",
"Headline": "Principal Software Engineer | ex-Google, ex-Huawei",
"Distance": "DISTANCE_1",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 666,
"ProfileId": "FFF",
"FirstName": "Akhyar",
"LastName": "Ah",
"Headline": "Procurement Manager | MBA - CIPS",
"Distance": "DISTANCE_1",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 777,
"ProfileId": "GGG",
"FirstName": "saeid",
"LastName": "kaze",
"Headline": "Founder & Po at Applymorning",
"Distance": "DISTANCE_1",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 888,
"ProfileId": "HHH",
"FirstName": "Asif Ahmed",
"LastName": "Barb",
"Headline": "DevOps/DevSecOps and Cloud Professional (CI/CD | GitOps | Docker | Kubernetes-CKAD| AWS | Azure | Infrastructure as Code | Cloud Security and FinOps | Prometheus )",
"Distance": "DISTANCE_1",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
},
{
"LinkedInMemberId": 999,
"ProfileId": "III",
"FirstName": "Muhammed ",
"LastName": "Has ",
"Headline": "Senior SAP Sales Manager driving revenue growth and client satisfaction",
"Distance": "DISTANCE_2",
"ProfilePictureUrl": "https://url_to_picture_image",
"ProfilePictureUrlLarge": "https://url_to_large_picture_image"
}
],
"Conversations": [
{
"UnreadCount": 1,
"CreatedAt": "2025-07-15T09:58:03.613Z",
"LastReadAt": "2025-07-31T11:57:46.742Z",
"LastActivityAt": "2025-08-01T08:00:26.586Z",
"GroupChat": false,
"Read": false,
"ConversationId": "CONV-ID-1",
"IsCreatedByThisAccount": false,
"Categories": [
"INBOX",
"PRIMARY_INBOX"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"ADD_PARTICIPANT",
"RENAMED_CONVERSATION",
"REMOVE_PARTICIPANT",
"CREATE_GROUP_CHAT_LINK"
],
"Participants": [
{
"MemberProfileId": "HHH"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 0,
"CreatedAt": "2024-07-22T08:39:43.531Z",
"LastReadAt": "2025-07-31T14:36:25.686Z",
"LastActivityAt": "2025-07-31T14:36:16.097Z",
"GroupChat": false,
"Read": true,
"ConversationId": "CONV-ID-2",
"IsCreatedByThisAccount": false,
"Categories": [
"INBOX",
"PRIMARY_INBOX",
"INMAIL"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"REPLY_TO_MESSAGE",
"REPLY",
"SEND_EXTERNAL_MEDIA_MESSAGE",
"REACTIONS",
"CREATE_GROUP_CHAT_LINK",
"SEND_VOICE_MESSAGE",
"DELETE_MESSAGE",
"ADD_PARTICIPANT",
"EDIT_MESSAGE",
"CREATE_NEW_GROUP_CHAT",
"RENAMED_CONVERSATION",
"CREATE_LINKEDIN_VIRTUAL_MEETING",
"DISPLAY_URL_AS_LINK_IN_MESSAGE",
"REMOVE_PARTICIPANT",
"SEND_VIDEO_MESSAGE"
],
"Participants": [
{
"MemberProfileId": "GGG"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 0,
"CreatedAt": "2025-07-31T10:16:18.741Z",
"LastReadAt": "2025-07-31T10:44:41.352Z",
"LastActivityAt": "2025-07-31T10:16:18.858Z",
"GroupChat": false,
"Read": true,
"ConversationId": "CONV-ID-3",
"State": "PENDING",
"IsCreatedByThisAccount": true,
"Categories": [
"INBOX",
"PRIMARY_INBOX",
"INMAIL"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"REPLY_TO_MESSAGE",
"SEND_EXTERNAL_MEDIA_MESSAGE",
"REACTIONS",
"CREATE_GROUP_CHAT_LINK",
"SEND_VOICE_MESSAGE",
"DELETE_MESSAGE",
"ADD_PARTICIPANT",
"EDIT_MESSAGE",
"REPLY",
"CREATE_NEW_GROUP_CHAT",
"RENAMED_CONVERSATION",
"CREATE_LINKEDIN_VIRTUAL_MEETING",
"REMOVE_PARTICIPANT",
"SEND_VIDEO_MESSAGE"
],
"Participants": [
{
"MemberProfileId": "FFF"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 0,
"CreatedAt": "2025-07-31T06:29:28.125Z",
"LastReadAt": "2025-07-31T07:45:55.94Z",
"LastActivityAt": "2025-07-31T06:29:28.157Z",
"GroupChat": false,
"Read": true,
"ConversationId": "CONV-ID-4",
"IsCreatedByThisAccount": false,
"Categories": [
"INBOX",
"PRIMARY_INBOX"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"ADD_PARTICIPANT",
"RENAMED_CONVERSATION",
"REMOVE_PARTICIPANT",
"CREATE_GROUP_CHAT_LINK"
],
"Participants": [
{
"MemberProfileId": "EEE"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 2,
"CreatedAt": "2025-07-27T09:45:05.359Z",
"LastActivityAt": "2025-07-30T12:16:11.58Z",
"GroupChat": false,
"Read": false,
"ConversationId": "CONV-ID-5",
"IsCreatedByThisAccount": false,
"Categories": [
"INBOX",
"PRIMARY_INBOX"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"ADD_PARTICIPANT",
"RENAMED_CONVERSATION",
"REMOVE_PARTICIPANT",
"CREATE_GROUP_CHAT_LINK"
],
"Participants": [
{
"MemberProfileId": "DDD"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 0,
"CreatedAt": "2025-07-30T11:18:31.582Z",
"LastReadAt": "2025-07-31T14:09:42.882Z",
"LastActivityAt": "2025-07-30T11:18:31.618Z",
"GroupChat": false,
"Read": true,
"ConversationId": "CONV-ID-6",
"IsCreatedByThisAccount": false,
"Categories": [
"INBOX",
"PRIMARY_INBOX"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"ADD_PARTICIPANT",
"RENAMED_CONVERSATION",
"REMOVE_PARTICIPANT",
"CREATE_GROUP_CHAT_LINK"
],
"Participants": [
{
"MemberProfileId": "III"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 0,
"CreatedAt": "2025-07-25T14:31:42.674Z",
"LastReadAt": "2025-07-31T11:57:35.08Z",
"LastActivityAt": "2025-07-25T14:31:42.71Z",
"GroupChat": false,
"Read": true,
"ConversationId": "CONV-ID-7",
"IsCreatedByThisAccount": false,
"Categories": [
"INBOX",
"PRIMARY_INBOX"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"ADD_PARTICIPANT",
"RENAMED_CONVERSATION",
"REMOVE_PARTICIPANT",
"CREATE_GROUP_CHAT_LINK"
],
"Participants": [
{
"MemberProfileId": "AAA"
},
{
"MemberProfileId": "BBB"
}
]
},
{
"UnreadCount": 0,
"CreatedAt": "2025-07-22T12:48:31.756Z",
"LastReadAt": "2025-07-24T13:59:41.307Z",
"LastActivityAt": "2025-07-22T12:48:31.85Z",
"GroupChat": false,
"Read": true,
"ConversationId": "CONV-ID-8",
"State": "PENDING",
"IsCreatedByThisAccount": true,
"Categories": [
"INBOX",
"PRIMARY_INBOX",
"INMAIL"
],
"DisabledFeatures": [
"UPDATE_MESSAGE_REQUEST_STATE",
"REPLY_TO_MESSAGE",
"SEND_EXTERNAL_MEDIA_MESSAGE",
"REACTIONS",
"CREATE_GROUP_CHAT_LINK",
"SEND_VOICE_MESSAGE",
"DELETE_MESSAGE",
"ADD_PARTICIPANT",
"EDIT_MESSAGE",
"REPLY",
"CREATE_NEW_GROUP_CHAT",
"RENAMED_CONVERSATION",
"CREATE_LINKEDIN_VIRTUAL_MEETING",
"REMOVE_PARTICIPANT",
"SEND_VIDEO_MESSAGE"
],
"Participants": [
{
"MemberProfileId": "CCC"
},
{
"MemberProfileId": "BBB"
}
]
}
],
"InboxType": "LINKEDIN"
}
}
Data:
Property |
Type |
Description |
---|---|---|
|
string |
Indicates the type of payload for |
└ |
object | null |
Not null when |
└ |
array |
List of all members participating in conversations related to the message event. |
└ |
array |
List of all conversations filtered by requested conditions on the queried page |
└ |
string |
Indicates the type of the requested inbox. |
└ |
object | null |
Null when |
Conversations.MemberParticipant object:
Property |
Type |
Description |
---|---|---|
|
int64 |
LinkedIn's unique internal member ID |
|
string |
Internal profile identifier. |
|
string | null |
Profile’s first name. |
|
string | null |
Profile’s last name. |
|
string | null |
Professional headline as shown on their profile. |
|
string | null |
Connection level (e.g., |
|
string | null |
URL to a 100x100 profile photo. |
|
string | null |
URL to a larger (800x800) profile photo. |
Conversations.Conversation object:
Field |
Type |
Description |
---|---|---|
|
Int64 | null |
Number of unread messages in the conversation. |
|
date |
When the conversation was created. |
|
date, | null |
When the last message in the conversation was read by the authenticated user. |
|
date | null |
Timestamp of the most recent message/activity in the conversation. |
|
boolean | null |
Indicates if the conversation is a group chat. |
|
boolean | null |
Whether the latest message has been read. |
|
string |
Unique identifier for the conversation. |
|
boolean |
Indicates if the authenticated user initiated the conversation. |
|
string | null |
Conversation status (created by inmail message) (e.g., |
|
array | null |
Tags that define the type of conversation (e.g., |
|
array | null |
List of disabled features for the conversation (e.g., |
|
array |
Member identifiers in the conversation. |
What to do
-
Upsert each conversation by (
LinkedInAccountId
,ConversationId
). -
Upsert
MemberParticipants
(profile mapping) byLinkedInMemberId
. -
Expect subsequent
MESSAGES
pages for each conversation from this page.
Variant B — SyncType: "MESSAGES"
(messages page for one conversation)
Every NEW_MESSAGE
delivery includes a Payload.Data.Messages
object. Within it, Events[]
holds the actual messages you must process. The content of each event lives inside MessageEvent
, which can appear in three shapes:
-
Regular:
MessageEvent
withText
/Body
/Attachments
-
Forwarded:
MessageEvent
withForwardedContent
-
InMail:
MessageEvent
withInMailContent
Use the tables below to parse each shape predictably.
Example of Payload.Data for Regular message
:
{
"SyncType": "MESSAGES",
"Messages": {
"ConversationId": "2-NjcxODg3MzgtNDliZC00MjA2LWI0MzQtZTMxZWJlMGFhODdmXzEwMA==",
"Profiles": [
{
"LinkedInMemberId": 1280758798,
"ProfileId": "ACoAAExW1A4BXw6Fsys_BhrDzjoEF290dTPEUrA",
"FirstName": "Josiane",
"LastName": "Delport",
"PublicIdentifier": "josiane-delport-a3ab0b2b8",
"Occupation": "DK Group Development Manager",
"BackgroundPictureUrl": "https://media.licdn.com/dms/image/v2/D4D16AQHp9DeL5JsfZA/profile-displaybackgroundimage-shrink_350_1400/profile-displaybackgroundimage-shrink_350_1400/0/1733411402731?e=1756944000&v=beta&t=gcztNDAVHoLw5w1AN6KVAiyBH-iABW1MZuftWeIfYnQ",
"ProfilePictureUrl": "https://media.licdn.com/dms/image/v2/D4D03AQFYxFRdVdUeow/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1709791882893?e=1756944000&v=beta&t=-OZZ__DhDB6iUKhABNI7dD-qWAg5OxjLB951uecBBFw",
"ProfilePictureUrlLarge": "https://media.licdn.com/dms/image/v2/D4D03AQFYxFRdVdUeow/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1709791882893?e=1756944000&v=beta&t=V7-HTrTwU0zzu6Aqslr3QEn6EPRAPAveY5pCYGqXRgY"
}
],
"Events": [
{
"CreatedAt": "2025-07-12T10:15:43.656Z",
"SubType": "MEMBER_TO_MEMBER",
"MessageId": "2-MTc1MjMxNTM0MzY1NmI0MzYxMC0xMDAmNjcxODg3MzgtNDliZC00MjA2LWI0MzQtZTMxZWJlMGFhODdmXzEwMA==",
"MessageEvent": {
"Body": "",
"Text": "Hi Ananth Nag, i will be so happy to connect !",
"Attachments": [
]
},
"ReactionSummaries": [
],
"From": {
"MessagingMemberProfileId": "ACoAAExW1A4BXw6Fsys_BhrDzjoEF290dTPEUrA"
}
}
],
"ConversationSyncFinished": false,
"InboxType": "LINKEDIN"
}
}
Example of Payload.Data for InMail message
:
{
"EventType": "NEW_MESSAGE",
"Payload": {
"Data": {
"Messages": {
"ConversationId": "2-NDQyMTc3NDAtYzdlZi00Y2U3LTk4NjYtNjhiYzNmN2YxNDVhXzEwMA==",
"Profiles": [
{
"LinkedInMemberId": 760655377,
"ProfileId": "ACoAAC1WrhEBnrh7ko6jZaTsK_2gOux5Q5edfMg",
"FirstName": "Béatrice",
"LastName": "AUGER",
"PublicIdentifier": "béatrice-auger-1018aa192",
"Occupation": "Responsable Recrutement et Ressources humaines chez Exens Ingénierie | Psychologie du travail",
"BackgroundPictureUrl": "https://media.licdn.com/dms/image/v2/D4D16AQF_D5V5frgHEQ/profile-displaybackgroundimage-shrink_350_1400/profile-displaybackgroundimage-shrink_350_1400/0/1730823975154?e=1758153600&v=beta&t=oO6pODi-Qv9JKvV7D1Oc-N05l1MD0F5ik9aW-uyKaaU",
"ProfilePictureUrl": "https://media.licdn.com/dms/image/v2/D4D03AQHOw3LekCEtzg/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1714138375047?e=1758153600&v=beta&t=r4ItTKjdKnDakjnQzTsdzj52CunqVp9KTCxciWlJgrk",
"ProfilePictureUrlLarge": "https://media.licdn.com/dms/image/v2/D4D03AQHOw3LekCEtzg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1714138375047?e=1758153600&v=beta&t=TkURG1zL1D_euUgcq-n0JTMEQbYonxQdAojaCZ6YK98"
}
],
"Events": [
{
"CreatedAt": "2025-05-21T06:19:31.426Z",
"SubType": "INMAIL",
"MessageId": "2-MTc0NzgwODM3MTE4NGI0MzQzMy0xMDAmNDQyMTc3NDAtYzdlZi00Y2U3LTk4NjYtNjhiYzNmN2YxNDVhXzEwMA==",
"MessageEvent": {
"Body": "",
"Subject": "Opportunité : Business development specialist chez Exens Ingénierie à Lyon",
"Text": "Bonjour Josiane,\n\nJe me permets de vous contacter car votre parcours en business development a attiré mon attention. \n\nChez Exens, société de conseil en ingénierie basée à Lyon, nous amorçons une phase de structuration commerciale ambitieuse après 2,5 ans d'activité. Nous cherchons un profil capable d'allier vision stratégique, data et exécution commerciale, pour renforcer notre équipe et maximiser la transformation de nos actions de prospection en opportunités réelles. \n\nLe rôle est transversal et clé : segmentation des marchés, qualification des leads, campagnes automatisées, KPIs, accompagnement des ingénieurs d'affaires dans la préparation et la conversion des rendez-vous. Une vraie mission à impact. \n\nJe serais ravie d'échanger avec vous quelques minutes pour en discuter. Êtes-vous ouverte à un court échange cette semaine ou la prochaine ? \n\nBien cordialement, \n\nBéatrice AUGER \nResponsable Recrutement/ Ressources humaines & Psychologue du travail\n\nBéatrice AUGER\nResponsable Recrutement/ Ressources humaines & Psychologue du travail",
"InMailContent": {
"InmailType": "JOB_INQUIRIES",
"ClickToReplyInmail": false,
"RecruiterInmail": true,
"InmailProductType": "RECRUITER"
}
},
"ReactionSummaries": [],
"From": {
"MessagingMemberProfileId": "ACoAAC1WrhEBnrh7ko6jZaTsK_2gOux5Q5edfMg"
}
}
],
"ConversationSyncFinished": true,
"InboxType": "LINKEDIN"
},
"SyncType": "MESSAGES"
},
"SyncFinished": true
},
"LinkedInAccountId": 8969,
"LinkedInEmail": "josiane.delport34@laposte.net"
}
Example of Payload.Data for Forwarded message
:
{
"EventType": "NEW_MESSAGE",
"Payload": {
"Data": {
"Messages": {
"ConversationId": "2-NzkyNjQ1ZGItYjE2Yi00MDQ0LTliZGItMjZhZjcxYzg1OTQ0XzEwMA==",
"Profiles": [
{
"LinkedInMemberId": 717285120,
"ProfileId": "ACoAACrA5wABV_zTuyfQqQTn18Gx55y1aQSkUlA",
"FirstName": "Volodimir",
"LastName": "Demiak",
"PublicIdentifier": "volodimir-demiak-680273180",
"Occupation": ".NET Developer"
},
{
"LinkedInMemberId": 1280758798,
"ProfileId": "ACoAAExW1A4BXw6Fsys_BhrDzjoEF290dTPEUrA",
"FirstName": "Josiane",
"LastName": "Delport",
"PublicIdentifier": "josiane-delport-a3ab0b2b8",
"Occupation": "DK Group Development Manager",
"BackgroundPictureUrl": "https://media.licdn.com/dms/image/v2/D4D16AQHp9DeL5JsfZA/profile-displaybackgroundimage-shrink_350_1400/profile-displaybackgroundimage-shrink_350_1400/0/1733411402731?e=1758153600&v=beta&t=xgo9kBkHYQrVW9FD41YPUI6HuJYl_f0QzA7IfXJbI2w",
"ProfilePictureUrl": "https://media.licdn.com/dms/image/v2/D4D03AQFYxFRdVdUeow/profile-displayphoto-shrink_100_100/profile-displayphoto-shrink_100_100/0/1709791882893?e=1758153600&v=beta&t=v_UkGT78da1biUEGXLXD_TsTgQBSef1Tm72BJr-3jtw",
"ProfilePictureUrlLarge": "https://media.licdn.com/dms/image/v2/D4D03AQFYxFRdVdUeow/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1709791882893?e=1758153600&v=beta&t=eHxH0vOLODv_B1h-lni8zvEwRIadgK4V774dePj1QSc"
},
{
"LinkedInMemberId": 640381435,
"ProfileId": "ACoAACYrcfsBfmMAfQHwgdeoT7XppQU7ekeYMio",
"FirstName": "Valentyna",
"LastName": "Boiko",
"PublicIdentifier": "valentyna-boikoo",
"Occupation": "IT Talent Acquisition | Development Lead at ExtTech Development",
"BackgroundPictureUrl": "https://media.licdn.com/dms/image/v2/D4D16AQGC8pqIf0FHvQ/profile-displaybackgroundimage-shrink_350_1400/B4DZijqV9iH8AY-/0/1755092443557?e=1758153600&v=beta&t=eIYfAqtMO-MNPRhZaBGm8lIB1IIvgEBOq2JGdr_LRA4"
}
],
"Events": [
{
"CreatedAt": "2025-08-01T08:00:26.586Z",
"SubType": "MEMBER_TO_MEMBER",
"MessageId": "2-MTc1NDAzNTIyNjU4NmI0ODA5NS0xMDAmNzkyNjQ1ZGItYjE2Yi00MDQ0LTliZGItMjZhZjcxYzg1OTQ0XzEwMA==",
"PreviousMessageInConversation": "2-MTc1Mzk1OTU0NjY0OWI5MzYzMS0xMDAmNzkyNjQ1ZGItYjE2Yi00MDQ0LTliZGItMjZhZjcxYzg1OTQ0XzEwMA==",
"MessageEvent": {
"Body": "",
"Text": "test again",
"ForwardedContent": {
"OriginalCreatedAt": "2025-03-26T14:45:17.483Z",
"ForwardedContentType": "TEXT",
"ForwardedBody": "Привіт :hugging_face:\n\nЗапрошую доєднатись до нашої Telegram-спільноти, де ми публікуємо:\n:computer: Безкоштовні курси | вебінари | івенти.\n:clipboard: Свіжі вакансії, актуальні новини.\n\nНаприклад, сьогодні опублікований пост \"Безкоштовні вебінари-івенти з 26.03-29.03», також попередні пост «Збірник ресурсів для вивчення англійської: рівні A2-B2»\n\nПриєднуйтесь за посиланням: https://t.me/+w8Z1Y79BdhtkNzNi (@dostupne_it)\n\nБуду рада бачити вас у нашій спільноті! :white_heart:",
"OriginalFrom": {
"MessagingMemberProfileId": "ACoAACYrcfsBfmMAfQHwgdeoT7XppQU7ekeYMio"
}
}
},
"ReactionSummaries": [],
"From": {
"MessagingMemberProfileId": "ACoAACrA5wABV_zTuyfQqQTn18Gx55y1aQSkUlA"
}
} ],
"InboxType": "LINKEDIN"
},
"SyncType": "MESSAGES"
}
},
"LinkedInAccountId": 8969,
"LinkedInEmail": "josiane.delport34@laposte.net"
}
Envelope (MESSAGES)
Path |
Field |
Type |
Notes |
---|---|---|---|
|
|
string |
|
|
|
string |
Link every message to this conversation |
|
|
array |
List profiles who send messages. (List can have only 1 profile, in case when all messages in payload are from same sender) |
|
|
array |
Each array item is a message event (see next table) |
|
|
boolean |
Nullable boolean value. |
|
|
string |
|
Events[]
— Common Message Fields
Path |
Field |
Type |
Description / Notes |
---|---|---|---|
|
|
date |
Original creation timestamp (use for ordering within a conversation) |
|
|
string |
|
|
|
string |
Unique identifier for the message. |
|
|
string |
Author’s profileId; compare with your account to detect inbound/outbound |
|
|
array | null |
Array of emoji reactions to the message.
|
|
|
string | null |
Present on some events (e.g., forwarded) for referencing threading |
|
|
object |
Content object — shape varies by type (tables below) |
MessageEvent Base Structure
Property |
Type |
Description |
---|---|---|
|
string | null |
Message Body (Can be empty, depends of message event type). |
|
string | null |
Message Subject (Can be empty, depends of message event type). |
|
string | null |
Message Text (Can be empty, depends of message event type). |
|
date, | null |
Nullable date when message was last time edited. |
|
object | null |
See |
|
object | null |
See |
|
object | null |
See |
Regular MessageEvent (Member-to-Member)
When does it occur?
-
SubType == "MEMBER_TO_MEMBER"
-
MessageEvent
does not containInMailContent
andForwardedContent
Path |
Field |
Type |
Notes |
---|---|---|---|
|
|
string |
Display text |
|
|
string |
Raw body (can be empty) |
|
|
array |
Files/links if present |
MessageEvent with ForwardedContent
Detection rule: MessageEvent.ForwardedContent
exists.
Path |
Field |
Type |
Notes |
---|---|---|---|
|
|
string |
Wrapper’s text (if any) |
|
|
string |
Wrapper’s body (if any) |
|
|
array |
Wrapper’s attachments |
|
|
date | null (ISO-8601) |
Timestamp of the original forwarded message |
|
|
string | null |
e.g., |
|
|
string | null |
Text of the forwarded message |
|
|
string |
Author of the forwarded message |
MessageEvent with InMailContent
Detection rule: MessageEvent.InMailContent
exists (also SubType == "INMAIL"
).
Path |
Field |
Type |
Notes |
---|---|---|---|
|
|
string |
InMail subject |
|
|
string |
InMail body text |
|
|
string | null |
e.g., |
|
|
boolean |
Reply capability |
|
|
boolean |
Sent via Recruiter |
|
|
string |
Inmail product type, like |
Profiles[]
Field |
Type |
Notes |
---|---|---|
|
int64 |
LinkedIn's unique internal member ID. |
|
string |
Join key; match with |
|
string | null |
Display name |
|
string | null |
Public LinkedIn URL segment ( |
|
string | null |
Job title on LinkedIn. |
|
string | null |
URL to the user's LinkedIn background photo. |
|
string | null |
Small profile pictureSmall profile picture. |
|
string | null |
Large version of profile picture. |
ThirdPartyMedia:
Property |
Type |
Description |
---|---|---|
MediaType |
string | null |
Media type. |
Title |
string | null |
Title |
Id |
string |
Third party media identifier |
GifUrl |
string | null |
Url for image |
PreviewGifUrl |
string | null |
Url for image preview |
Parsing & Handling Flow (developer checklist)
-
Envelope & routing
-
Ensure
Payload.Data.SyncType == "MESSAGES"
. -
Read
ConversationId
,Events[]
,Profiles[]
.
-
-
For each
Events[i]
-
Read identity:
MessageId
,CreatedAt
,From.MessagingMemberProfileId
,SubType
. -
Detect content shape (in order):
-
If
MessageEvent.InMailContent
→ InMail -
Else if
MessageEvent.ForwardedContent
→ Forwarded -
Else → Regular
-
-
Direction: inbound/outbound by comparing
From.MessagingMemberProfileId
with your account’s profileId. -
Normalize into your model and UPSERT by (
LinkedInAccountId
,ConversationId
,MessageId
).
-
-
Change detection (edits)
-
Compare mutable fields (text/body, attachments, reactions, and the mutable sub-objects of InMail/Forwarded).
-
If changed → UPDATE only the changed fields.
-
If identical → no-op (don’t re-emit notifications/counters).
-
-
Out-of-order safety
-
If the conversation is unknown, create a placeholder by
ConversationId
(link messages now, upsert conversation metadata later when theCONVERSATIONS
page arrives).
-
-
Ordering & UI
-
Inside a conversation, sort by
CreatedAt
(UTC) for display/logic. -
Use
ConversationSyncFinished
to know if more message pages are coming for this conversation in the current run.
-
-
Duplicates
-
Deliveries are at-least-once; the same message can reappear (retries/overlap).
-
With UPSERT + change detection, duplicates become no-ops.
-
Quick Type Detection Rules (copy/paste)
-
InMail:
MessageEvent.InMailContent
exists (and usuallySubType == "INMAIL"
). -
Forwarded:
MessageEvent.ForwardedContent
exists. -
Regular: neither
InMailContent
norForwardedContent
are present (typicallySubType == "MEMBER_TO_MEMBER"
).
What to do
-
Ensure the conversation exists (create a placeholder by
ConversationId
if you haven’t seen it yet). -
Upsert each message by (
LinkedInAccountId
,ConversationId
,MessageId
); link to the conversation. -
Use
ConversationSyncFinished
to know whether more message pages are expected for this conversation within the same run.
Ordering & duplicates (must-read)
-
Out-of-order:
MESSAGES
can arrive beforeCONVERSATIONS
.-
Create a placeholder conversation keyed by
ConversationId
; attach messages. -
When the
CONVERSATIONS
page arrives, upsert metadata into the placeholder.
-
-
Duplicates: The same conversation or the same message can arrive more than once (retries, overlapping ranges, repeated runs).
-
With UPSERT + unique keys, storage stays correct;
-
For business logic, if an upsert produced no field changes, treat it as a no-op (don’t re-fire notifications, counters, downstream events).
-
-
Parallel runs: Avoid overlapping runs for the same account unless you’re prepared for extra duplicates and interleaved deliveries.
Run completion
At the end of the run we set Payload.SyncFinished = true
.
Use this to mark the sync run as finished on your side (useful for job orchestration and dashboards).
Minimal processing flow (reference)
-
Verify
X-Webhook-Secret
→ return 200 OK quickly. -
Enqueue payload for async handling.
-
Switch by
SyncType
:-
CONVERSATIONS
→ upsert conversations & participants. -
MESSAGES
→ ensure conversation (placeholder if needed) → upsert messages (with edit detection).
-
-
If upsert produced no changes, treat as no-op for side effects.
-
Order messages by
CreatedAt
(UTC) within eachConversationId
. -
On
Payload.SyncFinished == true
→ mark the run complete.
Error Handling
If synchronization fails, the webhook includes Payload.Error
and Payload.Data
is null
.
Need do several actions:
-
verify account status
-
verify account’s proxy
-
verify account’s cookies by requesting own account profile information.
Conversations sync failed (SyncType: "CONVERSATIONS"
)
Property |
Type |
Description |
---|---|---|
|
date |
Date requested by user. |
|
string |
Date requested by user. |
|
string | null |
Cursor of last page. |
|
string |
Indicates the type of the requested inbox. |
|
string |
For conversation synchronization this value is |
Retry: call POST /api/v1/conversations/sync
again with the same ConversationsFromDate
/ MessagesFromDate
and the Cursor
from the error.
Single conversation sync failed (SyncType: "MESSAGES"
)
Property |
Type |
Description |
---|---|---|
ConversationId |
string |
ConversationId requested by user. |
|
string |
Indicates the type of the requested inbox. |
|
string |
For conversation messages (single conversation) synchronization this value is |
Retry: call POST /api/v1/conversations/{id}/sync
again with the same parameters.
Use Cases
1) Sync Inbox in
-
Inbox Refresh before sending message
Sync LinkedIn conversations/messages before sending new messages. -
Initial Message Import
Import all conversations from a given time to populate your platform with past data. -
Scheduled CRM Sync
Periodically fetch all messages usingfromDateTime
to keep CRM records up to date.
2) Trigger Follow-up Workflows
Automatically tag leads, assign tasks, or notify sales reps when replies come in.
3) Build a Unified Inbox
Combine LinkedIn messages with other channels (email, WhatsApp, etc.) in your platform.
4) Track Engagement
Detect who replied, when, and how—enabling response tracking and conversion insights.
5) Trigger AI/Chatbot Responses
Detect incoming messages to trigger auto-replies.
6) Analytics
Analyze message content and give end user understanding how well their outreach sequence works.