Lever Jobs Lookup — Job Postings API by Company Slug
Pricing
from $3.00 / 1,000 successful lookups
Lever Jobs Lookup — Job Postings API by Company Slug
Look up any company's live Lever job postings by slug or careers-page URL — title, location, team, commitment, and apply link, one row per open role. Straight from Lever's own public postings API, no login or key needed. Charged once per company with at least one open role — never per job posting.
Pricing
from $3.00 / 1,000 successful lookups
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
You paste a list of companies — a bare Lever slug like spotify or a full careers URL like
https://jobs.lever.co/spotify — and you get back every open role on that company's Lever job
board: title, location, team, commitment type, posting date, and a direct apply link, one row
per posting. This hits Lever's own public postings API (api.lever.co) directly, the same JSON
feed that powers a company's public jobs.lever.co careers page — no scraping, no login, no API
key. You can also filter down to the roles you actually care about, and put the actor on a
schedule to get only the postings that are new since your last run.
Who it's for
The accountable_eel catalogue sells company intelligence columns for outbound. Each actor takes a list of domains or company identifiers and returns one flat, stably-named row per input — firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and per-domain: a few tenths of a cent for a row that was actually found, and nothing for a miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists — VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No seat licence, no monthly minimum, no credit system to decode.
For Lever specifically: if your outbound list includes companies that hire through Lever, this is the column that turns "are they hiring" into a number and a role list you can filter and re-run.
Why this one
- Direct from Lever's own API, not HTML scraping — nothing to break when a careers page gets redesigned, and no proxy or browser overhead.
- Priced per company, not per job. A company with 200 open roles costs the same as one with three; you're paying for the lookup, not the payload size.
- Real job filters, not just a keyword grep on the finished row — title include/exclude,
location, remote, and posted-date all run before the row is built, so
jobCountreflects what actually matched. - A delta mode built for a schedule.
onlyNewSinceLastRunremembers what it showed you last time in a named key-value store in your own account, so a recurring run reports new roles instead of dumping the whole board every time. - Lever's own
workplaceTypefield drives the remote flag — a structural signal most ATS platforms don't expose, backed up by a text match on location and title as a fallback.
What you get
Every row carries these fields. query, found, status, message and scrapedAt are on every
row regardless of what was found; the rest come from Lever's postings API.
| Field | Type / format | What it is |
|---|---|---|
query | text | The input you passed in, as given. |
found | boolean | true if the company has a Lever board (even with 0 matching roles), false if it has no board at all. |
status | text | OK, NOT_FOUND, or BAD_FORMAT — see the FAQ for what each means. |
message | text | Human-readable detail, populated on a miss. |
scrapedAt | date | When this row was fetched, ISO timestamp. |
company | text | The Lever slug the row is for, normalized (lowercase, URL stripped to the slug). |
jobCount | number | How many postings are in this row's result — after filters, and after delta if onlyNewSinceLastRun is on. |
totalJobCount | number | Open jobs on the board before any filtering — lets you tell "filtered out" apart from "nothing there". |
newJobs | number | Postings new since your last run. null unless onlyNewSinceLastRun is on. |
firstRun | boolean | Whether this was the baseline run of this watchlist. null unless onlyNewSinceLastRun is on. |
jobs | array | The full matched job list, nested. Present when "One row per job posting" is off; each entry has the same title/location/team/commitment/createdAt/postedAt/remote/applyUrl shape as the flat columns below. |
title | text | Job title. |
location | text | Posting location, as Lever's categories.location reports it. |
team | text | Team/department, as Lever's categories.team reports it. |
commitment | text | Employment type — e.g. Permanent, Intern, Contract — as Lever reports it. |
createdAt | date | When Lever created the posting, ISO timestamp. |
postedAt | date | Same value as createdAt — Lever only tracks one date per posting; kept as a separate field for consistency with the other ATS actors in this catalogue. |
remote | boolean | true when Lever's own workplaceType says remote, or the location/title text matches a remote pattern as a backstop. |
applyUrl | link | Direct link to apply for the posting. |
Price
$5 per 1,000 companies, plus a $0.0001 start fee. Misses (found:false) are never charged.
That's the FREE-tier rate — it drops on paid Apify plans. You're only billed for a company with at
least one open role on its Lever board; a company with no board, an unknown slug, or a slug that's
moved off Lever costs nothing. A company whose board exists but whose postings all get filtered
out (or has nothing new since your last run) still returns found: true and is still charged —
the lookup happened and answered your question, it just came back at jobCount: 0.
1,000 companies through this actor: ~$5 if every one has an active Lever board, less for whatever fraction come back as misses. The same 1,000 rows through a credit-based enrichment platform: $80–$400.
How to use
- In the Apify Console. Open the actor page and click Start — the
companiesfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~lever-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"companies":["spotify"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
Paste one company per line — a bare slug (spotify) or a full careers URL
(https://jobs.lever.co/spotify); both resolve the same way. Leave the filters empty and you get
every open posting on each board.
To narrow the results, open the 🎯 Job filters section of the Input tab:
titleKeywords/excludeTitleKeywords— keep or drop roles by title, case-insensitive, partial-word matches count.locations— keep only roles whose location mentions one of your terms.remoteOnly— keep only roles Lever (or the location/title text) marks remote.postedAfter— drop anything posted before this date.
Different filters combine with AND; values inside one filter combine with OR. jobCount always
reflects what matched, totalJobCount always shows what was on the board before filtering, so a
filtered-to-zero result is never ambiguous with a broken run.
To watch a list on a schedule instead of re-pulling the same roles every time, turn on
onlyNewSinceLastRun in the 🔁 Watch for new jobs section. The first run baselines and returns
everything that matches; every run after that returns only postings it hasn't shown you before,
with newJobs and firstRun telling you which case you're in. A quiet run still returns a row
(jobCount: 0, newJobs: 0) rather than nothing, so you can tell "nothing new" apart from "the
schedule broke."
Turn off "One row per job posting" in the Input tab to get one row per company instead, with the
full matched job list nested in jobs.
Input
{"companies": ["spotify"]}
One company per line — paste the Lever slug or the full jobs.lever.co careers URL. Accepted formats: spotify, https://jobs.lever.co/spotify.
Don't know the company's exact Lever slug? Paste their careers page URL instead — both spotify
and https://jobs.lever.co/spotify work, and the slug is pulled out automatically.
Sample output
By default you get one row per open job posting (turn off "One row per job posting" in the Input tab to get one row per company instead, with the full job list nested inside):
| query | found | status | company | jobCount | totalJobCount | newJobs | firstRun | jobs | title | location | team | commitment | createdAt | postedAt | remote | applyUrl | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| spotify | true | OK | spotify | 95 | <open jobs on the board (before filters)> | <first run of this watchlist?> | <all jobs (full list)> | Advertiser Solutions Vendor Lead - Programmatic and Direct Support | London | Advertising Sales - Emerging and Scaled Sales | Permanent | 2026-07-20T17:49:59.619Z | <remote?> | https://jobs.lever.co/spotify/890b2c0f-f46f-4a4b-bb73-3a6af6e0edd5 | 2026-08-23T06:01:20.062Z |
A real row looks like:
| query | found | status | company | title | location | applyUrl |
|---|---|---|---|---|---|---|
| spotify | true | OK | spotify | Android Engineer - Advertising | New York, NY | https://jobs.lever.co/spotify/a0fa7da3-4c3c-4fa2-97bd-7d6eb01eb9e5 |
A company slug that doesn't exist on Lever, has moved off the platform, or currently has zero open
postings comes back as a single found: false row with a status/message explaining why — and
is never charged.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~lever-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"companies":["spotify"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~lever-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"companies":["spotify"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~lever-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"companies":["{{company}}"]}, mapping the row's company into the companies array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Lever Jobs Lookup | Apify" — the agent will find and run this actor.
Tips
- Start with no filters to see the full board, then add
titleKeywordsorlocationsonce you know what you're looking for — filters apply before the row is built, so you never pay to see roles you're about to throw away in a downstream step. - Put a filtered list on a schedule with
onlyNewSinceLastRunon instead of re-running the full pull — you'll get anewJobscount each time instead of a full dump to diff yourself. - Remember that changing any filter starts a fresh watchlist — the seen-list is keyed on the
filter combination, so editing
titleKeywordsmid-schedule re-baselines rather than silently reusing the old seen-set. - Use
totalJobCountalongsidejobCountwhen you're not sure whether a zero result means "no match" or "no board" — afound: truerow withjobCount: 0means the board exists and your filters just didn't match anything on it. - If your list is mixed across ATS platforms, don't try to guess which company runs Lever —
ats-jobs-unified-lookupchecks all seven platforms per company and tells you which one hit.
vs. alternatives
| What it costs | What you get | Trade-off | |
|---|---|---|---|
This actor (lever-jobs-lookup) | $0.005 per company whose board is found (less on paid tiers), $0.0001 actor start, nothing for a company with no Lever board | Every open posting for a company's Lever board — title, location, team, commitment, apply URL — filtered by role keyword, location, remote, or posting date, with onlyNewSinceLastRun for deltas | Lever only. If your list is mixed-ATS, use ats-jobs-unified-lookup. Lever exposes one date per posting (no separate "first posted" vs. "last updated"), and only one location field — no per-office breakdown. |
| TheirStack | $0.005–$0.03 per company | A job-postings dataset with history, normalised across many ATS platforms and job boards | Broader coverage than one platform, and it keeps history. This reads Lever's own API live, at the bottom of that price range. |
| Lever's own API | Free | The same JSON | It is the same JSON. This handles the slug/URL parsing, filtering, deltas, and the retries — and hands you a flat table instead of raw postings JSON. |
| Clay | $0.08–$0.40 per enriched row in credits, on top of a seat | A whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around it | If you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable from Clay via its HTTP step. |
Prices for third-party tools are their published list prices as of August 2026 and are not tracked here — check the vendor before relying on the comparison.
FAQ
Why is a row empty / why does found say false?
Either the input doesn't look like a Lever slug or URL (status: BAD_FORMAT), or that company
doesn't have a Lever board, or currently has zero open roles (status: NOT_FOUND). Check the
message column for the specific reason.
Why wasn't I charged for that row?
You're only charged for a company where at least one open role was found on its board. A company
with no board or no current openings is free — check status to see which.
Why was I charged for a company that returned 0 jobs?
Because its board exists and has open postings — they just didn't match your filters, or weren't
new since your last run. totalJobCount shows how many were actually on the board. A company with
no Lever board, or with nothing open at all, comes back found: false and is never charged.
Does the "new since last run" state cost anything or leak between users?
It lives in a named key-value store (lever-jobs-lookup-state) inside your own Apify account, so
nobody else can see it, and its storage cost is negligible — a list of posting IDs per company per
filter combination. Delete that store to reset every watchlist. Changing any filter also starts a
fresh watchlist automatically, since the filter combination is part of the seen-list's key.
Are there rate limits? The actor queries Lever's public postings API once per company in your input list; it isn't authenticated and doesn't need a key. Very large company lists run as a normal Apify job — expect run time to scale with list size, same as any other actor in this catalogue.
Is this GDPR-safe to run on a list of companies? The input is company slugs or careers-page URLs, and the output is public job posting data Lever already serves on the company's own careers page — nothing personal is looked up or stored beyond the seen-list of posting IDs used for delta mode, which lives in your own account.
Can I schedule this and call it from an AI agent at the same time?
Yes — the same actor works both ways. Put it on an Apify schedule with onlyNewSinceLastRun for a
standing watchlist, and call it synchronously over HTTP or MCP (see above) for one-off or
agent-driven lookups; they don't interfere with each other unless they share the same filter
combination on the same company.
Does this work for companies not on Lever?
No — only companies whose careers page runs on Lever's jobs.lever.co platform. Companies on
Greenhouse, Ashby, Workday, or another ATS need the matching lookup actor for that platform, or
ats-jobs-unified-lookup if you don't know which platform a company uses.