- Overview
- Step 1. Create Indeed account
- Step 2. Register your app
- Step 3. Create a NodeJS Express app
- Step 4. Configure your app
- Create config.js file
- Configure session state
- Configure Bootstrap
- Step 5. Expose XML job feed
- Return static list of jobs
- Install npm XML library
- Add sourceName to each job
- Add XML job feed route
- Step 6. Create homepage for app
- Step 7. Authorize your app to call Indeed APIs
- Step 8. Create sponsored jobs campaign
- Create GET /campaign/create route
- Create campaign-create view
- Create POST /campaign/create route
- Create createCampaign method
- Step 9. View sponsored jobs campaigns
- List campaigns
- Get sponsored job campaign details
- Pause, unpause, and delete campaigns
Sponsored Jobs API integration guide to create NodeJS ATS
Create a NodeJS applicant tracking system using 3-legged OAuth.
Unless you have a written agreement with Indeed regarding your use of Indeed's APIs, by using this API or its documentation, you agree to apply the Indeed API Terms and the Additional API Terms and Guidelines to your use of Indeed's APIs.
Overview
This guide shows ATS partners how to build a NodeJS Express app so employers can create Sponsored Jobs campaigns through your ATS.
- Use Framework: Node.js.
- Use OAuth: 3-legged OAuth.
- Review Sample code: Sponsored Job Campaigns API.

The sample app illustrates how to:
- Share ATS jobs with Indeed using an XML job feed.
- Authorize your ATS to call the Sponsored Jobs API on behalf of employers, using 3-legged OAuth.
- Call the
/campaignsendpoint to create a Sponsored Jobs campaign.
Download the sample app code from indeedeng/sponsored-jobs-nodejs-auth-code on GitHub.
Step 1. Create Indeed account
Create an Indeed user account for your application.
To create an Indeed account:
- Go to jp.indeed.com.
- Open the Profile menu and select Sign out if you're signed in.
- Select Sign in.
- Select New to Indeed?.
- Enter your email address and password.
Step 2. Register your app
When you become an Indeed partner, Indeed sets up an app for your integration. Sign in to Partner Console to view your app and OAuth credentials (client ID, secret, and authorization code for 3-legged OAuth). Exchange credentials for an access token to authenticate API calls.
Enter the following values for the OAuth 2.0 credential type:
Register your app Field Value Public client Indicate whether the app is a public client.
If this app integrates the ATS JavaScript Plugin into your ATS site, select This application is a public client.
Allowed grant types Select the authorization code grant type. Redirect URL Define one or more redirect URLs.
If this app integrates the ATS JavaScript Plugin into your ATS site, add the URL of the page that loads the plugin.
Select Save and continue.
Indicate whether you want your app to be reviewed, then select Save and continue. If you skip review, users see a warning that your app hasn't been reviewed.
Optionally provide additional company information, then select Save and continue.
Preview your app information, then select Complete registration.
The page shows your client ID (and, for non-public clients, your client secret). Keep these credentials secure: never share them or commit them to a public Git repository.
Step 3. Create a NodeJS Express app
The sample Node.js Express app uses the open-source openid-client library to let the OAuth client app call the Indeed API.
To create the Node.js Express app:
-
Download and install Node.js and npm.
-
Generate the
Find-TalentExpress app with the HandlebarsJS view engine:npx express-generator Find-Talent --view=hbs --gitThe
--gitoption generates a.gitignorefile for Express. -
Change into the directory that contains the
package.jsonfile: -
Install the required npm packages:
npm install -
Update your
package.jsonfile so that it includes theopenid-clientlibrary:npm install openid-client -
Install the open-source Axios library, which updates your
package.jsonfile:npm install axios -
Start your Express app:
npm start -
Open http://localhost:3000/.
The default Express index page appears with the message
Welcome to Express.
Step 4. Configure your app
To configure your Express app, create a configuration file, set up the session state, and enable Bootstrap.
Create config.js file
To store your secrets, create a config.js file in the root of the Find-Talent app with this content:
const config = { oysterBaseURL: 'https://apis.indeed.com/ads/v1', oauthDiscovery: 'https://secure.indeed.com/.well-known/openid-configuration', oauthClientId: '90f9f4bd6a34cac31daebe1a093a606ce6b34e91ae6cfa139432ae387269a529', oauthClientSecret: 'bML2BGshr8mLng6d1c1qCujH2PgblxEJwW5WqLxpr32XWfAFSonlhIE07buG7Nlr', oauthRedirectURL: 'http://localhost:3000/oauth-callback', scope: 'employer_access offline_access employer.advertising.account.read employer.advertising.campaign', sessionSecret: 'Something Secret!',};
module.exports = config;Notice the scope setting. This setting lists all scopes, which are the permissions that your OAuth app needs.
For example, to create sponsored jobs campaigns, include employer.advertising.campaign.
For the list of scopes, see Sponsored Jobs API scopes for ATS partners.
Replace oauthClientId and oauthClientSecret with the client ID and client secret for your registered OAuth app. You can find them on the Manage app credentials page.
The sessionSecret setting is used for Express session state. Replace Something Secret! with a new secret of your choice.
Because config.js contains secrets, do not make this file public. For example, do not store config.js in a public GitHub repository.
Configure session state
To avoid requesting an access token repeatedly, store the access token in session state. To enable session state for your Express app, run this command:
npm install express-sessionThis command adds a dependency to the package.json file.

