Lever Jobs API Scraper - Live Postings Data avatar

Lever Jobs API Scraper - Live Postings Data

Pricing

from $2.00 / 1,000 job postings

Go to Apify Store
Lever Jobs API Scraper - Live Postings Data

Lever Jobs API Scraper - Live Postings Data

Live job postings from the Lever public postings API (api.lever.co v0), global and EU hosts. Site names or careers URLs in, one normalized schema out with structured salary and a remote flag. No scraping, no proxies, no API keys.

Pricing

from $2.00 / 1,000 job postings

Rating

0.0

(0)

Developer

moonie

moonie

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Lever Jobs API Scraper

Unofficial. Not affiliated with, endorsed by or sponsored by Lever, Inc. It calls Lever's own public postings API. All trademarks belong to their owners. Removal requests: TAKEDOWN.md — honoured in 48 hours. Privacy: PRIVACY.md.

Live job postings straight from the Lever public postings APIapi.lever.co/v0/postings/{site} — normalized into one flat schema with structured salary, a real remote flag, parsed locations and a stable job id. You paste Lever site names (palantir) or Lever careers URLs; you get clean job rows back. Seven filters run before anything is billed, company summaries and error rows are free, and onlyNewJobs keeps a baseline in your own key-value store so a daily monitoring run returns only what changed. No scraping, no headless browser, no proxies, no API keys.

We index nothing you buy. There is no "jobs in our database" number here, because there is no index between you and the board: every row in your run was fetched from that employer's Lever site seconds earlier, never served from a crawl of unknown age. And because you are billed only for job rows you actually receive, a 500-company daily watch with onlyNewJobs costs a couple of cents a run.

What this is not: no keyword search without a company list; and this listing reads Lever only — an entry for another ATS comes back as a free error row.

What this Lever jobs API does

  • Endpointapi.lever.co/v0/postings/{site}?mode=json, with the EU host api.eu.lever.co tried automatically when the global host has nothing
  • Site name — the slug in your careers URL: https://jobs.lever.co/palantirpalantir. Case-sensitive: palantir works, Palantir returns 404
  • Remote flag — Lever's workplaceType becomes a real remote boolean with remoteSource: "ats"
  • Salary — Lever's salaryRange becomes salaryMin, salaryMax, salaryCurrency, salaryInterval with salarySource: "ats" where the employer filled it in
  • Descriptions — the full ad body, inline in the same response, on by default at no extra cost

That endpoint is Lever's own public postings API: the same one a company's careers page calls to render itself, published by Lever and requiring no credential. That is a different product from career-page scraping — no headless browser, no residential proxy, no bot walls, nothing that breaks when a marketing site is restyled.

Rows you are not charged for: company summaries, error rows, jobs removed by your filters, companies never reached because your maxJobs cap fired, and companies that failed.

Supported endpoint and what Lever actually gives you

FieldLeverNote
Remote flagYesworkplaceTypeOne of the two providers in this family that states it outright
Structured salarySometimes — salaryRangePresent only where the employer filled it in; regex fallback otherwise
DescriptionYes, inlineLists and closing sections are joined into one body
Employment typeYescommitmentNormalized to full_time / part_time / contract / temporary / internship / other, employmentTypeSource: "ats"
Department / teamYes — categoriesdepartment and team both populated where Lever has them
Job URLYeshostedUrl, plus applyUrl where Lever exposes one
Posted dateYescreatedAtExposed as postedAt with postedAtSource
EU hostingYesEU-resident boards live on api.eu.lever.co; we try both and report which answered

How to use the Lever postings API

  1. Paste your site names. One per line: palantir, or the full URL https://jobs.lever.co/palantir. EU URLs (jobs.eu.lever.co/...) resolve too. Watch the casing — Lever site names are case-sensitive.
  2. Set your filters. Title keywords, excluded titles, location, remote-only, departments, employment types, posted-after. They all run locally on the fetched JSON, before billing.
  3. Run it, or schedule it. For monitoring, turn on onlyNewJobs and give the task its own stateKey; the first run stores the baseline and later runs return only what is new.

