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:

GET https://api.linkedin.com/rest/complianceEvents?q=memberAndApplication

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:
  • SUCCESS - Event is successfully processed on the initial attempt.
  • FAILURE - Event has partial or complete processing failure on the initial attempt. The API will not surface multiple FAILURE events of the same activity.
  • SUCCESSFUL_REPLAY - Event is successfully reprocessed after one or many attempts.

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:

  1. Event with SUCCESS activityStatus.
  2. Event with FAILURE activityStatus with no subsequent event.
  3. Event with FAILURE activityStatus that eventually is followed by another event with SUCCESSFUL_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.