To configure session state, you modify the app.js file. Add this code near the top of the app.js file:
const config = require('./config');const session = require('express-session');Next, find this line of code in the app.js file:
var app=express(); Add this code immediately below it:
// session setupapp.use(session({ secret: config.sessionSecret, resave: false, saveUninitialized: true, cookie: { secure: false },}));You can use req.session in your controllers to store data in session state across multiple requests.
Configure Bootstrap
To style your app quickly, use the open-source Bootstrap CSS framework. Open the views/layout.hbs file and add this code directly below the <title> tag:
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>The complete layout.hbs page template file looks like this:
<!DOCTYPE html><html> <head> <title>Sponsor Jobs</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous"> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
<link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> {{>header}} <div class="container"> {{{body}}} </div> </body></html>Step 5. Expose XML job feed
Before an employer can sponsor a job on Indeed, Indeed must know about the job. To make jobs hosted on your ATS available to Indeed, expose an XML job feed. This section explains the correct format for the XML job feed.
Return static list of jobs
In a real ATS, employers' jobs are stored in a database. To keep the sample app simple, create a method that returns a static list of jobs:
static listJobs() { return [ { id: 2312, title: 'Product Manager', description: 'Manage products', posted: new Date('1/12/2021'), url: 'https://example.com/job/2312', city: 'Seattle', state: 'WA', country: 'USA', }, { id: 2313, title: 'Python Engineer', description: 'Must be an expert in Django.', posted: new Date('1/12/2021'), url: 'https://example.com/job/2313', city: 'Seattle', state: 'WA', country: 'USA', }, { id: 2314, title: 'Senior Python Engineer', description: 'Must be an expert in Django.', posted: new Date('1/12/2021'), url: 'https://example.com/job/2314', city: 'Seattle', state: 'WA', country: 'USA', }, ];}You can find this method in the \services\JobService.js file.
Install npm XML library
To convert the list of jobs into XML, use the Node Package Manager (npm) XML library. To install the XML library:
npm install xmlAdd sourceName to each job
Verify that each job includes all data that Indeed requires. In particular, each job must include a referenceNumber and a sourceName. This method, which is also in the services\JobService.js file, adds the required data:
static listJobsAsXML() { const jobs = this.listJobs().map((j) => ({ job: [ { title: { _cdata: j.title } }, { description: { _cdata: j.description } }, { date: { _cdata: j.posted } }, { referenceNumber: { _cdata: j.id } }, { url: { _cdata: j.url } }, { company: { _cdata: 'US Robotics and Mechanical Men' } }, { sourceName: { _cdata: 'Apple' } }, { city: { _cdata: j.city } }, { state: { _cdata: j.state } }, { country: { _cdata: j.country } }, { email: { _cdata: 'your_email@your_company.com' } }, { metadata: { _cdata: '' } }, ], }));
return [ { source: [ { publisher: 'Superhero ATS' }, { publisherurl: 'https://example.com' }, { lastBuildDate: Date() }, ...jobs, ], }, ];}The listJobsAsXML() method converts each job into a format that Indeed can read. Notice that each job includes both a referenceNumber, which is a unique ID, and a sourceName, which is set to Apple. Indeed uses sourceName to associate each job with the correct employer.
Add XML job feed route
Next, expose your job list as XML. Add the following jobFeed.js file to your app's routes folder:
const express = require('express');const xml = require('xml');const JobService = require('../services/JobService');
const router = express.Router();
router.get('/', async (req, res) => { res.contentType('application/xml'); res.send(xml(JobService.listJobsAsXML(), true));});
module.exports = router;This route calls the listJobsAsXML() method and passes the result to the XML library. It exposes the job list as XML in a format that Indeed can read:
<source> <publisher>Superhero ATS</publisher> <publisherurl>https://example.com</publisherurl> <lastBuildDate>Mon May 24 2021 14:43:59 GMT-0700 (Pacific Daylight Time)</lastBuildDate> <job> <title><![CDATA[Product Manager]]></title> <description><![CDATA[Manage products]]></description> <date><![CDATA[Tue Jan 12 2021 00:00:00 GMT-0800 (Pacific Standard Time)]]></date> <referenceNumber><![CDATA[2312]]></referenceNumber> <url><![CDATA[https://example.com/job/2312]]></url> <company><![CDATA[US Robotics and Mechanical Men]]></company> <sourceName><![CDATA[Apple]]></sourceName> <city><![CDATA[Seattle]]></city> <state><![CDATA[WA]]></state> <country><![CDATA[USA]]></country> <email><![CDATA[your_email@your_company.com]]></email> <metadata/> </job> <job> <title><![CDATA[Python Engineer]]></title> <description><![CDATA[Must be an expert in Django.]]></description> <date><![CDATA[Tue Jan 12 2021 00:00:00 GMT-0800 (Pacific Standard Time)]]></date> <referenceNumber><![CDATA[2313]]></referenceNumber> <url><![CDATA[https://example.com/job/2313]]></url> <company><![CDATA[US Robotics and Mechanical Men]]></company> <sourceName><![CDATA[Apple]]></sourceName> <city><![CDATA[Seattle]]></city> <state><![CDATA[WA]]></state> <country><![CDATA[USA]]></country> <email><![CDATA[your_email@your_company.com]]></email> <metadata/> </job> <job> <title><![CDATA[Senior Python Engineer]]></title> <description><![CDATA[Must be an expert in Django.]]></description> <date><![CDATA[Tue Jan 12 2021 00:00:00 GMT-0800 (Pacific Standard Time)]]></date> <referenceNumber><![CDATA[2314]]></referenceNumber> <url><![CDATA[https://example.com/job/2314]]></url> <company><![CDATA[US Robotics and Mechanical Men]]></company> <sourceName><![CDATA[Apple]]></sourceName> <city><![CDATA[Seattle]]></city> <state><![CDATA[WA]]></state> <country><![CDATA[USA]]></country> <email><![CDATA[your_email@your_company.com]]></email> <metadata/> </job></source>Step 6. Create homepage for app
The homepage of the sample app lists jobs with a Sponsor with Indeed button next to each job.