A minimal run — ["palantir"] with maxJobs: 50 — finishes in seconds and costs ten cents.

Coming from fantastic-jobs, jobo, bovi or webdata_labs

Saved input from another Lever Actor runs here unchanged. These input keys are accepted as aliases for companies, first non-empty wins, and an explicit companies always wins over an alias:

Their keyHere
siteNames, boardTokens, jobBoardNamescompanies
queries, companyUrls, startUrlscompanies
subdomains, companyIdentifierscompanies

What you gain: live boards instead of an index of unknown age; postedAfter and per-company filtering that run before billing, so filtered-out jobs are free; structured salary with currency and interval separated rather than a pay string; the EU host tried automatically instead of a silent 404; no contact, recruiter or candidate fields anywhere in the output; the full ad body on by default with contact redaction on by default; and a trackedSince date on every company row once onlyNewJobs is on.

What you lose, stated plainly: there is no keyword search without a company list. If "find me every Rust job anywhere" is your requirement, an aggregator fits better than this Actor. And this listing is Lever-only by design — if you need Greenhouse, Ashby, Recruitee, Rippling or Personio in the same run, use the multi-ATS Actor ats-jobs-scraper instead of running four listings.

Input

{
"companies": ["palantir", "https://jobs.lever.co/matchgroup"],
"maxJobs": 1000,
"titleKeywords": ["engineer", "data"],
"excludeTitleKeywords": ["intern"],
"locationKeywords": ["Berlin", "Germany", "Remote"],
"remoteOnly": false,
"employmentTypes": ["full_time"],
"postedAfter": "7 days",
"includeDescription": true,
"descriptionFormat": "text",
"redactContacts": true,
"outputProfile": "full",
"onlyNewJobs": false,
"stateKey": "lever-jobs-state-default"
}
FieldTypeDefaultEffect on cost
companiesarrayrequiredSite names or careers URLs. More companies, more charged rows
maxJobsinteger1000Your main cost control. Hard stop after this many charged rows; 0 = no limit
maxJobsPerCompanyinteger0Stops one enterprise board eating the whole budget
titleKeywords / excludeTitleKeywordsarray[]Filtered-out jobs are free
locationKeywordsarray[]Matches raw location text and parsed city, region, country
remoteOnlybooleanfalseKeeps only remote: true — reliable on Lever, which states it
departmentsarray[]Substring match on the Lever category
employmentTypesarray[]Lever reports a commitment on most postings
strictEmploymentTypebooleanfalseKeeps only ATS-confirmed types — usually safe here
postedAfterstringnull2026-08-01 or 7 days. Jobs with no date are kept
includeDescriptionbooleantrueBigger items, same price — the body costs nothing extra
redactContactsbooleantrueStrips contact details from description bodies
outputProfilestringfullminimal cuts token cost for AI agents
dedupestringidcontent also merges same title + company + location + requisition id
onlyNewJobsbooleanfalseReturns only ids not in your state store
stateKeystringlever-jobs-state-defaultName of the key-value store holding seen ids
maxConcurrencyinteger8Speed only; api.lever.co is capped separately at 1 rps

Output

One job row per posting (charged), plus free company_summary and error rows. The dataset schema is identical to the multi-ATS Actor's, so a pipeline can read both without a branch.

{
"recordType": "job",
"id": "lever:palantir:6e1f0c11-1c58-4f3b-9d0e-2a7c1f0a1234",
"provider": "lever",
"companySlug": "palantir",
"company": "Palantir Technologies",
"title": "Backend Engineer, Foundry",
"department": "Engineering",
"team": "Foundry",
"locationRaw": "London, UK",
"city": "London",
"country": "United Kingdom",
"countryCode": "GB",
"remote": false,
"workplaceType": "onsite",
"remoteSource": "ats",
"employmentType": "full_time",
"employmentTypeSource": "ats",
"salaryMin": null,
"salaryMax": null,
"url": "https://jobs.lever.co/palantir/6e1f0c11-1c58-4f3b-9d0e-2a7c1f0a1234",
"postedAt": "2026-08-19T00:00:00Z",
"postedAtSource": "created_at",
"descriptionRedacted": false,
"isNew": true,
"scrapedAt": "2026-08-26T03:00:12Z"
}

