ATS Job Boards - live postings from Greenhouse and Lever
Pricing
from $10.00 / 1,000 job board reads
ATS Job Boards - live postings from Greenhouse and Lever
Every open role on a company's own job board, from the public APIs Greenhouse and Lever publish for employers to embed on their careers page. One row per posting: title, location, department, apply URL, posted date. No login, no API key. Ashby is not read - its robots.txt refuses us.
Pricing
from $10.00 / 1,000 job board reads
Rating
0.0
(0)
Developer
Stephen Psaradellis
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
22 days ago
Last modified
Categories
Share
Every open role on a company's own job board, read from the public APIs Greenhouse and Lever publish so that employers can embed their postings on their careers page. One dataset row per posting: title, location, department, commitment, workplace, apply URL, posted date, and optionally the full HTML description.
No login. No API key. No scraping around a wall - these are the endpoints the company's own careers page calls.
Use case
You are tracking hiring at 50 companies - for a job board, a sales signal, a competitive read, or your own search. LinkedIn will not let you, and the aggregators are days stale and drop half the roles. But almost every one of those companies runs Greenhouse or Lever, and both publish the company's own postings over a public API so the careers page can render them. This Actor reads that: today's postings, from the employer, with the real apply URL.
What you get
One dataset row per open posting:
| field | meaning |
|---|---|
ats | greenhouse or lever |
board | the board token or company slug it came from |
job_id | the ATS's own id for the posting |
title | the role title as the employer wrote it |
location | the location string the ATS returns |
department | the team, when the ATS gives one (see the note below) |
commitment | e.g. Regular Full Time (Salary) - Lever only |
workplace | remote, hybrid or onsite - Lever only |
absolute_url | the real apply URL on the employer's board |
posted_at | when the ATS says the posting went up (UTC) |
read_at | when this row was read (UTC) |
Where a field is blank, the ATS returned nothing for it. Greenhouse's plain jobs endpoint sends no department; turn Include the full description on and it does, at no extra request. Nothing here is guessed or filled in from another source.
A RUN_SUMMARY record in the key-value store says how many boards were asked,
how many answered, how many were empty, how many 404ed, how many postings were
pushed, and what stopped the run if a cap did. A board with no open roles is
reported as empty, not dropped - "this company is not hiring right now" is an
answer, and you paid a request for it either way.
Sample output
Two rows from a run on 2026-09-07, exactly as the dataset holds them - one from each ATS, so you can see what each source does and does not send:
[{"ats": "greenhouse","board": "vercel","job_id": "5732855004","title": "Site Engineer","location": "Remote - United States","department": "","commitment": "","workplace": "","absolute_url": "https://job-boards.greenhouse.io/vercel/jobs/5732855004","posted_at": "2026-08-27T17:54:00.000Z","read_at": "2026-09-07T02:59:49.489Z"},{"ats": "lever","board": "leverdemo","job_id": "7e10ea46-98be-4bd1-a3ca-57d153b25c61","title": "Sales Engineer","location": "New York, New York","department": "Sales","commitment": "Remote","workplace": "remote","absolute_url": "https://jobs.lever.co/leverdemo/7e10ea46-98be-4bd1-a3ca-57d153b25c61","posted_at": "2025-11-25T21:21:23.926Z","read_at": "2026-09-07T02:59:54.502Z"}]
That run had Include the full description off, which is why the Greenhouse
row's department is empty and the Lever row's is not.
How to run it
- Open the Actor in Apify Console and press Start. The defaults read two
boards -
greenhouse:vercelandlever:leverdemo- and finish in seconds. - Replace Job boards with your own, one per line. The token is the last
path segment of the company's public board URL:
job-boards.greenhouse.io/vercelorjobs.lever.co/leverdemo. You can paste the whole URL and it will take the token off the end; a bare name with no prefix is tried on Greenhouse. - Read the dataset in Console, export it as JSON or CSV, or fetch it from the
API with the run's
defaultDatasetId.
Sample input
{"boards": ["greenhouse:vercel","lever:leverdemo"],"includeContent": false,"maxJobs": 200}
Input
- boards - the boards to read, in order, as
greenhouse:tokenorlever:company. - includeContent - adds each posting's full HTML body. Costs no extra
request. On Greenhouse it also fills in
departmentand offices. - maxBoards - stop after this many boards. 0 is unbounded.
- maxJobs - stop after this many postings. 0 is unbounded. This and
maxBoardsare also your bill ceiling. - timeoutSecs - seconds before a board read is retried, then recorded as an error against that board.
Pricing
Pay per event, with no charge for starting the Actor and no charge for platform usage:
| event | price | when |
|---|---|---|
board-read | $0.01 | one board fetched, whether or not it has open roles |
job-row | $0.004 | one posting pushed. A posting seen twice in a run is charged once |
What a run costs:
| run | events | price |
|---|---|---|
| default: 2 boards, 98 postings (measured 2026-09-07) | 2 + 98 | $0.41 |
| 20 boards averaging 40 roles | 20 + 800 | $3.40 |
| 50 boards averaging 40 roles | 50 + 2,000 | $8.50 |
| the default caps, whatever you feed them | 1,000 + 50,000 | $210.00 |
Lower maxBoards and maxJobs to bound a run below that.
Use it from code
The API tab on this page has ready-made snippets for Node.js, Python and
curl, including run-sync-get-dataset-items, which starts a run and returns
the rows in one call.
Use it from Claude or ChatGPT (Apify MCP)
This Actor is a tool your assistant can call directly, over the
Model Context Protocol. Apify hosts the
server at https://mcp.apify.com; adding ?tools= pins this Actor as one
named tool rather than loading the whole store.
Claude Desktop or Claude Code - add a custom connector with the URL:
https://mcp.apify.com?tools=vital_tuxedo/ats-job-boards
Any other MCP client (Cursor, VS Code, ChatGPT developer mode, your own agent) - add the server to its config:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com?tools=vital_tuxedo/ats-job-boards","headers": { "Authorization": "Bearer <APIFY_TOKEN>" }}}}
Drop the headers block to use OAuth instead: the browser opens once so you
can sign in to Apify and approve access. Then ask in plain language:
Pull every open engineering role at Vercel and Figma from their own job boards, and tell me which are remote.
Your assistant starts the run, waits for it and reads the dataset back. The per-event prices above are the whole cost - going through MCP adds nothing.
No Apify account at all? This Actor is flagged eligible for agentic
payments, so an agent holding USDC on Base can buy a prepaid Apify token at
https://agi.apify.com over x402 and run it with no account and no signup.
FAQ
Where do the rows come from? From the ATSes themselves:
boards-api.greenhouse.io/v1/boards/{token}/jobs and
api.lever.co/v0/postings/{company}?mode=json. Both are the endpoints an
employer's own careers page calls to render its openings. Greenhouse's docs
say it plainly: "Job Board data is publicly available, so authentication is
not required for any GET endpoints." Lever's robots.txt reads Allow: /
with Crawl-delay: 1, which this Actor honours as a real one-second gap
between Lever board reads - that is also why it has no concurrency dial.
Does it apply to jobs? No. Both ATSes have an application submission endpoint, and this Actor never calls it. It sends GETs and reads answers.
Does it read Ashby, Workday or Greenhouse's job-board HTML? No. Ashby is
in the same family and is deliberately left out: api.ashbyhq.com answers a
robots.txt request with 401, and a refusal is treated as a refusal.
Workday and HTML board scraping are not supported at all.
How do I find a company's board token? Open their careers page and follow
the link to the listing. If the URL is job-boards.greenhouse.io/acme, the
token is acme and you write greenhouse:acme. If it is
jobs.lever.co/acme, you write lever:acme. Pasting the whole URL works too.
What happens if a board does not exist? It is counted as missing in the
RUN_SUMMARY rather than failing the run - a company that has left the ATS is
a finding, not an error. You are charged the one board-read for asking.
Why is department empty on my Greenhouse rows? Because
Include the full description was off. Greenhouse's plain jobs endpoint
does not return departments; turning it on fills them in and costs no extra
request.
Running locally
npm installnpm start
Input is read from storage/key_value_stores/default/INPUT.json; the dataset
lands under storage/datasets/default/.