> ## Documentation Index
> Fetch the complete documentation index at: https://docs.peopledatalabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Examples - Job Posting Search API

This page is a library of copy-pasteable examples for the Job Posting Search API.

Each example is designed to be easy to adapt for your own workflow. Replace `YOUR_API_KEY` with your API key, then modify the request payload as needed.

If you want a more guided first walkthrough, start with the [Quickstart](https://docs.peopledatalabs.com/docs/quickstart-job-posting-api).

<Cards>
  <Card title="" href="" icon="">
    ## 🔍 Browse Examples

    <Accordion title="Click to see the full list of examples on this page" icon="">
      ### Exact ID Lookup

      * [Search by Exact Job Posting ID](#search-by-exact-job-posting-id)

      ### Company Filters

      * [Basic Search: Company + Title](#basic-search-company--title)
      * [Search by Company ID](#search-by-company-id)
      * [Search by Company Name](#search-by-company-name)
      * [Search by LinkedIn Profile](#search-by-company-linkedin-profile)

      ### Title & Role Filters

      * [Search by Title Taxonomy](#search-by-title-taxonomy)
      * [Search by Multiple Title Taxonomy Values](#search-by-multiple-title-taxonomy-values)

      ### Location Filters

      * [Country-level location](#country-level-location)
      * [City-level location](#city-level-location)
      * [Region-level location](#region-level-location)
      * [Continent-level location](#Continent-level-location)

      ### Date & Activity Filters

      * [Search by Exact Date](#search-by-exact-date)
      * [Search by Last Verified Date](#search-by-last-verified-date)
      * [Recently Deactivated Jobs](#recently-deactivated-jobs)
      * [Active Jobs Only](#active-jobs-only)

      ### Compensation Filters

      * [Filter by Salary Range + Currency + Period](#filter-by-salary-range--currency--period)
      * [Filter by Remote Work Policy](#filter-by-remote-work-policy)
      * [Combined Multi-Filter Search](#combined-multi-filter-search)

      ### Text & Content Filters

      * [Search by Description Text](#search-by-description-text)
      * [Search by Inferred Skills](#search-by-inferred-skills)

      ### Bulk Retrieval

      * [Paginate with `scroll_token`](#paginate-with-scroll_token)
      * [Save Results to a JSON File](#save-results-to-a-json-file)

      ### Elasticsearch Query Examples

      * [OR Logic: Data Engineer or Machine Learning Engineer](#or-logic-data-engineer-or-machine-learning-engineer)
      * [One of Several Titles Plus a Seniority Constraint](#must--should-one-of-several-titles-plus-a-seniority-constraint)
      * [Date Range Query](#date-range-query)
      * [Only Jobs with Salary Data](#only-jobs-with-salary-data)
      * [Exclude Internship Roles](#exclude-internship-roles)
      * [Search Across Multiple Companies](#search-across-multiple-companies)
      * [Combined Query: Company List + Date Range + Title Match](#combined-query-company-list--date-range--title-match)
    </Accordion>
  </Card>
</Cards>

<br />

<Callout icon="❗️" theme="error">
  **Heads Up! Credit Usage**

  Job Posting Search API calls cost 1 credit for **each** job posting record returned.

  If you are making a search that could have a large number of results, make sure to use the `size` parameter to control the maximum number of records returned per request and cap your credit usage.
</Callout>

<Callout icon="👍" theme="okay">
  **Found a bug? Is there an example you'd like to see that's not listed here?**

  Head over to the public roadmap and submit a [bug ticket](https://peopledatalabs.canny.io/bugs) or a [feature request](https://peopledatalabs.canny.io/feature-requests) and receive automatic notifications as your bug is resolved or your request is implemented.
</Callout>

<br />

## Field Filter Examples

Use [Field Filters](https://docs.peopledatalabs.com/docs/reference-job-posting-api#field-filters) when the request can be expressed using supported fields. Multiple Field Filters are combined with `AND` logic.

<Callout icon="📘" theme="info">
  **Choosing Between Field Filters and `query`**

  Use [Field Filters](https://docs.peopledatalabs.com/docs/reference-job-posting-api#field-filters) for standard filtering by company, title, location, salary, dates, and activity status.

  Use [`query`](https://docs.peopledatalabs.com/docs/reference-job-posting-api#elasticsearch-query) when you need logic that Field Filters do not support well, such as `OR`, `must_not`, `exists`, or searching across lists of values.
</Callout>

### Exact ID lookup

***

<br />

#### Search by Exact Job Posting ID

Use this when you already know the specific PDL job posting ID you want to retrieve.

> *Give me the job posting with this exact PDL job posting ID.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "id": "yjwkKHukr18",
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

### Company filters

***

<br />

#### Basic Search: Company + Title

Use this when you want a simple company + job title search using built-in field filters.

> *Show me open job postings at OpenAI with "engineer" in the title.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "company_website": "openai.com",
    "title": "engineer",
		"is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

<Callout icon="📘" theme="info">
  **Company Filter Tips**

  [`company_website`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#company_website) is the most commonly used identifier in practice for specifying a company.

  [`company_name`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#company_name) is cleaner-backed and convenient when you only know the company by name.

  [`company_id`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#company_id) is the most precise company filter when you already have the PDL company ID.

  For additional details see our [FAQs](https://docs.peopledatalabs.com/docs/faqs-job-posting-api): [What is the most precise way to search for a company?](https://docs.peopledatalabs.com/docs/faqs-job-posting-api#what-is-the-most-precise-way-to-search-for-a-company)
</Callout>

***

<br />

#### Search by Company ID

Use this when you know the PDL `company_id` and want the most precise company filter. Typically a PDL `company_id` will come from using our [Company Search API](https://docs.peopledatalabs.com/docs/company-search-api) or [Company Enrichment API](https://docs.peopledatalabs.com/docs/company-enrichment-api).

> *Show me open engineering job postings for this exact PDL company.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "company_id": "30x8wUj6MNfspLBBgNqOawgOLDP9", # OpenAI's PDL ID
    "title_role": "engineering",
		"is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Search by Company Name

Use this when you don't have a unique identifier for a company and want cleaner-backed fuzzy matching on `company_name`.

> *Show me open engineering job postings for Open AI.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "company_name": "Open AI",
    "title_role": "engineering",
		"is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Search by Company LinkedIn Profile

Use this when you want to search job postings for a company using its LinkedIn company URL.

> *Show me open job postings for OpenAI.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "company_profile": "linkedin.com/company/openai",
    "size": 10,
		"is_active": True,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Search by Title Taxonomy

Use PDL's normalized title fields when you want structured title filters instead of free-text title matching.

> *Show me open senior data engineering jobs in the research and development title class.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_sub_role": "data_engineering",
    "title_levels": "senior",
    "size": 10,
		"is_active": True,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

This example combines the`title_sub_role`, and `title_levels`.

> *Show me open vp-level finance jobs class.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "finance",
    "title_levels": "vp",
		"is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

This example combines the`title_role`, and `title_levels`.

***

<br />

#### Search by Multiple Title Taxonomy Values

Use this when you want to provide multiple comma-separated values for canonical taxonomy fields like [`title_class`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#title_class), [`title_role`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#title_role), [`title_sub_role`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#title_sub_role), and [`title_levels`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#title_levels).

> *Show me open jobs that are senior OR manager roles in data engineering OR data science*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "engineering",
    "title_sub_role": "data_engineering,data_science",
    "title_levels": "senior,manager",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

### Location filters

The [`location`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#location) input is flexible and can match countries, continents, regions, cities, and more.

<Callout icon="📘" theme="info">
  **Job Posts with Multiple Locations**

  Just a reminder that PDL job posting records can contain multiple locations. As a result, using the `location` filter will return job posts where at least one of the posted locations matches the provided input.
</Callout>

***

<br />

#### Country-level location

> *Show me open sales jobs in Germany.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "sales",
    "location": "germany",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### City-level location

> *Show me open engineering jobs in Seattle.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "engineering",
    "location": "seattle, washington",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Region-level location

> *Show me open engineering jobs in Ontario, Canada.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "engineering",
    "location": "ontario, canada",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Continent-level location

> *Show me open marketing jobs in Europe.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "marketing",
    "location": "europe",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

### Date and activity filters

<Callout icon="📘" theme="info">
  **Date Filter Cheat Sheet**

  * Use [`first_seen_min`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#first_seen_min), [`deactivated_date_min`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#deactivated_date_min), or [`last_verified_min`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#last_verified_min) for inclusive lower bounds.
  * Use [`is_active`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#is_active) to filter to active jobs
  * Use the corresponding `*_max` fields for inclusive upper bounds.
  * To match a single day exactly, set the `*_min` and `*_max` fields to the same `YYYY-MM-DD` date.
</Callout>

***

<br />

#### Search by Exact Date

Use parameterized date fields when you want to match a date range.

> *Show me all job postings posted between January 1, 2026 and January 15, 2026.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "first_seen_min": "2026-01-01",
    "first_seen_max": "2026-01-15",
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Search by Last Verified Date

Use this when you want job postings that were verified recently by PDL.

> *Show me open job postings that PDL verified within the last two days.*

```python
import requests
from datetime import date, timedelta

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

_two_days_ago = str(date.today()-timedelta(days=2))

payload = {
    "last_verified_min": _two_days_ago,
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Recently Deactivated Jobs

Use this when you want historical job postings that were deactivated within a specific date range.

> *Show me jobs that were deactivated during March 2026.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "deactivated_date_min": "2026-03-01",
    "deactivated_date_max": "2026-03-31",
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Active Jobs Only

Use the built-in `is_active` field filter when you want only active job postings. If `is_active` is not included, it is defaulted to `False`

> *Show me only true job postings for engineers.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "engineering",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

### Compensation filters

***

<br />

#### Filter by Salary Range + Currency + Period

Use this when you want compensation filters with explicit salary units.

> *Show me engineering jobs with annual salaries between $150,000 and $300,000 USD.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "engineering",
    "salary_range_min": 150000,
    "salary_range_max": 300000,
    "salary_currency": "usd",
    "salary_period": "annual",
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Filter by Remote Work Policy

Use this when you want jobs with a specific remote work policy value.

> *Show me active remote engineering jobs.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "title_role": "engineering",
    "remote_work_policy": "Remote",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Combined Multi-Filter Search

Use this when you want to combine multiple field filters with built-in `AND` behavior.

> *Show me active remote jobs in the United States with annual salaries of at least $150,000 USD.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "location": "united states",
    "remote_work_policy": "Remote",
    "salary_range_min": 150000,
    "salary_currency": "usd",
    "salary_period": "annual",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

### Text and content filters

<Callout icon="📘" theme="info">
  **Text Matching Behavior**

  * [`title`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#title) uses cleaned `match_phrase` behavior.
  * [`description`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#description) uses `match_phrase` behavior on the cleaned text description.
  * [`inferred_skills`](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#inferred_skills) uses `match`, which is broader than `match_phrase`.
</Callout>

<br />

#### Search by Description Text

Use this when you want to find jobs whose descriptions contain a specific phrase.

> *Show me active job postings whose descriptions mention "unlimited PTO".*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "description": "unlimited PTO",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Search by Inferred Skills

Use this when you want to search the skills extracted from the job posting description.

> *Show me active job postings that mention or imply requiring JavaScript skills.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "inferred_skills": "javascript",
    "is_active": True,
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

## Bulk Retrieval Examples

<br />

### Paginate with `scroll_token`

Use this when a query matches more records than you want to retrieve in a single response.

> *Give me the 10 results for the same search over two pages.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

base_payload = {
    "location": "united states",
    "title_role": "engineering",
    "size": 5 # Sets the number of records returned per request (max: 100)
}

first_response = requests.post(API_ENDPOINT, json={**base_payload, "api_key": API_KEY})
first_response.raise_for_status()
first_page = first_response.json()

print(f"First page returned {len(first_page['data'])} records")
print(f"Total matches: {first_page['total']}")

next_payload = {
    **base_payload,
    "scroll_token": first_page["scroll_token"]
}

second_response = requests.post(API_ENDPOINT, json={**next_payload, "api_key": API_KEY})
second_response.raise_for_status()
second_page = second_response.json()

print(f"Second page returned {len(second_page['data'])} records")
```

<br />

### Save Results to a JSON File

> *Run this search and save the full API response to a local JSON file.*

```python
import json
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "company_name": "openai",
    "title_role": "engineering",
    "size": 10
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()

with open("job_posting_results.json", "w") as f:
    json.dump(response.json(), f, indent=2)

print("Saved response to job_posting_results.json")
```

***

<br />

## Elasticsearch Query Examples

Use the `query` field when you need search logic that [Field Filters](https://docs.peopledatalabs.com/docs/reference-job-posting-api#field-filters) do not support, such as `OR` conditions, `exists` queries, or multi-company searches.

<Callout icon="📘" theme="info">
  **Choosing Between Field Filters and `query`**

  * Start with [Field Filters](https://docs.peopledatalabs.com/docs/reference-job-posting-api#field-filters) when you want simple filtering by documented input parameters.
  * Use [`query`](https://docs.peopledatalabs.com/docs/reference-job-posting-api#elasticsearch-query) when you need `OR`, `must_not`, `exists`, or other custom Elasticsearch logic.
  * If you provide both Field Filters and `query`, the `query` takes precedence and the Field Filters are ignored.
</Callout>

<br />

### OR logic

***

<br />

#### `OR` Logic: Data Engineer or Machine Learning Engineer

> *Show me jobs for either data engineers or machine learning engineers.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "query": {
        "bool": {
            "should": [
                {"match_phrase": {"title": "data engineer"}},
                {"match_phrase": {"title": "machine learning engineer"}}
            ],
            "minimum_should_match": 1
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### `must` + `should`: One of Several Titles Plus a Seniority Constraint

Use this when you want to require one condition and allow multiple title alternatives.

> *Show me senior jobs for either data engineers or analytics engineers.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "query": {
        "bool": {
            "must": [
                {"term": {"title_levels": "senior"}}
            ],
            "should": [
                {"match_phrase": {"title": "data engineer"}},
                {"match_phrase": {"title": "analytics engineer"}}
            ],
            "minimum_should_match": 1
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

<br />

### Range logic

***

<br />

#### Date Range Query

Use this when you want a custom Elasticsearch date range query, or when you need date logic beyond the built-in field filters.

> *Show me jobs first seen during January 2026.*

<Callout icon="📘" theme="info">
  **Dates in Elasticsearch**

  In Elasticsearch date queries, you can use either `YYYY-MM-DD` strings or integer timestamps in milliseconds. The example below uses `YYYY-MM-DD` strings for readability.
</Callout>

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

# Pick the exact date range you want to search.
start_date = "2026-01-01"
end_date = "2026-02-01"

payload = {
    "query": {
        "bool": {
            "must": [
                {
                    "range": {
                        "first_seen": {
                            "gte": start_date,
                            "lt": end_date
                        }
                    }
                }
            ]
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

This example finds job postings first seen on or after `2026-01-01` and before `2026-02-01`.

<br />

### Existence and exclusion logic

***

<br />

#### Only Jobs with Salary Data

Use this when you want job postings where salary information is present.

> *Show me only job postings that include salary data.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "query": {
        "bool": {
            "must": [
                {"exists": {"field": "salary_min"}}
            ]
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Exclude Internship Roles

Use this when you want to remove a class of jobs from the results with `must_not`.

> *Show me engineering jobs, but leave out internship roles.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "query": {
        "bool": {
            "must": [
                {"term": {"title_role": "engineering"}}
            ],
            "must_not": [
                {"match_phrase": {"title": "intern"}}
            ]
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

<br />

### Combined advanced queries

***

<br />

#### Search Across Multiple Companies

Use a `terms` query when you want to search across a list of company IDs.

> *Show me job postings across this list of companies.*

<Callout icon="📘" theme="info">
  **Query Array Limit**

  Any array in an Elasticsearch `query` (such as a `terms` array) has a hard limit of `100` elements. If your request goes over this limit, it will fail.

  See [`query` limitations](https://docs.peopledatalabs.com/docs/input-parameters-job-posting-api#query) for the full details.
</Callout>

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "query": {
        "terms": {
            "company_id": [
                "30x8wUj6MNfspLBBgNqOawgOLDP9",
                "LGrXE14x4Kvzj2cbaeRUngOCTuJA"
            ]
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

#### Combined Query: Company List + Date Range + Title Match

Use this when you want to combine multiple company IDs, title matching, and a `first_seen` cutoff date in one [Elasticsearch query](https://docs.peopledatalabs.com/docs/reference-job-posting-api#elasticsearch-query).

> *Show me engineer jobs at these companies that were first seen on or after January 1, 2026.*

```python
import requests

API_KEY = "YOUR_API_KEY"
API_ENDPOINT = "https://api.peopledatalabs.com/v5/job_posting/search"

payload = {
    "query": {
        "bool": {
            "must": [
                {
                    "terms": {
                        "company_id": [
                            "30x8wUj6MNfspLBBgNqOawgOLDP9",
                            "LGrXE14x4Kvzj2cbaeRUngOCTuJA"
                        ]
                    }
                },
                {
                    "match": {
                        "title": "engineer"
                    }
                },
                {
                    "range": {
                        "first_seen": {
                            "gte": "2026-01-01"
                        }
                    }
                }
            ]
        }
    },
    "size": 10,
    "pretty": True
}

response = requests.post(API_ENDPOINT, json={**payload, "api_key": API_KEY})
response.raise_for_status()
print(response.text)
```

***

<br />

## Choosing Between Field Filters and `query`

<Callout icon="📘" theme="info">
  **Quick Decision Guide**

  * Start with [Field Filters](https://docs.peopledatalabs.com/docs/reference-job-posting-api#field-filters) when you want simple filtering by documented input parameters.
  * Use [`query`](https://docs.peopledatalabs.com/docs/reference-job-posting-api#elasticsearch-query) when you need `OR`, `must_not`, `exists`, or other custom Elasticsearch logic.
  * If you provide both Field Filters and `query`, the `query` takes precedence and the Field Filters are ignored.
</Callout>