Two dataset views are provided: Jobs (spreadsheet-ready postings) and Company summaries. Export either as JSON, CSV, Excel or XML from the Storage tab.

What null means: we could not determine it. We never guess remote status, employment type, seniority or salary. A null field is the honest answer, and far more useful than an invented one when you are filtering thousands of rows.

Filters, deduplication and normalization

  • remote comes from Lever's workplaceType where present (remoteSource: "ats"); otherwise from the location text or the title, and null when nothing said. remoteOnly keeps only positively-confirmed remote jobs.
  • Salary comes from salaryRange first (salarySource: "ats"). Only when there is none do we run a conservative regex over the salary text (salarySource: "parsed"), with rejection gates for equity, bonuses, funding rounds, 401(k), date ranges and phone numbers. Never an LLM.
  • Employment type is normalized from Lever's commitment to full_time, part_time, contract, temporary, internship or other. strictEmploymentType keeps only ATS-confirmed ones.
  • Dedupe by id is always on. By content additionally merges rows with the same title, company, raw location and requisition id — useful for boards that list a role once per office, but it can merge genuinely separate openings. Dropped ids are listed in dedupedFrom on the surviving row.
  • Locations are parsed into city, region, country and an upper-case countryCode from a bundled table. No geocoding, no coordinates, no external service.

Privacy and contact redaction

  • The output has no contact, recruiter or candidate fields. Ever.
  • includeDescription ships on, so a default run carries the ad body. That body is the employer's own copyrighted advertisement text; publishing an ad licenses nobody to redistribute it. Set includeDescription: false if you would rather not hold ad bodies at all.
  • With redactContacts on (the default), the body is stripped of email addresses, phone numbers, LinkedIn/Xing/WhatsApp/Calendly/Telegram links and handles, and a person's name where the ad labels it as a contact (Contact:, Hiring manager:, Recruiter:, Ansprechpartner:). descriptionRedacted records that something was removed.
  • What redaction does not catch, stated plainly — we do not claim "no PII": a name in running prose with no contact label in front of it survives. Redaction is a contactability control, not anonymisation. Anyone named in an ad body gets it removed in 48 hours, unconditionally: TAKEDOWN.md · PRIVACY.md.
  • Nothing is stored outside your own Apify account and nothing is sent to the developer. The Actor opens no outbound connection to us and embeds no credential.

Pricing

$0.002 per job row — the only event that costs real money. Everything else on the Pricing tab is platform floor:

EventPriceWhat it is
job$0.002One job row delivered to your dataset. This is the price.
apify-actor-start$0.00005Apify's platform default, charged once per run.
delta-run$0.00001Instrumentation, recorded once per run when onlyNewJobs is on — one cent per thousand monitoring runs.

Free, always: company summary rows, error rows, jobs removed by your filters, companies never reached because your maxJobs cap fired, and companies that failed.

Run shapeCharged rowsCost
One site, 50 jobs (an agent query)50$0.10
Ten sites, 1,000 jobs (a backfill)1,000$2.00
500 sites, onlyNewJobs, 15 new jobs (daily monitoring)15$0.03

That is $2 per 1,000 jobs. Set maxJobs to bound any run, or ACTOR_MAX_TOTAL_CHARGE_USD to bound the spend directly — when that limit is reached the Actor stops pushing, writes budget_exhausted summaries and still finishes successfully.

Monitoring new Lever job postings (delta mode)

Turn on onlyNewJobs and give each monitoring task its own stateKey. The first run stores the baseline and returns everything; later runs return only ids that were not there before. stateRetentionDays (default 90) forgets ids that stopped appearing, so the store cannot grow forever. The state is a key-value store in your account, named by you — we never see it.

