Pay For Performance (P4P) Job Posting

Try in Postman

The LinkedIn's Pay For Performance (P4P) Job Posting enables posting of P4P jobs to LinkedIn from external solutions. P4P Job Posting is an extension of LinkedIn's Job Posting, and the job posting API request format is a superset of the format used for Promoted Jobs unless you are ingesting jobs via XML feed.

What To Expect

Important

Please read below thoroughly to understand the right next steps for your use case.

Implementation requirements vary depending on your offering and objectives:

  • For any partners, to view your P4P jobs and budgets, you will need to configure the P4P Reports API. This API has a similar usage to Check Job Posting Statuses API which you can also check the status of the posted jobs with externalJobPostingId or partnerJobCode, if applicable. You can find sample API requests from the "Try in Postman" collection above. You will need to join the LinkedIn Workspace and be approved to access it. Each partner will be requested to create a LinkedIn Developer Application to be the master or parent key of any LinkedIn Talent Solutions API integrations. With this key, you will be able to generate child applications with the Provisioning API to represent each client configuration within your partnership ecosystem. Please find a diagram below for a visual aid. To self-provision and activate each child app to be ready for posting or managing jobs or campaigns, you will need to call Provision Customer Hiring Contracts API.
  • If you are a Job Distributor (JD) or ATS partner who allows customers to buy individual job advertisements on Job Boards, you will need to add PayForPerformanceTotalBudget to your job posting request as in the Job Posting Schema with Pay For Performance (P4P) Extension. To learn more about how to post P4P jobs via API, please proceed to the section Sample Request for P4P Job Posting API below. Note that P4P Job Campaign API is NOT used to manage individual job advertisements.
  • If you are a Recruitment Advertising Agency (RAA) partner that posts jobs on behalf of customers via Campaigns, you will need to understand the P4P Job Campaign API to set up. A campaign is a series of goals that allow the sharing a single theme for more organized job management and related communications. It lets you group and strategize your customers' jobs and their budgets. Regardless of whether you post jobs via XML or API, campaign creation and maintenance should be handled by this API. If you post jobs via XML feed, please move on to the P4P Job Campaign API for your next step, and skip the Sample Request for P4P Job Posting API below. Keep in mind that, in your XML feed, you will need to add up to 3 fields to support P4P-specific job management as you can find them under Pay For Performance (P4P) Jobs XML Extension Schema. If you post jobs via API, please proceed to the section Sample Request for P4P Job Posting API below with the extended schema. Make sure that the contract and expireAt fields work differently in RAA than the rest of the Job Posting products as described in the Sample Request Body for Job Creation Note.

To help understand here is a brief diagram of what the Parent-Child Developer Application relationship is like and how to activate your customer per product: Redirect URLS

Once development is ready for certification, please contact your Partner Solutions Engineer and Business Development contacts to setup a meeting.

Sample Request for P4P Job Posting API

In order to post a job as P4P, you need to provide listingType field value as PREMIUM with the right contract.

Note

  • Only selective partners have the permission to post P4P jobs. If your developer application does not support posting P4P jobs, please reach out to LinkedIn's business development point of contact, if interested.
  • If you'd like to know more about Simple Job Postings (SJP) API, please visit Job Posting Overview.
curl --location --request POST 'https://api.linkedin.com/v2/simpleJobPostings' \
--header 'Authorization: Bearer {access_token}' \
--header 'x-restli-method: batch_create'

Note

  • You should generate the {access_token} from the Child Developer Application (via Provisioning API) that represents each Client account of yours.

Sample Request Body for Job Creation

Standard Job Creation

