Track hiring signals at any company with the Greenhouse and Lever public job APIs
Thousands of companies host their careers page on Greenhouse or Lever. Both platforms expose a public, documented, read-only API for those job boards, meant for building job sites. That makes them a clean data source for a useful question:
Which companies are hiring, for which teams, and how fast is that changing?
Sales teams use it as a buying signal, investors as a proxy for momentum, job seekers as an alert feed. This post shows how to get it in a few lines of Python, without scraping HTML and without collecting any personal data.
The two APIs
- Greenhouse:
https://boards-api.greenhouse.io/v1/boards/{company}/jobs?content=true - Lever:
https://api.lever.co/v0/postings/{company}?mode=json
Both return JSON lists of open postings. Lever asks clients to stay at about one request per second.
Calling them directly is easy for one company. It gets tedious when you want a watchlist, "only new jobs since yesterday", normalized fields across both platforms, and a per-company summary. That is what the Company Jobs Tracker Actor does, so the rest of this post uses it.
Hiring signals for a list of companies
pip install apify-client export APIFY_TOKEN=your_token import os from apify_client import ApifyClient client = ApifyClient(os.environ["APIFY_TOKEN"]) run = client.actor("caspiandata/ats-jobs-hiring-signals").call(run_input={ "companies": ["stripe", "airbnb", "lever:spotify", "lever:palantir"], "outputJobs": False, # only the per-company summary rows }) rows = [r for r in client.dataset(run["defaultDatasetId"]).iterate_items() if r["type"] == "company-signal"] for r in sorted(rows, key=lambda r: r["postedLast30Days"], reverse=True): print(r["company"], r["openRoles"], r["postedLast30Days"], r["topDepartments"][0]["name"]) The full script formats it as a table. Output from a run on 31 October 2026:
Company Open roles Posted 30d Remote % Top department Stripe 746 238 16% Account Executives (EMEA) Airbnb 202 94 10% Software Engineering Spotify 89 35 31% Engineering Palantir 299 17 0% Dev Run it again tomorrow and each row also has newSinceLastRun, closedSinceLastRun and changeSinceLastRun.
A daily "new jobs" alert
run = client.actor("caspiandata/ats-jobs-hiring-signals").call(run_input={ "companies": ["https://boards.greenhouse.io/stripe", "lever:spotify"], "keywords": ["data", "analytics"], "onlyNew": True, "stateKey": "my-watchlist", }) The first run returns everything; every later run returns only postings that appeared since the previous one. Put it on a cron job or an Apify schedule and pipe the result to Slack or email.
Finding a company's slug
Open the company's careers page and look for links to boards.greenhouse.io/<slug>, job-boards.greenhouse.io/<slug> or jobs.lever.co/<slug>. You can also just pass the slug and the Actor checks Greenhouse first, then Lever.
Notes
- Only public postings are read, via the APIs the platforms document for that purpose. Email addresses and phone numbers in descriptions are removed.
- Cost: $1 per 1,000 jobs and $5 per 1,000 company summary rows.
Runnable examples: github.com/caspiandata/caspiandata-examples
Disclosure: we (Caspian Data) built and maintain the Actor used here. This post was written with the help of AI tools and the numbers come from a real run.