Scrape any company's job postings β€” Greenhouse, Lever & Ashby, with one API call
DEV Community

Scrape any company's job postings - Greenhouse, Lever & Ashby, with one API call

Raw APIs

No key, no auth. These are live right now:

# Greenhouse
curl "https://boards-api.greenhouse.io/v1/boards/stripe/jobs"

# Lever
curl "https://api.lever.co/v0/postings/palantir?mode=json"

# Ashby
curl "https://api.ashbyhq.com/posting-api/job-board/openai"

At the time of writing that's 518 open roles at Stripe, 280 at Palantir, and 727 at OpenAI - three calls, three completely different JSON shapes. Greenhouse nests offices and departments as arrays of objects. Lever flattens everything into categories. Ashby puts the city in location.name and hides compensation behind a separate includeCompensation=true flag. Descriptions come back as escaped HTML on some, Markdown-ish on others. Multiply by six platforms and you've got a weekend project plus ongoing maintenance every time one of them changes.

The one-call version

Job Postings API auto-detects which ATS a company uses - from a bare slug or a full careers URL - and returns one normalized row per job. Here's a real, unedited record from a live run:

curl -X POST "https://api.apify.com/v2/acts/fetchbase~job-postings-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companies": ["stripe", "gitlab", "https://jobs.ashbyhq.com/openai"]
  }'
{
  "company": "stripe",
  "ats": "greenhouse",
  "id": "7954688",
  "title": "Account Executive, AI Sales (Grower)",
  "department": "1654 Account Executives (AI)",
  "location": "San Francisco, CA",
  "remote": null,
  "url": "https://stripe.com/jobs/search?gh_jid=7954688",
  "publishedAt": "2026-07-21T18:51:19-04:00",
  "salary": null,
  "description": "## Who we are\n\n### About Stripe\n\nStripe is a financial infrastructure..."
}

Note remote and salary are null there - and that's the honest part. Those fields are only as good as what the ATS publishes. Greenhouse boards frequently omit both. The actor normalizes the shape; it can't invent data the source doesn't expose.

The underrated part: some boards publish full comp

Ashby boards expose structured compensation, and plenty of companies leave it on. Of those 727 OpenAI roles, all 727 carry a published pay range - things like $257K - $335K β€’ Offers Equity. 460 of them are flagged remote. That is a real, public, structured compensation dataset that most people assume you have to buy from Levels.fyi or scrape out of rendered HTML. It's sitting behind a GET request.

Useful inputs

While you're exploring:

Input Does
companies Slugs or careers URLs - mix ATSes freely in one run
remoteOnly Keep only roles the board flags remote
titleFilter Substring match on title ("engineer")
maxJobsPerCompany Cap big boards (default 1000)
includeDescriptions Set false for a fast, light index

You're billed per job returned, so filters cut cost as well as noise.

Things worth building with it

  • A "who's hiring in AI" snapshot. One run across several labs, compare volume and department mix.
  • A remote-jobs alert. remoteOnly + titleFilter: "engineer" across your target companies, on a schedule, diffed against yesterday's dataset β†’ new postings to Slack.
  • Comp research. Pull a whole Ashby board and you get ranges attached to titles and locations.
  • Hiring as a market signal. Posting counts over time are a leading indicator - teams that are shipping are hiring, and teams in trouble quietly stop. Snapshot weekly and you've built a trends dataset nobody sells you.

Why the API route beats HTML scraping here

These are intended-use, documented endpoints. No bot walls, no proxy budget, no 3am breakage when a careers page gets redesigned. The tedious part - ATS detection, six-way shape merge, HTML→Markdown, comp parsing - is the part worth not rewriting yourself. Pay per job returned, failed runs cost nothing, and Apify's free credits cover plenty of testing.

The rest of the utility suite lives at apify.com/fetchbase. Built this because job data shouldn't require scraping infrastructure. If you want another ATS supported or normalized salary output, say so in the comments or the actor's Issues tab.

Comments

No comments yet. Start the discussion.