Sync Candidates
All candidates should be sent via the Middleware Platform whenever they are created or updated in your ATS. Use your candidate identifier when syncing candidates via API.
To ensure the best possible ATS candidate to LinkedIn member match rate, sync phoneNumbers, linkedInProfileUrl, currentCompanyName, and currentJobTitle along with firstName, lastName, and emailAddresses whenever available.
Throttle Limits
Throttle Limits | Requests Per Day (UTC) | Records Per Minute |
---|---|---|
Application maximum | 100,000 | 10,000 |
Note
Please submit batch calls grouped with no more than 100 records in sequential order.
Sync Candidates
Use the following endpoint to create and update records:
PUT https://api.linkedin.com/v2/atsCandidates?ids[0].atsCandidateId={id 1}&ids[0].dataProvider=ATS&ids[0].integrationContext={organization URN}&ids[1].atsCandidateId={id 2}&ids[1].dataProvider=ATS&ids[1].integrationContext={organization URN}
For each id specified in the request:
- Use your candidate id as the value of
id[i].atsCandidateId
. - Use the customer's organization id as the value of
id[i].integrationContext
. The format should be "urn:li:organization:{id}". - Use "ATS" as the value of
id[i].dataProvider
.
Request Body Fields
Field | Description | Format | Required |
---|---|---|---|
addresses | A list of the candidate's addresses May be empty array if not available | array of Address | Yes |
atsCreatedAt | Date record was created in your ATS. Must be greater than 0. | UTC Epoch Milliseconds | Yes |
atsLastModifiedAt | Date record was last updated in your ATS. Must be greater than 0. Must be greater than or equal to atsCreatedAt . |
UTC Epoch Milliseconds | Yes |
currentCompanyName | Name of the candidate's current employer | string | No |
currentJobTitle | Candidate's current job title | string | No |
doNotContact | flag to indicate if candidate should be contacted | boolean | No |
emailAddresses | List of candidate email addresses. Emails must follow X@X.X pattern. For One-Click Export see Attach Person URN. For Prospect use case see the Note section |
array of EmailAddress | Yes |
externalProfileUrl | Link to Profile in RSC. A URL that points to the candidate's external profile page, other than the LinkedIn profile | Url | Yes |
firstName | Candidate's first name | string | Yes |
lastName | Candidate's last name | string | Yes |
linkedInProfileUrl | A URL that points to the candidate's LinkedIn profile page. Can be used to facilitate profile matching within LinkedIn. String value cannot be empty or blank spaces | String | No |
middleInitial | Candidate's middle initial | string | No |
phoneNumbers | A list of the candidate's phone numbers. May be an empty array if not available | PhoneNumber[] | Yes |
prefix | The candidate's name prefix | string | No |
skills | Candidate's skills. | array of Skill | No |
sources | List of Candidate's source. | Source[] | No |
suffix | The candidate's name suffix | string | No |
tags | Candidate's tags. | array of Skill | No |
Note
When updating an existing record, you must specify all available fields. Omitting a field will set it to null.
For the Prospect use case, you may pass an empty array for the emailAddresses field.
PhoneNumber Schema
Field | Description | Format | Required |
---|---|---|---|
number | Formatted String of the phone number. The length should be no more than 25. | String | Required |
extension | Formatted String of the extension | String | Optional |
countryCode | If countryCode is provided, it must be in the ISO 3166 country code set. If number contains a country code (e.g., +1) and countryCode (e.g., GB) is provided, then the numeric country code has higher priority. | String | Optional |
Source Schema
Field | Description | Format | Required |
---|---|---|---|
sourceCategory | Category of where the candidate originated from. Must be one of these source category type :
|
Enum | Required |
sourceDetail | Where the candidate originated from. | String | Required |
Sample Request (query tunneled)
Note
In production, requests must use query tunneling to avoid reaching maximum URL length. You can use non-tunneled requests when request URLs are shorter than length limits, for testing purposes, and for troubleshooting. Please check details on Query Tunneling Migration Guide.
curl -L -X POST 'https://api.linkedin.com/v2/atsCandidates' \
-H 'X-HTTP-Method-Override: PUT' \
-H 'Content-Type: multipart/mixed; boundary=xyz' \
-H 'x-restli-method: batch_update' \
-H 'Authorization: Bearer {token}' \
--data $'--xyz\r\n
Content-Type: application/x-www-form-urlencoded\r\n\r\nids[0].atsCandidateId=CAND123&ids[0].dataProvider=ATS&ids[0].integrationContext=urn:li:organization:2414183&ids[1].atsCandidateId=CAND456&ids[1].dataProvider=ATS&ids[1].integrationContext=urn:li:organization:2414183\r\n--xyz\r\n
Content-Type: application/json\r\n\r\n
{
"entities": {
"atsCandidateId=CAND123&dataProvider=ATS&integrationContext=urn:li:organization:2414183": {
"addresses": [
{
"line1": "31 Spooner St",
"city": "Quahog",
"geographicArea": "RI",
"geographicAreaType": "STATE",
"postalCode": "02802",
"country": "us"
}
],
"atsCreatedAt": 1484864187000,
"atsLastModifiedAt": 1484864187000,
"currentCompanyName": "Pawtucket Patriot Brewery",
"currentJobTitle": "Quality Assurance",
"emailAddresses": [
"foo@example.com"
],
"externalProfileUrl": "https://example.com/p-griffin",
"firstName": "Peter",
"lastName": "Griffin",
"middleInitial": "L",
"phoneNumbers": [
{
"number": "555-555-5555",
"extension": "1234"
}
],
"skills": ["Java", "C++"],
"tags": ["Test1", "Test2"],
"sources":[
{
"sourceCategory": "LINKEDIN",
"sourceDetails": "Get the candidate from LinkedIn 1CE"
}
],
"prefix": "Mr",
"suffix": "Jr"
},
"atsCandidateId=CAND456&dataProvider=ATS&integrationContext=urn:li:organization:2414183": {
"addresses": [
{
"line1": "1000 W Maude Ave",
"line2": "ATTN: Maude Flanders",
"city": "Calgary",
"geographicArea": "AB",
"geographicAreaType": "PROVINCE",
"postalCode": "T1X 0L3",
"country": "ca"
}
],
"atsCreatedAt": 1484864187000,
"atsLastModifiedAt": 1484864187000,
"emailAddresses": [
"foo@example.com"
],
"externalProfileUrl": "https://example.com/m-flanders",
"firstName": "Maude",
"lastName": "Flanders",
"phoneNumbers": [
{
"number": "555-666-7777",
"extension": "1234"
}
],
"skills": ["Java", "C++"],
"tags": ["Test1", "Test2"],
"sources":[
{
"sourceCategory": "AGENCY",
"sourceDetails": "Get the candidate from recruiting agency"
}
],
"prefix": "Mrs"
}
}
}\r\n--xyz--'
Sample Request (without query tunneling)
curl -L -g -X PUT 'https://api.linkedin.com/v2/atsCandidates?ids[0].atsCandidateId=CAND123&ids[0].dataProvider=ATS&ids[0].integrationContext=urn%3Ali%3Aorganization%3A2414183&ids[1].atsCandidateId=CAND456&ids[1].dataProvider=ATS&ids[1].integrationContext=urn%3Ali%3Aorganization%3A2414183' \
-H 'Content-Type: application/json' \
-H 'x-restli-method: batch_update' \
-H 'Authorization: Bearer {token}' \
--data '{
"entities": {
"atsCandidateId=CAND123&dataProvider=ATS&integrationContext=urn:li:organization:2414183": {
"addresses": [
{
"line1": "31 Spooner St",
"city": "Quahog",
"geographicArea": "RI",
"geographicAreaType": "STATE",
"postalCode": "02802",
"country": "us"
}
],
"atsCreatedAt": 1484864187000,
"atsLastModifiedAt": 1484864187000,
"currentCompanyName": "Pawtucket Patriot Brewery",
"currentJobTitle": "Quality Assurance",
"emailAddresses": [
"foo@example.com"
],
"externalProfileUrl": "https://example.com/p-griffin",
"firstName": "Peter",
"lastName": "Griffin",
"middleInitial": "L",
"phoneNumbers": [
{
"number": "555-555-5555",
"extension": "1234"
}
],
"skills": ["Java", "C++"],
"tags": ["Test1", "Test2"],
"sources":[
{
"sourceCategory": "LINKEDIN",
"sourceDetails": "Get the candidate from LinkedIn 1CE"
}
],
"prefix": "Mr",
"suffix": "Jr"
},
"atsCandidateId=CAND456&dataProvider=ATS&integrationContext=urn:li:organization:2414183": {
"addresses": [
{
"line1": "1000 W Maude Ave",
"line2": "ATTN: Maude Flanders",
"city": "Calgary",
"geographicArea": "AB",
"geographicAreaType": "PROVINCE",
"postalCode": "T1X 0L3",
"country": "ca"
}
],
"atsCreatedAt": 1484864187000,
"atsLastModifiedAt": 1484864187000,
"emailAddresses": [
"foo@example.com"
],
"externalProfileUrl": "https://example.com/m-flanders",
"firstName": "Maude",
"lastName": "Flanders",
"phoneNumbers": [
{
"number": "555-666-7777",
"extension": "1234"
}
],
"skills": ["Java", "C++"],
"tags": ["Test1", "Test2"],
"sources":[
{
"sourceCategory": "AGENCY",
"sourceDetails": "Get the candidate from recruiting agency"
}
],
"prefix": "Mrs"
}
}
}'
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": {
"atsCandidateId=CAND123&dataProvider=ATS&integrationContext=urn%3Ali%3Aorganization%3A4gX03uw": {
"status": 204
},
"atsCandidateId=CAND456&dataProvider=ATS&integrationContext=urn%3Ali%3Aorganization%3A4gX03uw": {
"status": 204
}
}
}
Note
Be sure to check the response for error statuses corresponding to individual entities you submit.
Retrieve Candidate Matches
After you've sent candidates to us, you may retrieve candidate details, which will include any algorithmic and user-supplied matches with LinkedIn members.
GET https://api.linkedin.com/v2/atsCandidates?ids[0].atsCandidateId={id 1}&ids[0].dataProvider=ATS&ids[0].integrationContext={organization URN}&ids[1].atsCandidateId={id 2}&ids[1].dataProvider=ATS&ids[1].integrationContext={organization URN}&fields=matchedMembers,manualMatchedMember
Response Body
Field | Description | Format | Required |
---|---|---|---|
matchedMembers | LinkedIn's algorithmic profile matches for this candidate. If multiple results are present, you should use the first element. | array of Person URN null or not returned when matching hasn't yet occurred Empty when no matches could be found | no |
manualMatchedMember | The candidate match specified by the customer (for example, via the Profile Plugin). Use this as the preferred match if present. | Person URN null or not returned when customer hasn't specified a match | no |
Sample Request
curl -L -X POST 'https://api.linkedin.com/v2/atsCandidates' \
-H 'X-HTTP-Method-Override: GET' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Authorization: Bearer {token}' \
--data 'ids[0].atsCandidateId=CAND123&ids[0].dataProvider=ATS&ids[0].integrationContext=urn:li:organization:1000&ids[1].atsCandidateId=CAND456&ids[1].dataProvider=ATS&ids[1].integrationContext=urn:li:organization:1000&fields=matchedMembers,manualMatchedMember’
Sample Response
{
"errors": {},
"results": {
"atsCandidateId=CAND123&dataProvider=ATS&integrationContext=urn%3Ali%3Aorganization%3A1000": {
"manualMatchedMember": "urn:li:person:3co983jx7",
"matchedMembers": []
},
"atsCandidateId=CAND456&dataProvider=ATS&integrationContext=urn%3Ali%3Aorganization%3A1000": {
"manualMatchedMember": "urn:li:person:38x72uj1pt",
"matchedMembers": [
"urn:li:person:38x72uj1pt"
]
}
},
"statuses": {}
}
Note
LinkedIn matches profiles asynchronously with respect to candidate creates and updates. If the matchedMembers
field is ever null for a candidate, resend the request for that candidate in 60 seconds.
Delete Candidates
API Details
Perform HTTP DELETE on the /atsCandidates endpoint when a customer deletes candidate records. More information is available here.
Attach Person URN to Candidate
After your ATS receives a One-Click Export stub profile from LinkedIn and creates a candidate in your ATS, it is recommended to sync the newly created candidate in your ATS back to LinkedIn. You may use the sync candidates endpoint to create or update the candidate. Once you do this you must attach the Person URN to the candidate.
Note
You may pass an empty array for emailAddresses field in the sync candidates endpoint as long as you follow it up with attaching the Person URN to the candidate.
Use the following endpoint to attach a Person URN to a candidate:
POST https://api.linkedin.com/v2/atsCandidates?ids[0].atsCandidateId={id 1}&ids[0].dataProvider=ATS&ids[0].integrationContext={organization URN}&ids[1].atsCandidateId={id 2}&ids[1].dataProvider=ATS&ids[1].integrationContext={organization URN}
Request Body
Field | Description | Format | Required |
---|---|---|---|
manualMatchedMember | LinkedIn Person URN received from One-Click Export. | Person URN | yes |
Sample Request
Headers:
Authentication: Bearer {token}
x-restli-method: batch_partial_update
Request Body:
{
"entities": {
"atsCandidateId=CAND123&dataProvider=ATS&integrationContext=urn:li:organization:2414183": {
"patch": {
"$set": {
"manualMatchedMember": "urn:li:person:AFoqxfjB27"
}
}
}
}
}
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": {
"atsCandidateId=CAND123&dataProvider=ATS&integrationContext=urn:li:organization:2414183": {
"status": 204
}
}
}
Note
Be sure to check the response for error statuses corresponding to individual entities you submit.