Compliance Events API
Once a member has been opted-in to LinkedIn's Compliance Platform to monitor and archive communications from Sales Navigator, The Compliance Events API allows you to query and fetch all archived communications from Sales Navigator from the past 28 days of a regulated, authenticated member. It returns each monitored communication as an individual event record to provide ease of archive and remediation if necessary.
Note
Only Compliance APIs for Sales Navigator uses the Versioned LinkedIn APIs. Please append the header LinkedIn-Version: 202310
while making the API requests.
Usage
You must use an access token to make an authenticated call on behalf of a user.
Permissions
Permission | Description |
---|---|
r_compliance_sales_nav | Required to retrieve communications from Sales Navigator Inbox for compliance monitoring and archiving. |
To use the following APIs, you will need to know your application ID
. This can be found in your Developer Application Setting page. Select your application and go to the Mobile section to view your application ID
. Alternatively, you can find the ID from the URL as well (ie. https://www.linkedin.com/developer/apps/{applicationID}/auth)
.
Compliance Events
After the member is authorized for compliance monitoring via the Compliance Management API, you can start archiving the activities performed with the following request:
Query Parameters
Field Name | Required | Description |
---|---|---|
startTime | No | Represented as an inclusive timestamp in epoch milliseconds. If present, returns all the activities that are processed after the time. |
Note
We recommend you specifying startTime
by using the latest processedAt
from the previous response. If there is no event from the previous response, keep the same startTime
for the next request. If there is an event from the response, the next request should use the latest timestamp of the processedAt
and that event will show up on the next request's response. This way, we will ensure no data loss in the next API request.
We currently return events up to 28 days. If you specify a startTime
older than 28 days of the current timestamp, it will return events up to 28 days. If you specify an invalid timestamp, it will throw a 400 error.
In addition, we recommend querying at a count=10
to reduce latency and to query each member's activities once an hour. The upper limit is 50
. If you set a number not in the range [1,50]
, it will result in a 400
and an error message containing the recommended count
.
If you decide to increase number of activities returned via count
, keep in mind it will slow down processing time and can lead to timeouts. For querying each member's activities, we recommend spreading out your requests over the hour such that your application is not having QPS spikes, which could lead to timeouts as well.
We also recommend using the capturedAt time returned by Compliance Events API to determine the time of the event activity. There might be instances within the specific activity that do not return the created/lastModified time.
The Compliance Events API will return an array of elements. Each element is an activity record with the following schema:
Compliance Events Schema
Field Name | Description |
---|---|
id | The unique identifier for the activity event. |
capturedAt | Time the event is captured. |
processedAt | Time the event is processed. |
configVersion | The configuration version used to process this event. This is unique to the activity's resourceName and method. It can change periodically as we update our configurations to better the API experience. It will mainly used for debugging purpose. |
owner | The member who owns the record. It is the same member who has retrieval and viewing access to this activity. |
actor | The member who performs the action of the activity. |
resourceName | Name of resource being acted upon. |
resourceId | The identifier of the resource. |
resourceUri | URI of the resource being modified. Used for remediation. |
method | The resource method. Can be one of the following write methods: *As of now, if a method is DELETE, the activity and processedActivity fields should be empty since we cannot capture the object after it has been deleted. |
methodName | The optional string representing the method's name. Only present in ACTION method. |
activity | The original activity data. Used for remediation. |
processedActivity | The decorated original activity containing relevant contextual information. For example, if the original activity is a comment, this will include the original share content. Used for archiving. |
siblingActivities | The activities on the same resource level. This is used for previous sibling comments on a share or previous messages in a conversation. Will return up to 10 most recent previous activities. |
parentSiblingActivities | The previous activities on the parent resource level. Example would be the previous sibling comments of a parent comment of a nested comment. Will return up to 10 most recent previous activities. |
activityId | A unique string identifier of a captured activity. If an activity is processed more than once, all generated records share same activityId. |
activityStatus | NEW! The status of the event. Can be one of the following:
|
Sample Get Response
{
"owner": "urn:li:person:2qXA98-mVk",
"resourceId": "0-UzY2MDM3MjAzODc4OTk1OTI3MDRfNTAw",
"configVersion": 1,
"method": "CREATE",
"activity": {
"owner": "urn:li:person:kAq_1ptj-v",
"createdAt": 1574449632116,
"clientExperience": {
"clientGeneratedToken": "11daeca1-34af-47c2-b22e-d02a947c33a2"
},
"author": "urn:li:person:kAq_1ptj-v",
"id": "0-UzY2MDM3MjAzODc4OTk1OTI3MDRfNTAw",
"thread": "urn:li:messagingThread:0-NjU5OTczMDkxNTAzODAyNzc3Ng==",
"readAt": 1574449632000,
"content": {
"format": "TEXT",
"fallback": "Hello back to Sales Navigator inbox",
"formatVersion": 1,
"content": {
"string": "Hello back to Sales Navigator inbox"
}
},
"deliveredAt": 1574449632116
},
"resourceName": "messages",
"resourceUri": "/messages/0-UzY2MDM3MjAzODc4OTk1OTI3MDRfNTAw",
"actor": "urn:li:person:kAq_1ptj-v",
"activityId": "c86c3c71-7844-4ed1-b1fc-66deeac14192",
"processedAt": 1574449662997,
"capturedAt": 1574449632331,
"processedActivity": {
"owner": "urn:li:person:kAq_1ptj-v",
"owner~": {...},
"createdAt": 1574449632116,
"deliveredAt": 1574449632116,
"author~": {...},
"thread~": {
"owner": "urn:li:salesIdentity:334326",
"membership": [
{
"createdAt": 1573498467712,
"identity~": {
"member": "urn:li:person:2qXA98-mVk",
"member~": {...},
"id": 334326
},
"identity": "urn:li:salesIdentity:334326"
},
{
"createdAt": 1573498467712,
"identity~": {...},
"identity": "urn:li:person:kAq_1ptj-v"
}
]
},
"author": "urn:li:person:kAq_1ptj-v",
"thread": "urn:li:messagingThread:0-NjU5OTczMDkxNTAzODAyNzc3Ng==",
"id": "0-UzY2MDM3MjAzODc4OTk1OTI3MDRfNTAw",
"readAt": 1574449632000,
"content": {
"format": "TEXT",
"fallback": "Hello back to Sales Navigator inbox",
"formatVersion": 1,
"content": {
"string": "Hello back to Sales Navigator inbox"
}
}
},
"id": 978988628
}
Each activity record contains metadata such as resourceName
, resourceId
, resourceUri
, and more to help you identify the activity performed so you can properly archive and remediate as needed.
As best practice, we recommend archiving all the data but specifically method
, resourceName
, resourceId
, configVersion
and processedActivity
. For remediation, you will be able to use resourceUri
and activity
to easily update what is needed.
Samples or compliance events from Sales Navigator Communications are documented here.
Error Handling
In the event that a field or an activity is unable to be processed, we will still return the activity such that you are notified that an activity has occurred. The field that is not processed will have following message of "Unable_to_process_this_field."
. In the processedActivity
, the whole activity can be unprocessed, which will result in string of "message": "Unable to process this event."
. If a particular field in the processedActivity is unprocessed, then it will have !
and the string "message": "Unable to process this field."
. See below for examples.
Unable to process a field
{
"activity": {},
"activityId": "81fafbe1-ea4b-4454-a736-6b8a20d9aa90",
"actor": "urn:li:person:sFrA4B1w3F",
"capturedAt": 1494367986523,
"configVersion": 2,
"id": 23260,
"method": "UPDATE",
"owner": "urn:li:person:sFrA4B1w3F",
"processedActivity": {
"message": "Unable to process this event."
},
"processedAt": 1494368009776,
"resourceId": "Unable_to_process_this_field.",
"resourceName": "mockSimpleKeyCollection",
"resourceUri": "Unable_to_process_this_field."
}
unable to process an activity
{
"activity": {
"simpleUnionField": {
"int": 3
},
"urn": "urn:li:person:sFrA4B1w3F"
},
"activityId": "b77d27f4-b7c9-426c-a43e-204a2735c798",
"actor": "urn:li:person:sFrA4B1w3F",
"capturedAt": 1494368763168,
"configVersion": 2,
"id": 23716,
"method": "UPDATE",
"owner": "urn:li:person:sFrA4B1w3F",
"processedActivity": {
"message": "Unable to process this event."
},
"processedAt": 1494369845019,
"resourceId": "4",
"resourceName": "mockSimpleKeyCollection",
"resourceUri": "/mockSimpleKeyCollection/4"
}
Unable to process an urn field in processedActivity
{
"activity": {
"simpleUnionField": {
"int": 3
},
"urn": "urn:li:person:sFrA4B1w3F"
},
"activityId": "81fafbe1-ea4b-4454-a736-6b8a20d9aa90",
"actor": "urn:li:person:sFrA4B1w3F",
"capturedAt": 1494367986523,
"configVersion": 2,
"id": 23260,
"method": "UPDATE",
"owner": "urn:li:person:sFrA4B1w3F",
"processedActivity": {
"simpleUnionField": {
"int": 3
},
"urn": "urn:li:person:sFrA4B1w3F",
"urn!": {
"message": "Unable to process this field."
}
},
"processedAt": 1494368009776,
"resourceId": "4",
"resourceName": "mockSimpleKeyCollection",
"resourceUri": "/mockSimpleKeyCollection/4"
}
Replayer Feature
Replayer feature provides the ability to reprocess events that have already occurred and surfaced on the API response. This feature will provide more information on past activities that were not previously available during the initial compliance capture and process by surfacing them on new events. The Replayer feature will not modify existing events, only create new ones corresponding to the same activty. This feature will go live on February 12, 2020 with the goal of reprocessing all events that have missing and/or incomplete data.
Starting on February 12, 2020, you may see reprocessed events in the Compliance Events API response. To differentiate between initial and reprocessed events, we are introducing activityStatus
field to denote each event's process state. It can be one of the following: SUCCESS
, FAILURE
, or SUCCESSFUL_REPLAY
. To prevent archiving duplicate events, partners can filter out reprocessed events by filtering out SUCCESSFUL_REPLAY
events until they are ready to utilize this feature.
Currently, reprocessed events will only appear in the API response if it's successfully reprocessed with no processing failures. This means the maximum number of Compliance Events for a unique activity is two. Therefore the three possible scenarios are:
- Event with
SUCCESS
activityStatus. - Event with
FAILURE
activityStatus with no subsequent event. - Event with
FAILURE
activityStatus that eventually is followed by another event withSUCCESSFUL_REPLAY
activityStatus.
Some other ways to identify and differentiate these activities are to use the following fields: id
, activityId
, and processedAt
. For more information on these fields, refer to the Compliance Events Schema. See below for an example:
Sample Replay Activities
{
"elements": [
{
"id": 1000,
"owner": "urn:li:person:yrZCpj2ZYQ",
"resourceId": "urn:li:ugcPost:123456789",
"configVersion": 36,
"method": "CREATE",
"activity": {
"author": "urn:li:person:yrZCpj2ZYQ",
"id": "urn:li:ugcPost:123456789",
...
},
"resourceName": "ugcPosts",
"resourceUri": "/ugcPosts/urn:li:ugcPost:123456789",
"actor": "urn:li:person:yrZCpj2ZYQ",
"activityId": "8561f816-517e-49fb-901d-29c589e3b09f",
"processedAt": 1572831764582,
"capturedAt": 1573079762090,
"activityStatus": "FAILURE",
"processedActivity": {
"author": "urn:li:person:yrZCpj2ZYQ",
"author!": {
"message": "Unable to process this field."
},
"id": "urn:li:ugcPost:123456789",
...
}
},
{
"id": 1001,
"activityStatus": "SUCCESS",
...
},
{
"id": 1002,
"activityStatus": "SUCCESS",
...
},
{
"id": 1003,
"activityStatus": "SUCCESS",
...
},
{
"id": 1004,
"owner": "urn:li:person:yrZCpj2ZYQ",
"resourceId": "urn:li:ugcPost:123456789",
"configVersion": 37,
"method": "CREATE",
"activity": {
"author": "urn:li:person:yrZCpj2ZYQ",
"id": "urn:li:ugcPost:123456789",
...
},
"resourceName": "ugcPosts",
"resourceUri": "/ugcPosts/urn:li:ugcPost:123456789",
"actor": "urn:li:person:yrZCpj2ZYQ",
"activityId": "8561f816-517e-49fb-901d-29c589e3b09f",
"processedAt": 1573759549000,
"capturedAt": 1573079762090,
"activityStatus": "SUCCESSFUL_REPLAY",
"processedActivity": {
"author": "urn:li:person:yrZCpj2ZYQ",
"author~": {
"firstName": {
"localized": {
"en_US": "Bob"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
...
},
"id": "urn:li:ugcPost:123456789",
...
}
}
]
}
Note
Notice the first and last event in the above sample response and their specific fields: activityStatus
, id
, activityId
, and processedAt
. The activityStatus
field helps determine whether or not it's a reprocessed event and the last event denotes a reprocessed event. In addition, the two events correspond to the same activity by having the same activityId
. However, they have different unique id
and the first activity has the previous processedAt
timestamp while the last one has the latest timestamp. The last activity was not able to process the author
decoration in processedActivity
and has author!
whereas the first activity reprocessed the field with author~
in processedActivity
. For more information on response decoration, please refer here.