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.
Added postedWithinDays filter (0 = any) and postedDaysAgo output field on every job row (days between postedAt date and scrapedAt date). Filter is applied in jobs and monitor modes; empty filter returns all rows.
Removed rows in monitor mode now carry closedOn (ISO date = run date) alongside changeType: removed, so filled/closed roles report time-to-fill as closedOn minus postedAt; diff takes the run timestamp (scraped_at) and stamps it, and the Output table, monitor recipe and dataset schema document it.
New seniority field and seniority filter (Intern, Junior, Mid, Senior, Lead/Principal): Lever's categories level when the company sets it, otherwise read from the title; no signal is Mid. Filter keeps only the asked levels in jobs and monitor modes, monitor state is keyed per filter set, and a level change counts as changed.
Monitor runs with nothing new, changed or removed end successfully (status ok): scheduled monitors no longer fail on quiet days.
Monitor state lives in a store named after the Actor (lever-jobs-monitor-state), opened only in monitor mode.
0.4 (2026-11-02)
0.4 (2026-11-02): large boards (e.g. shieldai, ~10 MB) could exceed the 30 s client timeout and fail the run; raised the per-request timeout to 120 s and reduced retries to 2, and captured the shieldai board as a fixture.
0.3 (2026-11-02)
0.3 (2026-11-02): Lever now ships salaryDescription/salaryDescriptionPlain (and level in categories); the parser folds the salary description HTML into the merged description (converting empty *Plain fields) and lowercases company slugs, so no job loses its description or pay context.
0.2 (2026-11-01)
Lever sometimes ships empty *Plain fields while the HTML fields (descriptionBody, additional, opening, description) still carry the posting; the parser now converts that HTML so no job loses its description (or its salary parsed from it).
0.1
First release: reads Lever's public postings API (api.lever.co/v0/postings/<company>?mode=json, with automatic fallback to api.eu.lever.co), one request per company, no proxy or browser.
Salary as numbers from Lever's structured salaryRange, or from a range written in the posting text; ISO currency and period; salarySource says which.
Full description merged from Lever's parts (opening, body, list sections with headings, closing) as one plain text, plus HTML.
Flat rows: team, department, location, all locations, country, workplace type, commitment and a standard employment type, posting date, posting and apply links.
Modes: jobs and monitor (new/changed/removed since the last run; a changed pay range counts as changed). Never silent on 404 or empty companies. Pay per job; monitor charges only new and changed jobs.
0.5 (2026-11-03): updated to current Lever API responses and fixtures for all battery companies
0.6 (2026-11-03): refreshed fixtures to current Lever API responses and added capture-fixture parser tests.