# Lever Jobs Scraper with Salaries (`redomic/lever-jobs-monitor`) Actor

Lever jobs scraper for any company's careers page (Palantir, Spotify, Zoox, Shield AI and thousands more): flat rows with title, team, location, workplace, commitment, apply link, salary as numbers and the full description merged. Monitor mode returns only new, changed and removed jobs.

- **URL**: https://apify.com/redomic/lever-jobs-monitor.md
- **Developed by:** [Redomic](https://apify.com/redomic) (community)
- **Categories:** Jobs, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Lever Jobs Scraper with Salaries

![Lever Jobs Scraper with Salaries](https://api.apify.com/v2/key-value-stores/gWkRolOrSe1OMioQD/records/lever-jobs-monitor-hero)

For recruiters, sales teams and analysts who track who is hiring: give it a company on Lever (the name after `jobs.lever.co/`, for example `palantir`) and get every open job as a flat row: title, team, department, location, workplace type, commitment, posting date, apply link, **salary as numbers** when the company publishes it, and the full description with every section merged into one text.

Real rows from 31 Oct 2026:

| company | title | team | location | workplaceType | salaryMin | salaryMax | salaryCurrency | salaryPeriod | salarySource |
|---|---|---|---|---|---|---|---|---|---|
| shieldai | Aerodynamics & Performance Engineer (R5732) | V-BAT Engineering | Dallas, Texas | Onsite | 115,000 | 175,000 | USD | year | leverSalaryRange |
| shieldai | Aerostructures Design Engineer II (R5156) | X-BAT Engineering - Aerostructures | Seattle, Washington | Onsite | 108,000 | 160,000 | USD | year | leverSalaryRange |
| palantir | Administrative Business Partner - ShipOS | Administrative | Washington, D.C. | Hybrid | 60,000 | 97,000 | USD | year | description |
| spotify | Account Executive - Commercial, Spotify Technology | Platform | New York, NY | Hybrid | 87,069 | 124,385 | USD | year | description |

### What it does

- Salary as numbers, from two sources: Lever's structured `salaryRange` when the company sets it (counts from runs on 31 Oct 2026 with `{"companies": ["<company>"], "maxItems": 1000}`: Shield AI 528 of 655 jobs; Zoox 211 of 227), otherwise a pay range written in the posting ("The salary range for this position is estimated to be $5,900 - $10,500/month": Palantir 197 of 299). Min, max, ISO currency and period (`year`, `month`, `hour`...) in their own columns; `salarySource` says which. No range published: `null`, never an estimate.
- The whole description, merged: Lever splits a posting into an opening, a body, list sections ("What you'll do", "Requirements") and closing text. With `includeDescription` you get them all in page order as one plain-text field, plus the HTML.
- Seniority on every row (`Intern`, `Junior`, `Mid`, `Senior`, `Lead/Principal`): Lever's own `level` when the company sets it (Zoox sets `Junior` on 2 jobs in the 3 Nov capture), otherwise read from the title (`Senior Backend Software Engineer` is `Senior`, `Software Engineer, Internship` is `Intern`, `Senior / Staff Vehicle Program Manager` is `Lead/Principal`, no signal is `Mid`). Filter with `seniority` to get only the level you are hiring for.
- Monitor mode: Schedule it and get only new, changed (title, team, location, workplace, commitment or pay) and removed jobs since the last run, tagged in `changeType`. Unchanged jobs are free.
- US and EU accounts: Companies hosted on `jobs.eu.lever.co` are found automatically.
- Dead inputs are reported: A company Lever does not know (404 on both APIs) or with no open jobs gets a status row with the reason; a run with no data ends failed so a schedule alerts you. Example status row for a misspelled name:

  ```json
  {"_status": "failed", "company": "palantir-typo", "mode": "jobs", "rows": 0, "reason": "company not found on Lever (404 on the US and EU APIs): check the name after jobs.lever.co/"}
  ```
- One request per company: Lever's public postings API returns every posting with its description in one call: no proxy, no browser, runs in seconds.

### Input

| Field | Type | Default | Meaning |
|---|---|---|---|
| `companies` | array of strings | `["palantir"]` | Lever company names (after `jobs.lever.co/`). Full URLs are accepted |
| `mode` | enum | `jobs` | `jobs` lists every open job; `monitor` returns only new, changed and removed jobs since the last run |
| `search` | string | `""` | Keep jobs whose title, department, team, location, commitment, workplace type or description contains this text |
| `seniority` | array of strings | `[]` | Keep only these levels: `Intern`, `Junior`, `Mid`, `Senior`, `Lead/Principal`. Empty = every level |
| `includeDescription` | boolean | `false` | Add the merged plain-text description and the HTML. Same single request |
| `postedWithinDays` | integer | `0` | Only jobs posted in the last N days relative to the scrape time. 0 = any date |
| `maxItems` | integer | `100` | Max job rows per company, 1 to 1000 (3 companies x 100 = at most 300 rows) |

```json
{ "companies": ["palantir", "spotify"], "mode": "jobs", "search": "engineer", "maxItems": 50 }
```

### Output

One row per job, then one status row per company, then a summary row.

| Field | Example | Meaning |
|---|---|---|
| `id` | `baaae144-6477-4f3b-975b-ec1d04d0a7e4` | Lever posting id, stable across runs |
| `company` | `shieldai` | The company you asked for |
| `title` | `Aerostructures Design Engineer II (R5156)` | Job title |
| `team`, `department` | `X-BAT Engineering - Aerostructures`, `X-BAT Division` | As the company files the job |
| `location` | `Seattle, Washington` | Primary location |
| `allLocations` | `["Seattle, Washington"]` | Every location the posting lists |
| `country` | `US` | Country code, when Lever has it |
| `workplaceType` | `Onsite` | `Onsite`, `Hybrid` or `Remote` (null when unspecified) |
| `commitment` | `Full Time Employee` | The company's own wording |
| `employmentType` | `Full-time` | Standardised: `Full-time`, `Part-time`, `Contract`, `Internship`, `Temporary`; null when the wording does not say |
| `seniority` | `Senior` | `Intern`, `Junior`, `Mid`, `Senior` or `Lead/Principal`. From Lever's `level` when set, otherwise the title; no signal is `Mid` |
| `postedAt` | `2026-06-10T16:36:42Z` | When the posting was created, UTC |
| `postedDaysAgo` | `0` | Days between `postedAt` (date) and `scrapedAt` (date). Set on every job row. |
| `url` | `https://jobs.lever.co/shieldai/baaae144-6477-4f3b-975b-ec1d04d0a7e4` | Posting page |
| `applyUrl` | `https://jobs.lever.co/shieldai/baaae144-6477-4f3b-975b-ec1d04d0a7e4/apply` | Application form |
| `salaryMin`, `salaryMax` | `108000`, `160000` | Published pay range |
| `salaryCurrency`, `salaryPeriod` | `USD`, `year` | ISO 4217 code; `year`, `month`, `week`, `day` or `hour` |
| `salaryText` | `USD 108,000 - 160,000 per year` | The range as one string |
| `salarySource` | `leverSalaryRange` | `leverSalaryRange`, `description` or `null` |
| `salaryRanges` | `[{"min": 108000, "max": 160000, "currency": "USD", "period": "year", "label": null}]` | The range as a list (same shape as our Greenhouse and Ashby Actors) |
| `descriptionText`, `descriptionHtml` | `Shield AI is a venture-backed defense-tech company with the mission of...` | Only with `includeDescription` |
| `changeType` | `new` | Monitor mode only |
| `closedOn` | `2026-10-31` | Removed rows only: ISO date the job was first seen gone (the run date); `closedOn` minus `postedAt` is days open, so filled/closed roles report time-to-fill |
| `scrapedAt` | `2026-10-31T00:00:00Z` | When the row was fetched |

Status rows carry `_status` (`ok`, `empty`, `failed`), `company`, `mode`, `rows`, `reason` and `total` (open jobs). The last row has `_status: "summary"` with run totals and, in monitor mode, `new`, `changed`, `removed`, `firstRun`.

#### Seniority, real counts

With `{"companies": ["palantir"], "seniority": ["Senior"], "maxItems": 1000}` on the 3 Nov 2026 capture (302 open jobs) the 25 `Senior` rows are `Senior Backend Software Engineer - Application Development` and `Senior Front End Software Engineer - Application Development` (25 of 302; the same capture has 46 `Intern`, 38 `Junior` and 193 `Mid`). Zoox (226 open jobs) returns 65 `Lead/Principal` rows, including `Lead AI Engineer – Enterprise, Data & AI` and `Senior / Staff Vehicle Program Manager`.

### Pricing

`result`: $0.002 per job row delivered, nothing else: no start fee. 1,000 jobs ≈ $2.00. In monitor mode only new and changed jobs are charged; unchanged and removed jobs are free.

### Monitor recipe

1. Save a task with `{"companies": ["palantir", "spotify", "zoox"], "mode": "monitor"}`.
2. Schedule it daily in Apify Console.
3. Add a "run succeeded" webhook that sends the rows to Slack, Make or n8n, or export the dataset to Google Sheets.
4. `changeType: new` is a fresh opening (a hiring signal), `changed` a retitled or re-priced role, `removed` a filled or closed one. Every `removed` row carries `closedOn` (the run date), so `closedOn` minus `postedAt` gives you days open and time-to-fill per role without tracking state yourself.

Reliability (3 Nov 2026 capture): the nine boards in the test fixtures (1,451 jobs across palantir, shieldai, spotify, zoox, outreach, matchgroup, jumpcloud, ro and brilliant) all parse to real rows — 0 failed boards. An unchanged monitor run ends `ok` with no rows, so a quiet day is not a failed run; a typo or dead board still gets a `failed` status row instead of silence.

### FAQ

- **How do I find a company name?** Open the careers page; Lever postings live at `jobs.lever.co/<name>`. Paste the URL if you like.
- **Can I search all Lever companies at once?** No. Lever's public API is per company; list as many as you need.
- **Why is salary null for some jobs?** The company did not publish a range on Lever or in the posting text (common outside the US).

### What this does not do

It reads only Lever's public postings API: no logins, no applicant data, no personal contact details, no email extraction. It does not estimate missing salaries.

Sibling Actors: **Greenhouse Jobs Scraper with Salaries** and **Ashby Jobs Scraper with Salaries** (same row shape for the other two big startup ATSs), and **Google Jobs API Scraper**.

### Use it from AI agents (MCP) and Python

**AI agents.** Add this Actor as a tool in Claude, Cursor, VS Code or any MCP client through the Apify MCP server. The agent reads the input schema, so a plain request is enough.

```json
{
  "mcpServers": {
    "lever-jobs-monitor": {
      "url": "https://mcp.apify.com?tools=redomic/lever-jobs-monitor",
      "headers": {
        "Authorization": "Bearer <YOUR_APIFY_TOKEN>"
      }
    }
  }
}
```

**Python.** `pip install apify-client`, then:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("redomic/lever-jobs-monitor").call(run_input={"companies": ["palantir"], "mode": "jobs", "maxItems": 20})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### More from us

- [Ashby Jobs Scraper with Salaries](https://apify.com/redomic/ashby-jobs-monitor): Ashby jobs scraper for any startup careers board (OpenAI, Ramp, Notion and thousands more), with salary ranges as numbers: min, max, currency, period, plus equity and bonus flags
- [ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API](https://apify.com/redomic/ats-jobs-search): Search 328,000+ open jobs from 11,000+ companies on Greenhouse, Lever and Ashby in one run
- [Google Jobs Scraper - Job Postings API](https://apify.com/redomic/google-jobs): Google Jobs and job postings scraper: get job title, company, location, posted date, salary, full description and every apply link for any search
- [Google Trends API: Trending Now & Interest Over Time](https://apify.com/redomic/google-trends): Trending-now searches and new-trends alerts/monitoring per country with the news behind them, plus interest over time, interest by region, and related and rising queries for any keyword
- [Greenhouse Jobs Monitor & Scraper](https://apify.com/redomic/greenhouse-jobs-monitor): Monitor Greenhouse jobs from any company careers board (Airbnb, Stripe, Discord and thousands more)

# Changelog

This Actor's version history is a separate document: https://apify.com/redomic/lever-jobs-monitor/changelog.md

# Actor input Schema

## `companies` (type: `array`):

Lever company names: the part after jobs.lever.co/, for example palantir, spotify, zoox. You can also paste full careers or posting URLs; only the name is kept. EU-hosted companies (jobs.eu.lever.co) are found automatically.

## `mode` (type: `string`):

jobs lists every open job; monitor reports only new, changed (including a changed pay range) and removed jobs since the last run of the same company and keyword.

## `search` (type: `string`):

Keep only jobs whose title, department, team, location, commitment, workplace type or description contains this text. Case-insensitive. Leave empty for every open job.

## `seniority` (type: `array`):

Keep only jobs at these seniority levels. Empty = every level. Seniority is Lever's categories.level when set, otherwise read from the title (no signal = Mid).

## `includeDescription` (type: `boolean`):

Add the full description (opening, body, every section and closing, merged as plain text, plus the HTML) to each row. Off by default to keep rows small; the keyword filter searches descriptions either way. No extra request.

## `maxItems` (type: `integer`):

Upper limit on job rows per company (and so on what you pay): 3 companies x 100 = at most 300 rows. Default 100, maximum 1000.

## `postedWithinDays` (type: `integer`):

Only jobs posted in the last N days relative to the scrape time. 0 = any date.

## Actor input object example

```json
{
  "companies": [
    "palantir"
  ],
  "mode": "jobs",
  "search": "",
  "seniority": [],
  "includeDescription": false,
  "maxItems": 20,
  "postedWithinDays": 0
}
```

# Actor output Schema

## `results` (type: `string`):

All result rows from the default dataset.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        "palantir"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("redomic/lever-jobs-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companies": ["palantir"],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("redomic/lever-jobs-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "palantir"
  ],
  "maxItems": 20
}' |
apify call redomic/lever-jobs-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,redomic/lever-jobs-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/dlcQNkSlnHOXZyHyu/builds/CG5UPpKDK2ttMFECd/openapi.json
