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.
To upload a resume, you first need to get a signed URL from LinkedIn and then use it to upload the file. When uploading resume, LinkedIn recommends to abide by the following considerations:
- Supported media formats are: PDF, DOC, or TXT
- Ensure that the media file size does not exceed 10MB for all file types
- Upload only one resume object per API call
- Ensure that all calls to upload resume use OAuth 2.0 authentication
- A typical workflow to upload your resume consists of the following steps:
A typical workflow to upload your resume consists of the following steps:
When a customer activates CRM Connect for the first time, you must sync all of their historical data to LinkedIn to power the integration.
Create URL
Use the following endpoint to create URL:
POST https://api.linkedin.com/v2/hireMediaUrl
API Authorization
This API is governed by OAuth 2.0 Authorization Framework and you must pass a bearer access token in your request as Authorization header. The access tokens are obtained via OAuth 2.0 Client Credentials flow. You must use your customer's application client id and client secret to obtain the access token.
Request Body Fields
Field | Description | Format | Required |
---|---|---|---|
usageParameter | Helps LinkedIn to uniquely identify the use case for which media upload is being done. For this use case, use tcrmResumeParameters |
Complex | Required |
contentType | Type of the resume file. Valid values are: |
String | Required |
hiringContext | The contract which is signed by the customer with LinkedIn to use LinkedIn Recruiter services. Must be in the format urn:li:contract:{Id} | Recruiter contract URN | Required |
Timespan
Field | DataType |
---|---|
duration | long |
unit | ENUM values of the type: MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, YEAR |
Sample hireMediaURL Request
Headers:
Authorization: Bearer {token}
Accept:application/json
Content-Type:application/json
X-RestLi-Protocol-Version:2.0.0
Request Body (resume will be persisted in Linkedin forever):
{
"usageParameters":
{
"tcrmResumeParameters" : {}
},
"contentType": "text/plain",
"hiringContext": "urn:li:contract:123456"
}
Request Body (resume will be removed from Linkedin in 72 hours):
{
"usageParameters":
{
"tcrmResumeParameters" : {}
},
"contentType": "text/plain",
"hiringContext": "urn:li:contract:123456"
}
Sample Response
A successful request returns a 201
HTTP response code. The response has an empty body and contains a signed URL in the x-linkedin-id
response header.
Sample Response Body
HTTP/2 201
x-li-responseorigin: RGW
location: /hireMediaUrl/https%3A%2F%2Fwww.linkedin.com%2Fambry%2F%3Fx-li-ambry-ep=IKNzqXRAxc1n6yCEaLQFyikjNuvufa9i6Ek2Or5V4RpUZu8AY9CRylnLjOWX6ABe05uiXOyr0rw6hvnNcDdJLEd1Kunfn...fdfr67h
x-linkedin-id: https://www.linkedin.com/ambry/?x-li-ambry-ep=IKNzqXRAxc1n6yCEaLQFyikjNuvufa9i6Ek2Or5V4RpUZu8AY9CRylnLjOWX6ABe05uiXOyr0rw6hvnNcDdJLEd1Kunfn...fdfr67h
x-restli-protocol-version: 2.0.0
content-length: 0
date: Thu, 17 Jun 2021 09:27:30 GMT
Upload Resume File
After getting a signed URL, you can now upload the resume file by calling the below API. To define a filename, add the query parameter x-ambry-filename
to the signed URL received from the /hireMediaUrl
endpoint and use it to define the filename of the file being uploaded.
Sample Upload Request
curl -i "https://www.linkedin.com/ambry/?x-li-ambry-ep=AQEvzZSZZQH75QAAAXhws9LWCtrppkjlS2oJyQOrJA...1XFGyS1XfEvSo&x-ambry-filename={filename}" -H "Authorization: Bearer {token}" --data-binary @datafile
Sample Upload Response Response
A successful request returns a 201
HTTP response code. The response has an empty body and contains file location in the location
response header.
Sample Upload Response Body
HTTP/2 201
cache-control: no-cache, no-store
pragma: no-cache
expires: Thu, 01 Jan 1970 00:00:00 GMT
location: /AAYUAgCvAAkAAQAAAAJFyLgwRkz_TmebRMrAixANdQ.txt
x-li-uuid: HP2pABxWiRI1FsAisAAA==
date: Thu, 17 Jun 2021 09:56:58 GMT
content-length: 0
Sync Uploaded Candidate Resumes
Candidate Resumes should be synced to the Middleware Platform whenever they are created, updated, or deleted in your solution.
Throttle Limits
Throttle Limits | Requests Per Day (UTC) | Records Per Minute |
---|---|---|
Candidate Resumes maximum | 100,000 | 10,000 |
Note
Please submit batch calls grouped with no more than 100 records in sequential order.
Sync Uploaded Candidate Resumes API Endpoint
https://api.linkedin.com/v2/tcrmCandidateResumes?tcrmCandidateIdId={id1}&dataProvider=PARTNER&integrationContext={organization URN}?ids={resume id 1}
Sync Uploaded Candidate Resumes API Query String Parameters
Parameter | Description | Type | Required |
---|---|---|---|
tcrmCandidateId | Candidate identifier within external Talent CRM | String | Required |
tcrmResumeId | Resume identifier within external Talent CRM | String | Required |
integrationContext | LinkedIn company URN provided during customer onboarding, e.g. urn:li:organization:1 |
String | Required |
dataProvider | Hardcoded, this value is always PARTNER |
String | Required |
Sync Candidate Resumes via Batch Update
Perform HTTP PUT
on the /tcrmCandidateResumes
endpoint to sync candidate resumes to LinkedIn. Batch requests require the x-restli-method: batch_update
header. Multiple records can be sent in a single API request as indicated in the example below.
Sync Candidate Resumes Request Body Fields
Field | Description | Format | Required |
---|---|---|---|
tcrmCreatedAt | Date record was created in your CRM | UTC Epoch Milliseconds | Required |
resumeFile | URN using format urn:li:ambryBlob:{location} |
AmbryBlobUrn | Required |
Sample Sync Uploaded Candidate Resumes Request
curl -i -X PUT 'https://api.linkedin.com/v2/tcrmCandidateResumes?ids%5B0%5D.tcrmCandidateId=tcrmCandidateId100&ids%5B0%5D.integrationContext=urn:li:organization:1234567890&ids%5B0%5D.dataProvider=PARTNER&ids%5B0%5D.tcrmResumeId=resumeid100&ids%5B1%5D.tcrmCandidateId=tcrmCandidateId200&ids%5B1%5D.integrationContext=urn:li:organization:1234567890&ids%5B1%5D.dataProvider=PARTNER&ids%5B1%5D.tcrmResumeId=resumeid200' \
--header 'x-restli-method: batch_update' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer {access_token}' \
--data-raw '{
"entities": {
"tcrmCandidateId=tcrmCandidateId100&dataProvider=PARTNER&integrationContext=urn:li:organization:1234567890&tcrmResumeId=resumeid100": {
"resumeFile": "urn:li:ambryBlob:/AAYUAgCvAAkAAQAAAAJFyLgwRkz_TmebRMrAixANdQ.txt",
"tcrmCreatedAt": 1670935153
},
"tcrmCandidateId=tcrmCandidateId200&dataProvider=PARTNER&integrationContext=urn:li:organization:1234567890&tcrmResumeId=resumeid200": {
"resumeFile": "urn:li:ambryBlob:/AAYUAgCvAAkAAQAAAAJFyLgsRkz_TmebRMrAixxAjba1.txt",
"tcrmCreatedAt": 1670935153
}
}
} '
Sample Sync Uploaded Candidate Resumes Response
A successful request will return a 200 OK
response code, and you will find the status of each entity in the response body.
{
"results": {
"dataProvider=PARTNER&integrationContext=urn%3Ali%3Aorganization%3A1000&tcrmCandidateId=tcrmCandidateId200&tcrmResumeId=resumeid200": {
"status": 204
},
"dataProvider=PARTNER&integrationContext=urn%3Ali%3Aorganization%3A1000&tcrmCandidateId=tcrmCandidateId100&tcrmResumeId=resumeid100": {
"status": 204
}
},
"errors": {}
}
Delete Candidate Resumes
Sample Delete Uploaded Candidate Resumes Request
curl -i -X DELETE "https://api.linkedin.com/v2/tcrmCandidateResumes?ids%5B0%5D.tcrmCandidateId=tcrmCandidateId100&ids%5B0%5D.integrationContext=urn:li:organization:1234567890&ids%5B0%5D.dataProvider=PARTNER&ids%5B0%5D.tcrmResumeId=resumeid100&ids%5B1%5D.tcrmCandidateId=tcrmCandidateId200&ids%5B1%5D.integrationContext=urn:li:organization:1234567890&ids%5B1%5D.dataProvider=PARTNER&ids%5B1%5D.tcrmResumeId=resumeid200" \
--header 'Authorization: Bearer {access_token}' \
-H 'X-RestLi-Protocol-Version:1.0.0' \
-H 'Accept:application/json' \
Sample Delete Uploaded Candidate Resumes Response Body
A successful request will return a 200 OK
response code, and you will find the status of each entity in the response body.
{
"results": {
"dataProvider=PARTNER&integrationContext=urn%3Ali%3Aorganization%3A1000&tcrmCandidateId=tcrmCandidateId200&tcrmResumeId=resumeid200": {
"status": 204
},
"dataProvider=PARTNER&integrationContext=urn%3Ali%3Aorganization%3A1000&tcrmCandidateId=tcrmCandidateId100&tcrmResumeId=resumeid100": {
"status": 204
}
},
"errors": {}
}