{
   "elements":[
      {
         "integrationContext": "urn:li:company:{your_company_id}",
         "contract": "urn:li:contract:{your_contract_id}",
         "companyApplyUrl": "https://careers.yourcompany.com",
         "externalJobPostingId": "PromotedJobPostingG1TC1",
         "companyJobCode": "ATS-SourceID_or_externalJobPostingId_of_this_job",
         "posterEmail": "poster@linkedin.com",
         "jobPostingOperationType": "CREATE",
         "title": "Promoted Job Posting G1 TC1",         
         "description": "<b>Objective of the Position</b><br/> <ul> <li>To develop digital content plan, manage and monitor different content executions for social and online platforms to maximize the communication effectiveness and impact</li> <li>To manage, monitor and keep optimizing the performance of social platforms of MB and AMG</li> <li>To monitor and manage internet word of mouth to keep the health of brand and product image</li></ul>",
         "listedAt": 1513756352000,
         "location":"San Francisco, CA",
         "industries": [
            "urn:li:industry:55"
         ],         
         "budget": {
            "payForPerformanceTotalBudget": {
             "currencyCode": "USD",
             "amount": "275.00"
            }
         },
         "listingType": "PREMIUM"
      }  
   ]
}

RAA Job Creation

{
   "elements":[
      {
         "integrationContext": "urn:li:company:{your_company_id}",
         "companyApplyUrl": "https://careers.yourcompany.com",
         "externalJobPostingId": "PromotedJobPostingG1TC1",
         "companyJobCode": "ATS-SourceID_or_externalJobPostingId_of_this_job",
         "posterEmail": "poster@linkedin.com",
         "jobPostingOperationType": "CREATE",
         "title": "Promoted Job Posting G1 TC1",         
         "description": "<b>Objective of the Position</b><br/> <ul> <li>To develop digital content plan, manage and monitor different content executions for social and online platforms to maximize the communication effectiveness and impact</li> <li>To manage, monitor and keep optimizing the performance of social platforms of MB and AMG</li> <li>To monitor and manage internet word of mouth to keep the health of brand and product image</li></ul>",
         "listedAt": 1513756352000,
         "location":"San Francisco, CA",
         "industries": [
            "urn:li:industry:55"
         ],
         "listingType": "PREMIUM",
         "partnerJobCampaignId": "abcd1234"
      }  
   ]
}

Note

  • From PP4P General Availability (GA), integrationContext - company or organization ID or companyPageURL is required to fill out.
  • Ensure that requests do not include duplicate updates to the same externalJobPostingId. The same contents under two different externalJobPostingId will not be considered as a duplicate job.
  • It is mandatory to provide contract information in integrationContext or contract with the exception of the Recruitment Advertising Agency (RAA) partner. For RAA, please do not fill out the contract field, and the appropriate values will be looked up by the correct child application {access_token} associated with the right campaign.
  • If the posterEmail field is not provided or correct, the job will be posted on behalf of the default job poster email as it was configured in your contract.
  • For budget.payForPerformanceTotalBudget.amount, there will be 3-tier presets (low, medium & high) you must decide before sending jobs with your LinkedIn Business Development (BD) counterpart. Please note that RAA jobs will load the budget from the associated campaign.
  • To update the budget you must use RENEW jobPostingOperationType to send the request with the new amount like a normal UPDATE operation. The difference is that this will reset your job's duration to 30 days to the latest amount.
  • Only for RAA, expireAt will be fixed to 30 days from the listedAt. As far as the associated job campaign exists, the job will auto-renew.
  • companyJobCode is now required to provide to ensure the job quality especially if you are integrating with other LinkedIn products, such as Onsite Apply or Apply Connect, as the next enhancement. If you have the job's unique ID (also known as requisition ID) from the original source such as ATS, please provide that. Otherwise, you can duplicate an externalJobPostingId value into it.

Sample Request Body for Job Upgrade

Simple Job Posting (SJP) API supports an update of the created jobs, too. This is not a P4P-specific operation, and one can find general guidelines and expectations on the Update and Renew Jobs page. For P4P, if you have free/Basic jobs with LinkedIn, too, you can upgrade them to P4P jobs via this update operation. Please use Check the Job Operation Task Status API to check the asynchronous operation status as you do for regular API-posted jobs.

