- Integrate with the Hiring Lab API
- Get an API key
- Authenticate your requests
- Test your integration
- Handle authentication errors
- Hiring Lab API overview
- Key features
- Available datasets
- Get job postings data
- Regional job postings data
- Sectoral job postings data
- Get remote work data
- Get wage growth data
- Get AI job postings data
- List available data coverage
- List countries with data coverage
- List available sectors
- List available geographies
- List available regions
- List all datasets
- Pagination
- Troubleshoot errors
- Hiring Lab API FAQs
Hiring Lab API
Access Indeed Hiring Lab labor market data for analysis and research.
By using this API and its documentation and building an integration, you agree to the Indeed's terms of service.
Integrate with the Hiring Lab API
To integrate with the Hiring Lab API, you need an API key for authentication.
Get an API key
Indeed provides API keys to partners and researchers who need access to Hiring Lab data.
To request an API key:
- Email hiring-lab-api@indeed.com with your use case and organization details.
- Indeed reviews your request and provisions an API key.
- You receive the API key by email.
Store your API key securely. Do not embed it in client-side code or commit it to version control.
Authenticate your requests
Include your API key in the Indeed-API-Key header on every GraphQL request to the Hiring Lab API:
curl -X POST 'https://apis.indeed.com/graphql' \ -H 'Content-Type: application/json' \ -H 'Indeed-API-Key: YOUR_API_KEY' \ --data-raw '{ "query": "query { findHiringLabPostingsPublic(first: 10, input: { filter: { country: [\"US\"] } }) { edges { node { ... on HiringLabNationalPosting { date indexSa } } } } }" }'Replace YOUR_API_KEY with your actual API key.
Add a Referer header
Include a Referer header in your requests to prevent blocking by security filters. This header identifies the domain making the API call:
curl -X POST 'https://apis.indeed.com/graphql' \ -H 'Content-Type: application/json' \ -H 'Indeed-API-Key: YOUR_API_KEY' \ -H 'Referer: https://your-domain.com' \ --data-raw '{ "query": "query { findHiringLabPostingsPublic(first: 10, input: { filter: { country: [\"US\"] } }) { edges { node { ... on HiringLabNationalPosting { date indexSa } } } } }" }'Replace https://your-domain.com with your actual domain or service identifier.
Test your integration
Test your API key with a simple query:
curl -X POST 'https://apis.indeed.com/graphql' \ -H 'Content-Type: application/json' \ -H 'Indeed-API-Key: YOUR_API_KEY' \ -H 'Referer: https://your-domain.com' \ --data-raw '{ "query": "query { findHiringLabPostingsPublic(first: 5, input: { filter: { country: [\"US\"], postingType: TOTAL } }) { edges { node { ... on HiringLabNationalPosting { id date country { countryCode countryName } postingType indexSa indexNsa } } cursor } pageInfo { hasNextPage } } }" }'A successful response returns job postings data:
{ "data": { "findHiringLabPostingsPublic": { "edges": [{ "node": { "id": "...", "date": "2024-10-01", "country": { "countryCode": "US", "countryName": "United States" }, "postingType": "TOTAL", "indexSa": 102.5, "indexNsa": 103.2 }, "cursor": "..." }], "pageInfo": { "hasNextPage": true } } }}Handle authentication errors
If your API key is missing or invalid, you receive a 401 Unauthorized error.
If your request does not include a Referer header, your request might be blocked by security filters. Include a Referer header that identifies your domain or service.
If you attempt to access APIs outside the Hiring Lab scope, you receive a FORBIDDEN error:
{ "errors": [{ "message": "The client doesn't have access to any requested field from '[API NAME]'.", "extensions": { "code": "FORBIDDEN" } }], "data": { "[value]": null }}Verify that your query uses only Hiring Lab API queries (findHiringLabPostingsPublic, findHiringLabRemotePublic, findHiringLabWagesPublic, findHiringLabAiPublic, and related metadata queries).
Hiring Lab API overview
Use the Hiring Lab API to access data published by Indeed Hiring Lab at data.indeed.com. The API provides access to comprehensive labor market data including job postings trends, wage growth, remote work patterns, and AI-related job opportunities.
Researchers, policymakers, economists, and analysts can call the Hiring Lab API to gather reliable labor market data for their work. Depending on the dataset, data is available at various granularities and frequencies.
Key features
- Comprehensive coverage: Access to multiple countries and regions
- Multiple granularities: National, regional, and sectoral data
- Real-time updates: Daily and monthly data updates
- Cursor-based pagination: Efficient data retrieval for large datasets
- Public and private data: Different access levels based on authentication
Available datasets
The Hiring Lab API provides access to these core datasets:
| Dataset | Description | Granularity | Frequency | |||
|---|---|---|---|---|---|---|
| National | Regional | Sectoral | Daily | Monthly | ||
| Job Postings | Job postings indices by seasonal adjustment | ✔ | ✔ | ✔ | ✔ | |
| Remote Work | Remote and hybrid job postings and searches | ✔ | ✔ | ✔ | ||
| Wage Growth | Year-over-year wage growth from job postings | ✔ | ✔ | ✔ | ||
| AI Jobs | AI-related job postings, including generative AI | ✔ | ✔ | |||
Get job postings data
To get job postings index data, call the findHiringLabPostingsPublic query:
query { findHiringLabPostingsPublic(first: 50, input: { filter: { country: ["US"], postingType: TOTAL } }) { edges { node { ...on HiringLabNationalPosting { id date country { countryCode countryName } postingType indexSa indexNsa } } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } }}Regional job postings data
To get regional job postings data, call the same query and filter by geography and region:
query { findHiringLabPostingsPublic(input: { filter: { country: ["US"], geography: STATES, region: ["California", "Texas"] } }) { edges { node { ...on HiringLabRegionalPosting { date country { countryCode countryName } region { regionCode regionName } geography { geography } indexSa indexNsa } } } }}Sectoral job postings data
To get job postings data by sector:
query { findHiringLabPostingsPublic(input: { filter: { country: ["US"], sector: ["Technology", "Healthcare"] } }) { edges { node { ...on HiringLabSectoralPosting { date country { countryCode countryName } sector { sectorCode sectorName } indexSa indexNsa } } } }}Get remote work data
To access remote work trends, call the findHiringLabRemotePublic query:
query { findHiringLabRemotePublic(input: { filter: { country: ["US"], metric: POSTINGS } }) { edges { node { ...on HiringLabNationalRemote { date country { countryCode countryName } metric remoteShare } } } }}The remoteShare field returns the percentage of job postings that are remote or hybrid. To filter by POSTINGS or SEARCHES, include the metric parameter.
Get wage growth data
To get wage growth information, call the findHiringLabWagesPublic query:
query { findHiringLabWagesPublic(input: { filter: { country: ["US"] } }) { edges { node { ...on HiringLabNationalWage { date country { countryCode countryName } wageGrowthYoy wageGrowth3Ma } } } }}The response includes:
wageGrowthYoy: Year-over-year change in posted wageswageGrowth3ma: 3-month lagged moving average of year-over-year change
Get AI job postings data
Use the findHiringLabAiPublic query to access AI-related job trends:
query { findHiringLabAiPublic(input: { filter: { country: ["US"] } }) { edges { node { ...on HiringLabNationalAI { date country { countryCode countryName } aiShare } } } }}The response includes aiShare, the percentage share of AI-related job postings.
List available data coverage
List countries with data coverage
query { findHiringLabCountriesPublic(input: { filter: { datasetId: "job_postings", granularity: NATIONAL } }) { results { countryCode countryName } }}List available sectors
query { findHiringLabSectorsPublic(input: { filter: { datasetId: "job_postings", country: "US" } }) { results { sectorCode sectorName } }}List available geographies
query { findHiringLabGeographiesPublic(input: { filter: { datasetId: "job_postings", country: "US" } }) { results { geography } }}List available regions
query { findHiringLabRegionsPublic(input: { filter: { datasetId: "job_postings", country: "US", geography: STATES } }) { results { regionCode regionName } }}List all datasets
query { allHiringLabDatasetsPublic { results { id name description granularity frequency } }}Pagination
The Hiring Lab API uses cursor-based pagination for efficient data retrieval. Use the first parameter to specify the number of results per page (maximum 50), and use the after parameter with a cursor value to get the next page:
query { findHiringLabPostingsPublic(first: 50, after: "cursor_value_from_previous_response", input: { filter: { country: ["US"] } }) { edges { node { #...your fields } cursor } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } }}Troubleshoot errors
To troubleshoot OAuth errors that can occur before you access GraphQL, see Troubleshoot OAuth errors.
To troubleshoot GraphQL errors, see Troubleshoot GraphQL errors.
For definitions of Hiring Lab API terms, see Hiring Lab API glossary.
Hiring Lab API FAQs
All job postings indices use February 1, 2020 as the baseline (= 100). This baseline ensures consistent comparison across countries and time periods.
Seasonally adjusted (SA) indices remove typical seasonal patterns to show underlying trends. Non-seasonally adjusted (NSA) indices show raw data including normal seasonal fluctuations like holiday hiring.
- Job postings and remote work data: Updated daily
- Wage growth data: Updated monthly
- AI job postings data: Updated daily
Coverage varies by dataset. Use the findHiringLabCountriesPublic query to see available countries for each dataset and granularity level.
To get historical data, use cursor-based pagination. Start with your desired filters and use the after parameter and cursor values from previous responses to paginate through results.
The maximum number of results per request is 50. Use pagination to get larger datasets.
The API returns data in chronological order. To filter to a desired time range, use pagination and the date field in your application logic.