Integrations: n8n, Make, Zapier, Clay, Google Sheets, Slack

  • n8n — the Apify node, Run an Actor, then Get dataset items.
  • Make — the Apify Run an Actor module plus Watch dataset items.
  • Zapier — Apify's Run Actor action; map title, company, url, postedAt into your CRM.
  • Clay — call the Actor as an HTTP enrichment step, keyed on the Lever site name.
  • Google Sheets — export the Jobs view as CSV, or push items from n8n/Make.
  • Slack — filter on isNew in delta mode and post new rows to a channel.

For AI agents and MCP

Agent-friendly by construction: limited permissions, pay-per-event with a single paid event, no Standby mode, typed error rows instead of stack traces, and a minimal output profile returning only title, company, locationRaw, city, countryCode, remote, url, postedAt to keep token cost down.

{
"companies": ["palantir"],
"outputProfile": "minimal",
"maxJobs": 25,
"remoteOnly": true
}

Set maxJobs on every call and ACTOR_MAX_TOTAL_CHARGE_USD on the run to cap spend. Errors come back as dataset rows with recordType: "error" and a machine-readable status, so a tool call never has to parse a traceback.

Limitations you should know before you buy

  • Lever site names are case-sensitive. palantir works, Palantir returns 404. This is the single most common cause of an empty run.
  • api.lever.co is rate-limited to 1 request per second on our side, so very large company lists take longer here than on the other ATS listings.
  • Structured salary is present only where the employer filled salaryRange in; many Lever boards leave it empty and you get null rather than a guess.
  • An EU-resident board answers on api.eu.lever.co. We try the global host first and fall back automatically, so an EU-only board costs one extra request, not an error.
  • This listing reads Lever only. A Greenhouse board token or an ashbyhq.com URL is refused with a free error row naming the right Actor.
  • There is no keyword search without a company list.

ats-jobs-scraper reads all six providers (Greenhouse, Lever, Ashby, Recruitee, Rippling, Personio) in one run with the same schema and the same price. Sibling per-ATS listings exist for Greenhouse and Ashby.

FAQ

Is this legal? We call Lever's own public, unauthenticated postings API, we honour documented rate limits, we do not scrape career pages, we use no proxies and we touch no login-walled site. Copyright is a separate question and we will not pretend otherwise: the description body stays the employer's copyrighted text, and any rightholder who wants it out gets it out in 48 hours — TAKEDOWN.md.

Do I need an API key? No. The endpoint requires no credential and the Actor stores none.

How fresh is the data? Fetched live at run time. No index, no cache between you and the board.

Where do I find a site name? It is the path segment in the careers URL — https://jobs.lever.co/palantirpalantir. You can paste the whole URL instead. Copy the casing exactly.

My board returns 404. Check the casing first, then confirm the company is really on Lever. EU boards are handled automatically.

Can I get salaries for every job? No. salaryRange depends entirely on what the employer published.

How do I schedule it daily? Apify Schedules, with onlyNewJobs: true and a dedicated stateKey.

How do I export to CSV? Storage → the Jobs view → Export → CSV.

Support and issues

Open an issue on the Actor's Issues tab or in the public GitHub repository at https://github.com/moonie0201/ats-jobs. Every issue gets a reply within 14 days, usually within 48 hours. Bug reports that include the run id and the input are fixed fastest.

Removal, takedown, copyright or privacy requests jump the queue and are answered within 48 hours: TAKEDOWN.md · PRIVACY.md.

Disclaimer

This Actor is unofficial. It is not affiliated with, endorsed by, or sponsored by Lever, Inc. It uses Lever's public postings API to retrieve publicly published job advertisements. All trademarks belong to their respective owners.

Job advertisement text remains the copyright of the employer that wrote it. The structured fields this Actor produces are factual. Removal requests are honoured within 48 hours: TAKEDOWN.md.