{
   "elements":[
      {
         "integrationContext": "urn:li:company:{your_company_id}",
         "contract": "urn:li:contract:{your_contract_id}",
         "companyApplyUrl": "https://careers.yourcompany.com",
         "externalJobPostingId": "UpgradeJobPostingG1TC1",
         "posterEmail": "poster@linkedin.com",
         "jobPostingOperationType": "UPDATE",
         "title": "Upgraded Job Posting G1 TC1",         
         "description": "<b>Objective of the Position</b><br/> <ul> <li>To develop digital content plan, manage and monitor different content executions for social and online platforms to maximize the communication effectiveness and impact</li> <li>To manage, monitor and keep optimizing the performance of social platforms of MB and AMG</li> <li>To monitor and manage internet word of mouth to keep the health of brand and product image</li></ul>",
         "listedAt": 1705648400000,
         "location":"San Francisco, CA",
         "industries": [
            "urn:li:industry:55"
         ],         
         "budget": {
            "payForPerformanceTotalBudget": {
             "currencyCode": "USD",
             "amount": "275.00"
            }
         },
         "listingType": "PREMIUM"
      }  
   ]
}

Note

  • listingType must be PREMIUM and budget is mandatory to provide to upgrade a free job to P4P.
  • Once ugraded, the listing date of the job will be the time of the upgrade, and it will expire after 30 days from that date.
  • Upgrade with an incorrect budget.amount, such as $1,000, will be rejected.

Sample Request Body for Job Downgrade

One can also downgrade a P4P job to the free/Basic job with the same update operation as you do to upgrade. Please use Check the Job Operation Task Status API to check the asynchronous operation status.

{
   "elements":[
      {
         "integrationContext": "urn:li:company:{your_company_id}",
         "contract": "urn:li:contract:{your_contract_id}",
         "companyApplyUrl": "https://careers.yourcompany.com",
         "externalJobPostingId": "DowngradeJobPostingG1TC1",
         "posterEmail": "poster@linkedin.com",
         "jobPostingOperationType": "UPDATE",
         "title": "Downgraded Free Job Posting G1 TC1",         
         "description": "<b>Objective of the Position</b><br/> <ul> <li>To develop digital content plan, manage and monitor different content executions for social and online platforms to maximize the communication effectiveness and impact</li> <li>To manage, monitor and keep optimizing the performance of social platforms of MB and AMG</li> <li>To monitor and manage internet word of mouth to keep the health of brand and product image</li></ul>",
         "listedAt": 1705648400000,
         "location":"San Francisco, CA",
         "industries": [
            "urn:li:industry:55"
         ],         
         "listingType": "BASIC"
      }  
   ]
}

Note

  • listingType must be BASIC and budget should be removed to successfully downgrade a job.
  • Downgrading a job will not change created, listed and expiring dates of the job.

Sample Response Body

For Success

A successful request returns a 200 OK response code, and you will find the simpleJobPostingTaskIDs in the response body.

{
    "elements": [
        {
            "id": "urn:li:simpleJobPostingTask:03ff7ca6-dedf-4d92-b856-10669f8fe5ef",
            "status": 202
        }
    ]
}

For Error

In case of an error, the request will return a 200 OK response code and the error message is within the response body like an example below.

{
   "elements": [
      {
      "error": {
         "message": "ERROR :: /title :: field is required but not found and has no default value\n",
         "status": 422
      },
      "status": 422
      }
   ]
}

Note

  • Please make sure to check and record the response for error status corresponding to an individual job you submit.
  • The Task ids returned in the above responses are valid for 24 hours.
  • Check the Job Operation Task Status to find the status of the job posting via above task ids.
  • If you already have paid job contract with LinkedIn, please use the contract. If you post a P4P job that is already posted with the contract, your job will fail and considered as a duplicate. The same happens if you have already posted a P4P job, but you are trying to post the same free job.

API Error Details

In addition to the regular errors you can encounter with /simpleJobPostings, you can have more errors and validations specific to P4P.