The homepage uses the JobService listJobs() method.
The JavaScript code for the homepage in routes\index.js is:
const express = require('express');const JobService = require('../services/JobService');
const router = express.Router();
/* GET home page. */router.get('/', async (req, res) => { const jobs = JobService.listJobs(); res.render('index', { jobs, });});
module.exports = router;This view is for the homepage:
<h1>Your Jobs</h1>
{{#unless jobs}} <div class="alert alert-primary mt-3" role="alert"> <p> You don't have any jobs. </p> </div>{{else}}<table class="table"> <thead> <tr> <th scope="col">Title</th> <th scope="col">City</th> <th scope="col">Country</th> <th scope="col">Action</th> </tr> </thead> <tbody> {{#each jobs}} <tr> <th scope="row">{{this.title}}</th> <td>{{this.city}}</td> <td>{{this.country}}</td> <td><a href="/campaign/create/{{this.id}}" class="btn btn-primary btn-sm" role="button">Sponsor with Indeed</a></td> </tr> {{/each}} </tbody></table>{{/unless}}When an employer selects Sponsor with Indeed, the app sends the employer to the /campaign/create route.
Step 7. Authorize your app to call Indeed APIs
The sample app uses Express middleware to enforce OAuth authorization. The middleware checks whether the current user has an OAuth access token. If not, it redirects the user to the Indeed OAuth consent screen.
The Express middleware is in the middleware\IndeedOAuthAuthorize.js file:
const config = require('../config');const IndeedOAuthService = require('../services/IndeedOAuthService');
async function IndeedOAuthAuthorize(req, res, next) { const indeedOAuth = new IndeedOAuthService(config, req.session); const tokenSet = await indeedOAuth.getTokenSet(null);
if (!tokenSet) { req.session.returnUrl = req.originalUrl; const authorizeURL = await indeedOAuth.getAuthorizeURL('employer_access offline_access'); res.redirect(authorizeURL); } else { res.locals.tokenSet = tokenSet; next(); }}
module.exports = IndeedOAuthAuthorize;The IndeedOAuthAuthorize middleware enforces authorization for each of the routes that require an OAuth access token. For example, the Sponsor with Indeed button links to the /campaign/create route.
The app uses IndeedOAuthAuthorize middleware with this route:
router.get('/create/:jobId', IndeedOAuthAuthorize, async (req, res) => { ....ommited...}If an employer using the ATS requests the /campaign/create route and the app is not authorized to act for that employer, the app redirects the employer to the OAuth consent screen:

After the employer selects Allow, the OAuth employer selection screen appears. This screen lets the employer choose which employer to associate with the OAuth access token. For example, in the following image, the employer can select US Robotics and Mechanical Men.

After the employer selects Continue, the sample app gets an OAuth access token from Indeed and stores it in session state. If the employer later selects another route that requires authorization, the middleware can read the access token directly from session state, so the employer does not need to authorize the app again.
Step 8. Create sponsored jobs campaign
To let an employer sponsor any of their Indeed jobs, create an Indeed sponsored jobs campaign.
Create GET /campaign/create route
Create the campaign.js route to handle an HTTP GET request:
router.get('/create/:jobId', IndeedOAuthAuthorize, async (req, res) => { const jobId = Number(req.params.jobId); const job = JobService.getJob(jobId); const campaignService = new CampaignService(config, req.session, res.locals.tokenSet);
// get account const account = await campaignService.getAccount(); if (!account.jobSourceList || account.jobSourceList.length === 0) { res.redirect('/campaign/no-job-source'); } else { // create campaign defaults const newCampaign = { startDate: getISODateString(new Date()), targetEndDate: getISODateString(getFutureDate(3)), budgetMonthlyLimit: 100.00, budgetOneTimeLimit: 100.00, };
res.render('campaign-create', { job, newCampaign, }); }});Notice that the code calls the campaignService.getAccount() method to get the employer's Indeed account. This method returns a response like this:
{ "jobSourceList": [{ "id": "67c9fd651aff79bf", "siteName": "Apple" }], "contact": "Susan Calvin", "company": "US Robotics and Mechanical Men", "id": "5266416001932948", "email": "indeed.sample.app+employer@gmail.com"}The returned account information includes a jobSourceList. Each job source has an id and a siteName. The siteName must match the sourceName for each job in the XML job feed. See Add sourceName to each job. Use the id and siteName to create a sponsored jobs campaign.
The route checks whether the account includes at least one job source. If it does not, the employer cannot sponsor a job, and the sample app shows an error page.

Create campaign-create view
If the account includes at least one job source, the sample app shows the create-campaign view. This view lets the employer set a budget to sponsor a job on Indeed. The employer can choose to set a monthly budget:

Or, the employer can decide to set a one-time budget with start and end dates:

The markup to create the create-campaign view is:
<h1>Sponsor with Indeed</h1>
<p> Sponsor the <b>{{job.title}}</b> job with Indeed by completing the following form.</p>
<form method="post" action="/campaign/create/{{job.id}}">
<div class="row g-3"> <div class="col"> <p> Select how you want to spend your advertising budget. </p> <div class="form-check form-check-inline"> <input class="form-check-input" name="selectBudgetType" type="radio" id="monthlyRadio" value="monthly" checked /> <label class="form-check-label" for="monthlyRadio">Monthly Budget Limit</label> </div>
<div class="form-check form-check-inline"> <input class="form-check-input" name="selectBudgetType" type="radio" id="oneTimeRadio" value="oneTime"> <label class="form-check-label" for="oneTimeRadio">One Time Budget Limit</label> </div> </div> </div>
<fieldset id="monthly" class="mt-2"> <legend>Monthly Budget Limit</legend>
<div class="row mb-3"> <div class="col"> <label for="budgetMonthlyLimit" class="form-label">Budget</label> <div class="input-group mb-3"> <span class="input-group-text">$</span> <input name="budgetMonthlyLimit" id="budgetMonthlyLimit" type="number" min="50" step="any" class="form-control" placeholder="Budget" value="{{newCampaign.budgetMonthlyLimit}}" /> </div> </div> </div>
</fieldset>
<fieldset id="oneTime" style="display:none" class="mt-2"> <legend>One Time Budget Limit</legend>
<div class="row mb-3"> <div class="col form-group"> <label for="budgetOneTimeLimit" class="form-label">Budget</label> <div class="input-group mb-3"> <span class="input-group-text">$</span> <input name="budgetOneTimeLimit" id="budgetOneTimeLimit" type="number" min="50" step="any" class="form-control" value="{{newCampaign.budgetOneTimeLimit}}" /> </div> </div> </div>
<div class="row mb-3"> <div class="col"> <label for="startDate" class="form-label">Start Date</label> <input name="startDate" id="startDate" type="date" class="form-control" placeholder="Start Date" value="{{newCampaign.startDate}}" /> </div> <div class="col"> <label for="targetEndDate" class="form-label">Target End Date</label> <input name="targetEndDate" id="targetEndDate" type="date" class="form-control" placeholder="Target End Date" value="{{newCampaign.targetEndDate}}" /> </div> </div>
</fieldset>
<div class="row mb-3"> <div class="col"> <a class="btn btn-secondary mr-2" href="/">Cancel</a> <button type="submit" class="btn btn-primary">Submit</button> </div> </div>
</form>
<script> const monthly = document.getElementById('monthly'); const oneTime = document.getElementById('oneTime');
document.getElementById('oneTimeRadio').addEventListener('click', (e) => { monthly.style.display = 'none'; oneTime.style.display = 'block'; });
document.getElementById('monthlyRadio').addEventListener('click', (e) => { monthly.style.display = 'block'; oneTime.style.display = 'none'; });</script>The markup uses Bootstrap to create an HTML form. The form includes two fieldsets:
- Include one fieldset for the monthly budget.
- Include one fieldset for the one-time budget.
A small amount of JavaScript at the bottom of the view shows only one fieldset at a time.
Create POST /campaign/create route
When an employer submits the form in the create-campaign view, the sample app calls the POST /campaign/create route. This route gets the form field values and calls the JobService createCampaign() method to create the sponsored jobs campaign.
router.post('/create/:jobId', IndeedOAuthAuthorize, async (req, res) => { const campaignService = new CampaignService(config, req.session, res.locals.tokenSet);
// get job const jobId = Number(req.params.jobId); const job = JobService.getJob(jobId);
// get form fields const newCampaign = { name: `${job.title} - ${new Date().toUTCString()}`, budgetType: req.body.selectBudgetType, budgetMonthlyLimit: Number(req.body.budgetMonthlyLimit), budgetOneTimeLimit: Number(req.body.budgetOneTimeLimit), startDate: getISODateString(new Date(req.body.startDate)), targetEndDate: getISODateString(new Date(req.body.targetEndDate)), };
// get account const account = await campaignService.getAccount();
// sponsor job campaignService.createCampaign(account, job, newCampaign);
res.redirect('/');});Create createCampaign method
The createCampaign() method in services\JobService.js calls the Sponsored Jobs API and creates the job campaign.
Notice that createCampaign() uses the job source ID and siteName to create the campaign. The sample app gets the siteName from the employer account.
The sample code also includes the job ID, which is the reference number from the XML job feed, in the Sponsored Jobs API request.
async createCampaign(account, job, newCampaign) { let request = { name: newCampaign.name, jobsSourceId: account.jobSourceList[0].id, jobsSourceName: account.jobSourceList[0].siteName, jobsToInclude: 'query', jobsQuery: `refnum:${job.id}`, };
if (newCampaign.budgetType === 'monthly') { request = { ...request, ...{ budgetMonthlyLimit: newCampaign.budgetMonthlyLimit, budgetFirstMonthBehavior: 'startNowProratedAmount', }, }; } if (newCampaign.budgetType === 'oneTime') { request = { ...request, ...{ budgetOnetimeLimit: newCampaign.budgetOneTimeLimit, startDate: newCampaign.startDate, targetEndDate: newCampaign.targetEndDate, }, }; } const url = `${this.config.oysterBaseURL}/campaigns`; const results = await this.requestResource(url, 'POST', request); return results;}The createCampaign() method calls the Indeed Sponsored Jobs API through requestResource(), which uses Axios to make the HTTP request.
The sample code passes the OAuth access token in the Authorization header. Indeed rejects any request that omits it.
async requestResource(url, method = 'GET', data) { console.info(`Axios ${method}: ${url}`); try { const results = await axios({ url, method, headers: { Authorization: `Bearer ${this.tokenSet.access_token}`, }, data, }); return results.data.data; } catch (err) { console.error('Error when making request'); console.dir(err.response.data, { depth: null }); throw err; }}After an employer submits the form to create a sponsored jobs campaign, redirect the employer to the sample app homepage.
Step 9. View sponsored jobs campaigns
An employer can select Manage Sponsored Jobs Campaigns in the header to list all campaigns.
You can list campaigns, get details for a specific campaign, and pause, unpause, or delete campaigns.

List campaigns
To list campaigns for an employer, make a GET request against the /campaigns endpoint.
The getCampaigns() method from the CampaignService.js file is:
async getCampaigns() { const url = `${this.config.oysterBaseURL}/campaigns`; const results = await this.requestResource(url); // filter out deleted campaigns return results.Campaigns.filter((c) => c.Status !== 'DELETED');}This method returns a JSON response:
[{ "Name": "Senior Python Engineer - Sat, 01 May 2021 16:58:47 GMT", "Id": "a6fde835690ecf9d", "Status": "PAUSED" }, { "Name": "Senior Python Engineer - Thu, 06 May 2021 17:42:40 GMT", "Id": "d0fb6cf60753eef3", "Status": "ACTIVE" },
{ "Name": "Product Manager - Fri, 21 May 2021 21:10:14 GMT", "Id": "8881f81292b2bf48", "Status": "ACTIVE" }]The response includes the Name, Id, and Status fields for each campaign.
A campaign can be ACTIVE, PAUSED, or DELETED.
The getCampaigns() method removes any deleted campaigns.
Get sponsored job campaign details
To view details for a sponsored job campaign, an employer can select View.


The sample code get the campaign details through the getCampaignDetails() method in the CampaignService class:
async getCampaignDetails(campaignId) { // get campaign general info const generalUrl = `${this.config.oysterBaseURL}/campaigns/${campaignId}`; const general = await this.requestResource(generalUrl);
// get campaign budget info const budgetUrl = `${this.config.oysterBaseURL}/campaigns/${campaignId}/budget`; const budget = await this.requestResource(budgetUrl);
// get campaign properties info const propertiesUrl = `${this.config.oysterBaseURL}/campaigns/${campaignId}/properties`; const properties = await this.requestResource(propertiesUrl);
return { ...general, ...budget, ...properties, };}The getCampaignDetails() method calls these Indeed endpoints:
- Call
/campaigns/<id>to get general campaign information. - Call
/campaigns/<id>/budgetto get campaign budget information. - Call
/campaigns/<id>/propertiesto get campaign property information.
The view combines and displays the data from these endpoints.
Pause, unpause, and delete campaigns
An employer can pause, unpause, or delete a campaign by changing its status. The updateCampaignStatus() method sends a PATCH request to the /campaigns/<id> endpoint to update the campaign status:
async updateCampaignStatus(campaignId, newStatus) { const url = `${this.config.oysterBaseURL}/campaigns/${campaignId}`; const results = await this.requestResource(url, 'PATCH', { status: newStatus, }); return results.Campaigns;}When you delete a campaign, the campaign status changes to DELETED, but the campaign is not removed:
