跳到正文
DEV Community· Ben Barazandeh·· 3 小時前AI 評分55

如何直接透過 Greenhouse、Lever、Ashby 和 Workday 追蹤目標公司的新職位

Track New Jobs at Your Target Companies Straight From Their ATS (Greenhouse, Lever, Ashby, Workday)

AI 導讀

Ben Barazandeh 示範如何直接讀取 Greenhouse、Lever、Ashby 和 Workday 的公開 JSON 資料源,追蹤目標公司的新職位,毋須抓取招聘頁 HTML。

正文

Disclosure: I'm Ben, and I built the Apify Actor mentioned later in this post. I charge per result for it. Everything in the tutorial part works with free tools too.

If you sell to companies that are hiring, recruit into them, or just want to know when a particular team opens a role, the company's own careers page is the best signal you can get. It's first-party and current, and you don't get job-board reposts or listings that expired three weeks ago.

The nice surprise is that you rarely need to scrape HTML to read it. Most careers pages are a thin skin over an Applicant Tracking System (ATS), and most ATSs publish a public JSON feed for exactly this purpose.

Step 1: Find the ATS behind a careers page

Open the careers page, click any job, and look at the URL:

URL looks like ATS Public feed
boards.greenhouse.io/stripe or job-boards.greenhouse.io/... Greenhouse boards-api.greenhouse.io/v1/boards/{slug}/jobs
jobs.lever.co/spotify Lever api.lever.co/v0/postings/{slug}?mode=json
jobs.ashbyhq.com/openai Ashby api.ashbyhq.com/posting-api/job-board/{slug}
nvidia.wd5.myworkdayjobs.com/... Workday POST search endpoint per tenant

The slug in the URL is what you pass to the API.

Step 2: Call the feeds yourself

These three calls worked when I ran them on 25 Oct 2026:

# Greenhouse: every open job at Stripe
curl -s "https://boards-api.greenhouse.io/v1/boards/stripe/jobs" \
  | python3 -c "import json,sys; j=json.load(sys.stdin)['jobs']; print(len(j), j[0]['title'], '|', j[0]['location']['name'])"

# Lever: Spotify
curl -s "https://api.lever.co/v0/postings/spotify?mode=json" \
  | python3 -c "import json,sys; j=json.load(sys.stdin); print(len(j), j[0]['text'])"

# Ashby: OpenAI, with structured compensation
curl -s "https://api.ashbyhq.com/posting-api/job-board/openai?includeCompensation=true" \
  | python3 -c "import json,sys; j=json.load(sys.stdin)['jobs']; print(len(j), j[0]['title'])"

The output was 719 jobs at Stripe, 90 at Spotify and 793 at OpenAI. No key, no login, no browser.

Step 3: The pitfalls

Once you go past three companies, this is where the time goes:

  • Every ATS has its own schema. Greenhouse gives you location.name, Lever categories.location, Ashby location plus secondaryLocations. Department, remote flag and employment type all have different names and shapes. You'll write a normaliser per ATS.
  • Salary is only sometimes structured. Ashby, Lever and Recruitee can return min/max/currency. Elsewhere, if the company publishes pay at all, it's buried in the description HTML and you have to parse ranges like "$250K - $445K" yourself.
  • Lever has an EU host. Some companies live on jobs.eu.lever.co and need the EU API host (api.eu.lever.co) instead.
  • Workday is the awkward one. Each tenant has its own host and site name, you POST a search, and it caps at about 2,000 results per search. For a big employer you need keyword searches to reach specific roles.
  • "New jobs" needs a date. To get a "posted today" feed, you need each ATS's published/updated date, which also differs per platform. Dedupe on the ATS job ID.
  • Be gentle. These are public feeds, but one request per board per day is plenty for monitoring.

None of it is hard. It's just a lot of small adapters.

Step 4: Or use the packaged version

I wrapped seven ATSs (Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters and Recruitee) into one Apify Actor, Career Site Jobs API. You can pass career URLs, ats:slug, or just a bare company name, and it tries to detect the ATS:

{
  "companies": ["https://jobs.ashbyhq.com/openai", "https://boards.greenhouse.io/airbnb",
                "https://jobs.lever.co/spotify",
                "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite", "stripe"],
  "keywords": ["engineer"],
  "maxItemsPerCompany": 3
}

Every row has the same fields whatever the ATS: company, ats, jobId, title, department, location, remote, employmentType, salaryMin, salaryMax, salaryCurrency, postedAt, url, applyUrl, description and a few more. Fields an ATS doesn't publish come back as null.

Here's what that input returned in a real run on 17 Oct 2026 (15 jobs, about 7 seconds). The log reported 814 open jobs at OpenAI, 173 at Airbnb, 82 at Spotify, 732 at Stripe (auto-detected from the plain name stripe), and 2,000 at NVIDIA, which is Workday's search cap, not the real total.

ATS Company Title Location Salary
ashby openai Research Engineer San Francisco $250K - $445K
greenhouse Airbnb Engineering Manager, Guest & Host London, United Kingdom –
lever spotify AV Engineer - Platform Stockholm –
workday nvidia Director, Engineering – Software Engineering Vietnam, Hanoi –
greenhouse Stripe AI Engineer Chicago –

(The counts differ from my 25 Oct curl calls above because boards change daily. That's the point of reading them live.)

Filters: title keywords to include or exclude, location with aliases (United States also matches entries like US, CA, Santa Clara), remote only, department, and postedWithinDays. Each run also writes a per-company SUMMARY record with the detected ATS, jobs on the board, jobs saved and any errors.

The setup I'd actually use

  1. Put your 20–200 target accounts in companies.
  2. Set postedWithinDays: 1 (or 2, to be safe with time zones).
  3. Schedule it daily in Apify and connect Google Sheets, Slack or a webhook.

You get a morning list of the roles each target company opened yesterday. If you set includeDescription: false, runs are lighter and faster.

Limits, honestly

  • It isn't a job board. It reads the companies you give it. It can't search "all companies hiring Rust engineers".
  • Seven ATSs only. iCIMS, Taleo, SuccessFactors, custom in-house career sites and LinkedIn/Indeed aren't covered.
  • Workday tops out around 2,000 jobs per search. Add keywords for very large employers.
  • Salary only where the company publishes it. In the sample above, only the Ashby rows had pay.
  • Auto-detection by name can miss. If acme isn't found, paste the careers URL instead.

What it costs

$0.002 per job ($2 per 1,000), with no start fee. You pay only for jobs saved after your filters, and the run stops cleanly at your "maximum cost per run". The 15-job test above was 3 cents in job charges. The DIY route costs nothing but your time.

Play fair

Use the data in line with each company's terms, and don't use hiring signals to spam recruiters or hiring managers. A short, relevant note beats a sequence of ten.

Which ATS or Workday tenant breaks for you? I'd love to collect edge cases in the comments, especially tenants with odd site names.

來源:DEV Community · dev.to