HTTP CODE RESPONSE STATUS ERROR MESSAGE DESCRIPTION RESOLUTION
400 400 Please authenticate your LinkedIn contract with the LI job posting widget to promote your Job Post to a recommended budget. Customer of the job already has a premium job posting (e.g.) contract with LinkedIn. Please use the existing contract first before posting via P4P.
400 400 Invalid currencyCode was provided in the budget. Please check the contract for supported currencyCode. No currency was setup for contract. Please reach out to your Business Development contact to check the contract.
400 400 Invalid budget amount was provided in the parameter: {payForPerformanceTotalBudget={currencyCode=usd, amount=}} No total budget was setup for contract. Please reach out to your Business Development contact to check the contract.
400 400 Invalid budget amount was provided in the parameter: {payForPerformanceTotalBudget={currencyCode=usd, amount=1.000}} Decimal places exceeded the limit of 2. Please send a budget amount in the two decimal places of ".xx".
400 400 Invalid budget amount was provided in the parameter: {payForPerformanceTotalBudget={currencyCode=usd, amount=a}} Amount was not a number. Please send a numeric budget amount.
400 400 Invalid budget amount was provided in the parameter: {payForPerformanceTotalBudget={currencyCode=usd, amount=-1.00}} Amount was not a positive number. Please send a positive budget amount.
400 400 Invalid budget amount was provided in the parameter: {payForPerformanceTotalBudget={currencyCode=usd, amount=10001.00}} Amount exceeded the budget limitation per job. Please send a budget amount less than USD $10,000 per job. If your currencyCode is other than USD, then please do the conversion to match.
400 400 Job is not qualified to have a budget. Your contract is not qualified for P4P, or the customer may already have a PJP (Premium) or other contract with LinkedIn. Please make sure that the customer will need to post jobs to the existing contract first. To learn more about P4P, please reach out to your LinkedIn BD counterpart.
400 400 Invalid currencyCode was provided in the budget. Please check the contract for supported currencyCode. currencyCode was empty or not recognizable. Please send a valid, ISO 4217 standard currencyCode .
400 400 Invalid currencyCode was provided in the budget. Please check the contract for supported currencyCode. currencyCode was provided, but not matching with the currency in your P4P contract. Please reach out to your Business Development contact to check the contract.
400 400 The payloads for partner job {external-job-posting-id} creation must have field CompanyApplyUrl & sourceDomain. Basic P4P job with no companyApplyUrl. Please provide CompanyApplyUrl and sourceDomain.
400 400 The payloads for partner job {external-job-posting-id} creation must have field CompanyApplyUrl & sourceDomain. Premium P4P job with no companyApplyUrl. Please provide CompanyApplyUrl and sourceDomain.
400 400 The payloads for basic job {external-job-posting-id} creation must have field CompanyApplyUrl & sourceDomain. Basic slot job with no companyApplyUrl. Please provide companyApplyUrl.
400 400 The partner job campaign id is not found in the payload. The partnerJobCampaignID is not provided in the payload. Please provide a campaign id.
400 400 The partner job campaign does not exist. The campaign provided in the payload does not exist. Please provide a valid campaign id.
400 400 The partner job campaign is not active. The campaign provided in the payload is not active. Please provide a valid campaign id.
400 400 The customer contract does not exist for developer application {your Child application ID}. The campaign provided in the payload is not active. Please provide a valid campaign id.
400 400 The renew operation is not supported for this job. The jobPostingOperationType is RENEW. Please use a valid operation type - CREATE/UPDATE/CLOSE.
400 400 The budget field should not be present in the payload for this job. The budget field is included in the payload. Please remove the budget field.
400 400 The expireAt is not supported for this job. The expireAt field is included in the payload. Please remove the expireAt field.
400 400 This job cannot be of type BASIC. The listingType is BASIC. Please change the listingType to PREMIUM.
402 402 Payment Required returned for https://api.linkedin.com/v2/simpleJobPostings/. Your contract is out of the budget. Please reach out to your Business Development contact to check the contract.
406 406 Operation type UPDATE is not allowed for a non-existing job of partner urn urn:li:partner:{your Parent application ID}, partner job code {your LinkedIn job code}. The job you were you were trying to update did not exist. Please re-CREATE your job after resolving the cause of the failure. You can know about the root causes by using the Job Operation Task Status API.
422 422 ERROR :: /budget/payForPerformanceTotalBudget/currencyCode :: field is required but not found and has no default value. currencyCode was null and the field was not provided. Please send a valid, ISO 4217 standard currencyCode .