Share via


Sync Candidate Resumes

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:

  1. Create URL
  2. Upload Resume File

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:
  • "text/plain" for TXT file
  • "application/pdf" for PDF file
  • "application/msword" for DOC file
  • 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": {}
    }