Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
As a LinkedIn partner, you can allow your customers to authorize your ATS to use specific Middleware Platform integrations, such as Recruiter System Connect (RSC), on their behalf. To achieve this:
- You will create and configure a development application for the customer.
- Using the app's credentials, you will host a customer-facing configuration plugin that allows customers to manage their integrations with your ATS.
- After the customer pre-authorizes integrations in the plugin, you will update integrations on behalf of the customer with a user-facing integration name.
- Depending on the type of integration, you may need to send customer-specific configuration values.
- Finally, the customer will log into the relevant LinkedIn product and enable the integration. Once enabled, you will be authorized to begin sending customer data to the Middleware Platform.
Details for each step are below.
Note
The latest API version is 202604. Use this version in the LinkedIn-Version header for all API requests to access the most recent features and improvements.
Steps
- Create and Configure a Customer App
- Display the ATS Integration Configuration Plugin
- Update Customer Integrations
- Sync Integration Configurations
- Verify Customer Integrations Enablement
Throttle Limits
| Endpoint | Requests Per Day (UTC) |
|---|---|
v2/atsIntegrations |
5,000 |
rest/integrations |
5,000 |
rest/integrationConfigurations |
5,000 |
1. Create and Configure a Customer App
The Provisioning API allows you to create API keys for each of your customers. Please note that you will need to store a unique API key for each of your customers.
Once your app is configured, you may begin making API requests and testing the integration. All API requests require authorization.
Note
For existing CSA customers, you will be using their existing API keys. Please contact your Partner Engineering representative to coordinate migrating these API keys.
2. Display the ATS Integration Configuration Plugin
Using the customer's app credentials obtained in step 1, display the ATS Integration Configuration Plugin:
<script type="text/javascript" src="https://platform.linkedin.com/xdoor/scripts/in.js">
api_key: { Enter the customer app API key (client_id) received in the Provisioning API response. }
extensions: ATSIntegrationWidget@https://platform.linkedin.com/rsc/extensions/onboarding-widget
</script>
<script type="IN/ATSIntegrationWidget"
data-supported-bundled-integration-types="RECRUITER_SYSTEM_CONNECT_COMPANY,RECRUITER_SYSTEM_CONNECT_CONTRACT,APPLY_WITH_LINKEDIN"
data-onintegrate="handleIntegrations"
data-width="{width}" >
</script>
<script>
/**
* This callback should:
* 1) Store the customer's integration in your ATS. These values are used to throughout the Middleware Platform's API.
* 2) Tell your server to create and configure customer integrations via the Middleware Platform using this data.
* @param {Object[]} integrations
* @param {string} integrations[].integrationContext
* @param {string} integrations[].integrationType
* @param {string} integrations[].tenantType
*/
function handleIntegrations (integrations) {
//Your code here
}
</script>
Integration Enums
The value for data-supported-bundled-integration-types should be based on the integrations as indicated below:
| Enum | Description | Required |
|---|---|---|
| APPLY_CONNECT | Used for the Apply Connect integrations only | No |
| APPLY_WITH_LINKEDIN | Used for the Apply with LinkedIn integrations only | No |
| RECRUITER_SYSTEM_CONNECT_COMPANY, RECRUITER_SYSTEM_CONNECT_CONTRACT | Used for the RSC integrations only | Yes |
Plugin Load
The plugin will load based on the data-width and data-supported-bundled-integration-types attributes you specify. Use the latter attribute to declare which integrations you support.
Plugin Callback
The callback specified for the data-onintegrate script attribute will be fired when the customer enables an integration within the plugin. You will need to store the values you retrieve per customer for: integrationContext , integrationType, and tenantType as they will be used in the next step.
Note
- Details on the customer's workflow within the plugin can be found here.
- In order to reload the widget on a single page application, use in.parse()
- Verify Content Security Policy includes "platform.linkedin.com" and "www.linkedin.com"
Multiple Contract Support
The onboarding widget supports multiple contract activations. When your customer activates their first contract, the plugin returns a payload with the following four types of integrationType values.
[
{
"tenantType": "RECRUITER",
"integrationType": "ONE_CLICK_EXPORT",
"integrationContext": "urn:li:organization:12345678",
"onboardingStatus": "REQUESTED"
},
{
"tenantType": "RECRUITER",
"integrationType": "CSA_API",
"integrationContext": "urn:li:contract:12345678",
"onboardingStatus": "REQUESTED"
},
{
"tenantType": "RECRUITER",
"integrationType": "IN_ATS_INDICATOR",
"integrationContext": "urn:li:organization:12345678",
"onboardingStatus": "REQUESTED"
},
{
"tenantType": "RECRUITER",
"integrationType": "PROFILE_PLUGIN",
"integrationContext": "urn:li:organization:12345678",
"onboardingStatus": "REQUESTED"
}
]
If your customer selects Apply with LinkedIn, that integration type will also be included in the payload.
After receiving the payload, proceed with steps 3–5 of the onboarding process.
Subsequent Contract Activation
To activate a second contract, your customer can use the “Change Contract” button in the widget. The new payload will include only the values of integrationType that were not already configured (e.g., only CRM_CSA_API). For example, see the following payload:
[
{
"tenantType": "RECRUITER",
"integrationType": "CSA_API",
"integrationContext": "urn:li:contract:87654321",
"onboardingStatus": "REQUESTED"
}
]
Note
- You only need to sync data with one organization URN. Sending data for multiple organization URNs in the sync APIs (under module 2) is not supported to avoid complexity.
- When a customer activates a contract with the same organization, the payload includes only the new
integrationTypevalues (e.g., CRM_CSA_API), keeping all other values the same. - If a customer activates a contract with a different organization URN, you’ll receive the full payload as in Multiple Contract Support. In such cases, throw an error and advise the customer that only one organization can be active. They can contact the LinkedIn integrations support at ltsatsintegrations@linkedin.com for assistance.
- For any subsequent contract payloads, repeat Steps 3–5 of the onboarding process, as done previously.
3. Update Customer Integrations
Sync Customer Integrations
Note
Creating integrations must be done server-side and in real-time.
Please submit batch calls grouped with no more than 100 records and a minimum delay of one-second between calls.
For each id part specified in the request:
- Use the customer's integration context obtained in step 2 as the value of
id[i].integrationContext. The format will be either "urn:li:organization:{id}" or "urn:li:contract:{id}". - Use the integration type obtained in step 2 as the value of
id[i].integrationType. - Use the tenant type obtained in step 2 as the value of
id[i].tenantType.
- Use the customer's integration context obtained in step 2 as the value of
id[i].integrationContext. The format will be either "urn:li:organization:{id}" or "urn:li:contract:{id}". - Use the integration type obtained in step 2 as the value of
id[i].integrationType. - Use the tenant type obtained in step 2 as the value of
id[i].tenantType. - Use "ATS" as the value of
id[i].dataProvider.
Request Body Fields
| Field | Description | Format | Required |
|---|---|---|---|
| integrationName | Customer-facing name for the integration. | string | Yes |
Sample Request
curl --location --globoff 'https://api.linkedin.com/rest/integrations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=ONE_CLICK_EXPORT&ids[0].tenantType=RECRUITER' \
--header 'x-restli-method: batch_partial_update' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}'\
--header 'LinkedIn-Version: 202602' \
--data '{
"entities": {
"integrationContext=urn:li:organization:1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER": {
"patch": {
"$set": {
"integrationName": "{{customer_name}} LinkedIn Recruiter One-Click Export Integration"
}
}
}
}
}'
curl --location --globoff 'https://api.linkedin.com/rest/integrations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=ONE_CLICK_EXPORT&ids[0].tenantType=RECRUITER' \
--header 'x-restli-method: batch_partial_update' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}'\
--header 'LinkedIn-Version: 202603' \
--data '{
"entities": {
"integrationContext=urn:li:organization:1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER": {
"patch": {
"$set": {
"integrationName": "{{customer_name}} LinkedIn Recruiter One-Click Export Integration"
}
}
}
}
}'
curl --location --globoff 'https://api.linkedin.com/rest/integrations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=ONE_CLICK_EXPORT&ids[0].tenantType=RECRUITER' \
--header 'x-restli-method: batch_partial_update' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}'\
--header 'LinkedIn-Version: 202604' \
--data '{
"entities": {
"integrationContext=urn:li:organization:1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER": {
"patch": {
"$set": {
"integrationName": "{{customer_name}} LinkedIn Recruiter One-Click Export Integration"
}
}
}
}
}'
API Endpoint
POST https://api.linkedin.com/v2/atsIntegrations?ids[0].integrationContext={integrationContext}&ids[0].integrationType={integrationType}&ids[0].tenantType={tenantType}&ids[0].dataProvider=ATS
Headers:
Authorization: Bearer {token}
x-restli-method: batch_partial_update
{
"entities": {
"integrationContext=urn:li:organization:{org_id}&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&dataProvider=ATS": {
"patch": {
"$set": {
"integrationName": "My Customer's LinkedIn Recruiter One-Click Export Integration"
}
}
}
}
}
Sample Response
A successful request will return a 200 OK response code, and you will find the status of each entity in the response body.
Sample Response Body
{
"errors": {},
"results": {
"integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&dataProvider=ATS&integrationContext=urn%3Ali%3Aorganization%3A{org_id}": {
"status": 204
}
}
}
Sample Response
A successful request will return a 200 OK response code, and you will find the status of each entity in the response body.
Sample Response Body
{
"results": {
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER": {
"status": 204
}
},
"errors": {}
}
Note
Be sure to check the response for error statuses corresponding to individual entities you submit.
4. Sync Integration Configurations
Some integrations require additional configuration values to be created to complete customer onboarding for Recruiter System Connect. Configurations are a set of key-value pairs which are defined for a specific integration.
Here is an example request that sets the CALLBACK_URL key for the ONE_CLICK_EXPORT configuration type:
Sample Upsert Request
curl --location --globoff --request PUT 'https://api.linkedin.com/rest/integrationConfigurations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=ONE_CLICK_EXPORT&ids[0].tenantType=RECRUITER&ids[0].configurationName=CALLBACK_URL' \
--header 'x-restli-method: batch_update' \
--header 'LinkedIn-Version: 202602' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data '{
"entities": {
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&configurationName=CALLBACK_URL": {
"configurationValue": {
"string": "https://www.linkedin.com"
}
}
}
}'
curl --location --globoff --request PUT 'https://api.linkedin.com/rest/integrationConfigurations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=ONE_CLICK_EXPORT&ids[0].tenantType=RECRUITER&ids[0].configurationName=CALLBACK_URL' \
--header 'x-restli-method: batch_update' \
--header 'LinkedIn-Version: 202603' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data '{
"entities": {
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&configurationName=CALLBACK_URL": {
"configurationValue": {
"string": "https://www.linkedin.com"
}
}
}
}'
curl --location --globoff --request PUT 'https://api.linkedin.com/rest/integrationConfigurations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=ONE_CLICK_EXPORT&ids[0].tenantType=RECRUITER&ids[0].configurationName=CALLBACK_URL' \
--header 'x-restli-method: batch_update' \
--header 'LinkedIn-Version: 202604' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--data '{
"entities": {
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&configurationName=CALLBACK_URL": {
"configurationValue": {
"string": "https://www.linkedin.com"
}
}
}
}'
URL:
PUT https://api.linkedin.com/v2/atsIntegrations/integrationContext=urn:li:organization:{org_id}&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&dataProvider=ATS/configurations?ids=CALLBACK_URL
Headers:
Authorization: Bearer {token}
x-restli-method: batch_update
Request Body:
{
"entities": {
"CALLBACK_URL": {
"configurationValue": {
"string": "https://customer.callback.com/goes/here"
}
}
}
}
Sample Response
{
"results": {
"configurationName=CALLBACK_URL&integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER": {
"status": 204
}
},
"errors": {}
}
{
"errors": {},
"results": {
"CALLBACK_URL": {
"status": 204
}
}
}
You can find more details on how to configure these keys, example requests, and definition of which configuration values are required for various integration types in our Integration Configuration docs.
Note
If a customer opts-out of restricting user-based entity visibility or your ATS doesn't offer this security functionality, you should configure customer entity visibility defaults so that entities without ACLs are shown in LinkedIn products.
5. Verify Customer Integrations Enablement
Customer integrations have three onboarding statuses:
- Requested - the customer requested the integration.
- Partner Ready - the integration is ready to be enabled by the customer.
- Enabled - the integration is set up and ready to use.
When a customer enables an integration, the onboarding status of that integration changes from Partner Ready to Enabled. When that happens, LinkedIn will send you a push notification (see Receive Push Events ) with a unique ID. You can use this ID to retrieve information about the customer and the enabled integration.
In order for push notifications to work, you must first submit a callback URL as a integration configuration for each integration the customer requested. Refer to Sync Integration Configurations for more details.
Once callback URLs are submitted, LinkedIn will generate and send a push notification automatically when a customer enables an integration. A notification will be sent for every integration enabled.
Notifications will follow the syntax below:
Sample Notification
"Content-Type":"application/json",
"X-LI-Signature":"d3756e445a8065c0f38c2182c502f8229800eb2c6a9f3b4a1fdf152af867e6fc"
{
"id":"{Unique Notification ID}",
"type":"INTEGRATION_STATUS_CHANGE",
"expiresAt":0
}
Note
Onboarding status change notifications will be denoted by the value INTEGRATION_STATUS_CHANGE (enum) in the type field.
Upon receiving the notification and verifying that type = INTEGRATION_STATUS_CHANGE , use the endpoint below with the unique notification ID to retrieve more information about the enabled integration.
API Endpoint
GET https://api.linkedin.com/rest/integrations?q=request&requestId={Unique Notification ID}
GET https://api.linkedin.com/v2/atsIntegrations?q=request&requestId={Unique Notification ID}
Sample Response
{
"elements": [
{
"integrationContext": "urn:li:organization:2414183",
"integrationName": "My Customer's LinkedIn Recruiter One-Click Export Integration",
"integrationType": "ONE_CLICK_EXPORT",
"onboardingStatus": "ENABLED",
"tenantType": "RECRUITER"
}
],
"paging": {
"count": 10,
"links": [],
"start": 0
}
}
{
"elements": [
{
"dataProvider": "ATS",
"integrationContext": "urn:li:organization:2414183",
"integrationName": "My Customer's LinkedIn Recruiter One-Click Export Integration",
"integrationType": "ONE_CLICK_EXPORT",
"onboardingStatus": "ENABLED",
"tenantType": "RECRUITER"
}
],
"paging": {
"count": 10,
"links": [],
"start": 0
}
}
For partners who implemented RSC prior to December 2017 and AWLI please reference the section below:
To manually retrieve the onboarding status of customer integrations, use the endpoint below:
Sample Request
curl --location --globoff 'https://api.linkedin.com/rest/integrations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=IN_ATS_INDICATOR&ids[0].tenantType=RECRUITER&ids[1].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[1].integrationType=PROFILE_PLUGIN&ids[1].tenantType=RECRUITER&ids[2].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[2].integrationType=ONE_CLICK_EXPORT&ids[2].tenantType=RECRUITER&ids[3].integrationContext=urn%3Ali%3Acontract%3A454294456&ids[3].integrationType=CSA_API&ids[3].tenantType=RECRUITER' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--header 'LinkedIn-Version: 202602'
Sample Request
curl --location --globoff 'https://api.linkedin.com/rest/integrations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=IN_ATS_INDICATOR&ids[0].tenantType=RECRUITER&ids[1].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[1].integrationType=PROFILE_PLUGIN&ids[1].tenantType=RECRUITER&ids[2].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[2].integrationType=ONE_CLICK_EXPORT&ids[2].tenantType=RECRUITER&ids[3].integrationContext=urn%3Ali%3Acontract%3A454294456&ids[3].integrationType=CSA_API&ids[3].tenantType=RECRUITER' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--header 'LinkedIn-Version: 202603'
Sample Request
curl --location --globoff 'https://api.linkedin.com/rest/integrations?ids[0].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[0].integrationType=IN_ATS_INDICATOR&ids[0].tenantType=RECRUITER&ids[1].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[1].integrationType=PROFILE_PLUGIN&ids[1].tenantType=RECRUITER&ids[2].integrationContext=urn%3Ali%3Aorganization%3A1234&ids[2].integrationType=ONE_CLICK_EXPORT&ids[2].tenantType=RECRUITER&ids[3].integrationContext=urn%3Ali%3Acontract%3A454294456&ids[3].integrationType=CSA_API&ids[3].tenantType=RECRUITER' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {token}' \
--header 'LinkedIn-Version: 202604'
Sample Response
A successful response will look like the following:
{
"results": {
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=IN_ATS_INDICATOR&tenantType=RECRUITER": {
"integrationName": "{{customer_name}} LinkedIn Recruiter IN_ATS_INDICATOR Integration",
"onboardingStatus": "ENABLED"
},
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=PROFILE_PLUGIN&tenantType=RECRUITER": {
"integrationName": "{{customer_name}} LinkedIn Recruiter PROFILE_PLUGIN Integration",
"onboardingStatus": "ENABLED"
},
"integrationContext=urn%3Ali%3Aorganization%3A1234&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER": {
"integrationName": "ONE_CLICK_EXPORT",
"onboardingStatus": "PARTNER_READY"
},
"integrationContext=urn%3Ali%3Acontract%3A454294456&integrationType=CSA_API&tenantType=RECRUITER": {
"integrationName": "{{customer_name}} LinkedIn Recruiter CSA_API Integration",
"onboardingStatus": "ENABLED"
}
},
"statuses": {},
"errors": {}
}
Sample Request
GET https://api.linkedin.com/v2/atsIntegrations?ids[0].integrationContext={integrationContext}&ids[0].integrationType={integrationType}&ids[0].tenantType={tenantType}&ids[0].dataProvider=ATS
Sample Response
A successful response will look like the following:
{
"errors": {},
"results": {
"integrationContext=urn:li:organization:{org_id}&integrationType=ONE_CLICK_EXPORT&tenantType=RECRUITER&dataProvider=ATS": {
"integrationName": "My Customer's LinkedIn Recruiter One-Click Export Integration",
"onboardingStatus": "ENABLED"
}
},
"statuses": {}
}
The response body will include the fields you supplied as well as the following fields:
| Field | Description | Format |
|---|---|---|
| integrationName | The customer-facing integration name you supplied | string |
| onboardingStatus | One of the three onboarding statuses for a given integration: REQUESTED, PARTNER_READY or ENABLED | enum |
Tip
During development, we recommend not having more than 10-15 integrations on your development contract as this may cause issues with our APIs. This will not be an issue in production as most customers generally have between 1-2 enabled integrations. If you should have more than 10-15 integrations please file a support ticket with a list of integrations you would like to delete.