Hiring Signals & ATS Jobs Scraper — Greenhouse, Lever, Ashby
Pricing
from $0.80 / 1,000 job records
Hiring Signals & ATS Jobs Scraper — Greenhouse, Lever, Ashby
Hiring signals from company career pages: new, removed and changed roles per company, plus normalized job postings from Greenhouse, Lever, Ashby, SmartRecruiters, Workable, 7 more ATSs, USAJOBS and any careers page with JobPosting markup. Pay per job and signal.
Pricing
from $0.80 / 1,000 job records
Rating
0.0
(0)
Developer
Owlabee
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 hours ago
Last modified
Categories
Security
Limited permissionsShare

Hiring signals for sales, recruiting and investment teams: point this Actor at company career pages on Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Rippling, Gem, Breezy HR, Teamtailor, Personio, Manatal or JobScore, at US federal agencies on USAJOBS (with your own free API key), or at any careers site that publishes schema.org JobPosting markup, and it returns every open role as normalized JSON, then, on scheduled runs, the new, removed and changed roles per company with a hiring-velocity score. It reads public job-board APIs, feeds and the employers' own pages, so there is no login, browser or proxy.
Renamed on 2026-11-07: this Actor's address changed from
owlabee/ats-hiring-signalstoowlabee/job-postings-api. Saved tasks, schedules, webhooks and integrations keep working, because they point to the Actor's ID, which did not change. Update anything that calls it by name: API URLs (owlabee~job-postings-api), MCP tool lists (owlabee/job-postings-api) and bookmarks.
What it does
This Actor scrapes job postings straight from the public job-board APIs and feeds that company career pages are built on: Greenhouse, Lever, Ashby, SmartRecruiters and Workable, and since November 2026 also Rippling, Gem, Breezy HR, Teamtailor, Personio, Manatal and JobScore. Give it a list of boards (greenhouse:stripe, https://jobs.lever.co/spotify, personio:tado, …) and it returns one normalized record per open job: title, department, team, location (raw plus best-effort city/country), a remote flag, employment type, posted/updated dates, apply URL, optional plain-text description and salary data where the source exposes it (Ashby, Lever, Personio, Breezy HR, USAJOBS and JobPosting markup).
Two more kinds of source fill the gaps between ATSs. USAJOBS (usajobs:VA) returns every open federal job of an agency through the official Search API, with pay range and closing date; it needs your own free API key, because the government's terms do not allow a key to be shared. schema.org JobPosting markup (jsonld:https://www.example.com/careers, or automatically with extendedDetection) covers careers sites on any other system (iCIMS, Jobvite, JazzHR, Phenom, Avature, custom sites) as long as they publish the structured data search engines read; the Actor honors robots.txt and reads one page at a time.
Switch to signals mode and it becomes a hiring monitor. Each board is compared with the snapshot from the previous run and you get change events — new-role, removed-role, title-changed, location-changed — plus one board-summary per company with open-role count, net change, top departments, top locations, remote share and a 0–100 hiring velocity score. That is the data sales teams, recruiters, investors and researchers use to spot companies that are expanding, freezing or shifting focus, without touching LinkedIn.
Because it reads official job-board APIs over plain HTTP, it needs no browser, no proxies and no login, which keeps it fast and cheap: 1,000 jobs cost about $1.00. Results are available as JSON, CSV, Excel, through the Apify API, webhooks and the Apify MCP server.
Once you know who is hiring, SPF, DMARC & DKIM Checker — Bulk Domain WHOIS, DNS & SSL adds each company's registrar, mail provider and tech stack in one more run.
Why this Actor
| This Actor | Typical scraper in this category | Do it yourself | |
|---|---|---|---|
| Data sources covered | Twelve ATS providers (Greenhouse, Lever, Ashby, SmartRecruiters, Workable, Rippling, Gem, Breezy HR, Teamtailor, Personio, Manatal, JobScore) through their public job-board APIs and feeds, USAJOBS with your own key, and schema.org JobPosting markup on any other careers site, mixed freely in one run | One to three providers, often a single one, frequently scraped from the rendered careers page | One API client per provider, each with its own pagination, field names and quirks |
| Modes | jobs export and signals monitoring: new, removed, retitled and relocated roles plus one summary per company with a hiring velocity score | Export only; change detection, when offered, is a flag that marks unseen jobs | Store snapshots yourself and write the diff, the summary and the scoring |
| Output fields | One normalized record per job: title, department, team, raw and parsed location, remote flag, employment type, dates, apply URL, optional description text, compensation where published | Provider-specific raw fields, or a normalized subset without compensation or parsed location | Whatever you map, re-mapped whenever a provider changes its payload |
| Pricing unit | Per job record, per hiring signal and per board request; an error item costs the same as the record it replaces | Per job result, sometimes with a per-run fee or a monthly plan on top | Your engineering time plus the compute that runs it |
| Proxies or browsers needed | None: plain HTTPS to official APIs, no login | Browser automation and residential proxies when the careers page is scraped instead of the API | None if you use the APIs, a browser farm if you do not |
| Agent / MCP ready | Yes: pay-per-event, limited permissions, pin link, prompts and a call example below | Sometimes | You write and host the tool definition |
| Limits | Public boards only; Workable sits behind a WAF and may be blocked; time budget per board, request deadlines, caps per board and per run | Varies; caps are usually per run only | Rate limits and retry handling are yours to tune |
- Signals mode is a hiring monitor, not just an export: one summary per company with net change and a 0–100 velocity score, which is the field sales and investor teams sort by.
- Billing follows the work: a board request is charged even when it returns nothing or times out, so the cost of an empty or failing board is known before the run and nothing is billed in bulk at the end.
- Every abandoned unit of work is visible: a blocked or stalled board becomes a charged error item with a code, never a silent gap in the dataset.
- Honest fields:
department,postedAtandcompensationstaynullwhen a provider does not publish them; nothing is inferred. - The quick-start input is the Store's daily automated test, so the Actor is verified every day against live boards.
How to use
- Enter your Job boards, one per line, either as
provider:boardIdor by pasting the career-page URL. The provider is detected from the hostname (boards.greenhouse.io,job-boards.greenhouse.io,jobs.lever.co,jobs.ashbyhq.com,careers.smartrecruiters.com,apply.workable.com,<company>.workable.com,ats.rippling.com,jobs.gem.com,<company>.breezy.hr,<company>.teamtailor.com,<company>.jobs.personio.de,careers-page.com,careers.jobscore.com). For US federal jobs addusajobs:<agency code>and fill in the USAJOBS section with your own key. You can also paste the company's own careers URL (https://www.example.com/careers): the Actor fetches that page once, follows redirects and detects the ATS board behind it. Or pick a Company preset (ai-labs,developer-tools,fintech) to add a curated, verified list of boards. - Pick a Mode:
jobsfor a full export,signalsto detect changes since the last run. Optionally enable Include job description, lower Max jobs per board, set a Webhook URL. - Click Start. For signals, schedule the same task (daily or weekly); the first run writes a baseline, every later run writes only what changed plus a summary per board.
Quick start input
The same input the Store runs in its daily automated test, so it is cheap and always available; paste it into the JSON tab of the input form or send it as the body of an API or MCP call:
{"boards": ["greenhouse:stripe","lever:spotify"],"mode": "jobs","includeDescription": false,"maxJobsPerBoard": 50}
Ready-to-run inputs
Seven inputs you can paste as they are; each validates against the input schema.
Every open role on one Greenhouse board, with description text
{"boards": ["greenhouse:stripe"],"mode": "jobs","includeDescription": true,"maxJobsPerBoard": 500}
A Lever board pasted as its careers URL
{"boards": ["https://jobs.lever.co/spotify"],"mode": "jobs","includeDescription": false,"maxJobsPerBoard": 1000}
Weekly hiring signals for several companies, summary POSTed to a webhook (schedule it weekly; the first run writes the baseline)
{"boards": ["greenhouse:stripe", "lever:spotify", "ashby:openai"],"mode": "signals","maxJobsPerBoard": 2000,"stateStoreName": "hiring-signals-weekly","webhookUrl": "https://example.com/hooks/hiring-signals"}
A company careers URL instead of a board URL (the Actor fetches the page once, detects the ATS behind it and scrapes that board; the careers page fetch counts as one board request)
{"boards": ["https://www.anyscale.com/careers"],"mode": "jobs","includeDescription": false,"maxJobsPerBoard": 500}
Weekly hiring signals for a whole sector with a company preset (59 verified fintech and crypto boards; add your own boards to the list, duplicates are merged)
{"boards": ["greenhouse:stripe"],"companyPreset": "fintech","mode": "signals","maxJobsPerBoard": 2000,"stateStoreName": "fintech-weekly"}
Boards on the newer ATSs plus careers sites without a supported ATS (extendedDetection also looks for Rippling, Gem, Breezy HR, Teamtailor, Personio, Manatal and JobScore behind a careers URL, then reads the site's JobPosting markup)
{"boards": ["personio:tado", "https://career.teamtailor.com/jobs", "rippling:rippling", "https://www.example.com/careers"],"extendedDetection": true,"mode": "jobs","maxJobsPerBoard": 500}
Weekly federal hiring signals for two agencies on USAJOBS (your own key and the email it was registered with; the key is a secret input and never appears in the output or the log)
{"boards": ["usajobs:VA", "usajobs:HE38"],"usajobsApiKey": "<your USAJOBS API key>","usajobsEmail": "you@example.com","mode": "signals","stateStoreName": "federal-weekly"}
Input
| Field | Type | Required | Description |
|---|---|---|---|
boards | string[] | yes, unless companyPreset is set | provider:boardId (greenhouse, lever, ashby, smartrecruiters, workable, rippling, gem, breezy, teamtailor, personio, manatal, jobscore, usajobs with an agency code, or jsonld:<careers URL>), a public board URL, or a company's own careers URL (https://www.example.com/careers): that page is fetched once (redirects followed, up to 5 MB read, 20 seconds including retries) and the Greenhouse, Lever, Ashby, SmartRecruiters or Workable board behind it is detected and scraped like any other board. The careers page fetch counts as one board request; a page with no detectable board becomes one ATS_NOT_DETECTED error item. Duplicates are merged. |
companyPreset | ai-labs | developer-tools | fintech | no | Adds a curated list of boards to boards (duplicates by provider and board id are merged): ai-labs 50 boards, developer-tools 57, fintech 59, every one verified on 2026-10-27 against the public job-board APIs from the companies' own careers pages or ATS board URLs; the full list with sources is in docs/presets.md in the Actor's repository. Default none. |
extendedDetection | boolean | no | Default false, so careers URLs behave exactly as before. When true, a careers URL with none of the original five boards is also checked for a Rippling, Gem, Breezy HR, Teamtailor, Personio, Manatal or JobScore board, and then for schema.org JobPosting markup (the page itself, the job pages it links on the same site, or the job URLs in the site's sitemap). robots.txt is honored. |
mode | jobs | signals | no | jobs (default) lists every open job; signals diffs against the previous snapshot. |
includeDescription | boolean | no | Add descriptionText (HTML → text, max 3,000 chars). Default false. SmartRecruiters and Workable need one extra request per job for this; Rippling and Breezy HR listings carry no description, so it stays null there. |
maxJobsPerBoard | integer | no | Cap per board (default 2000). Boards over the cap are marked truncated; removed-role signals are suppressed for them. |
stateStoreName | string | no | Named key-value store holding snapshots for signals mode (default ats-hiring-signals-state). |
webhookUrl | string | no | POST target for the end-of-run summary (per-board summaries, counts, charges). |
maxConcurrency | integer | no | Boards fetched in parallel (default 5). Same-host requests are additionally limited to ~2/s. |
maxSecondsPerBoard | integer | no | Time budget per board in seconds (default 900, 30 to 3600). See "Limits and fair use". |
usajobsApiKey | string (secret) | for usajobs: boards | Your own USAJOBS Search API key (free at developer.usajobs.gov). Sent only to data.usajobs.gov in a header; never logged or written to the output. The Actor ships no key. |
usajobsEmail | string | for usajobs: boards | The email the key was registered with; USAJOBS requires it as the User-Agent of every request. |
Output example

A job record (mode: jobs, or baseline run in signals mode):
{"type": "job","provider": "greenhouse","boardId": "stripe","companyName": "Stripe","jobId": "4012345007","title": "Senior Backend Engineer, Payments","department": "Engineering","team": "Payments Platform","location": "San Francisco, CA","city": "San Francisco","country": "United States","remote": false,"employmentType": "full-time","postedAt": "2026-09-01T16:00:00.000Z","updatedAt": "2026-10-10T22:02:11.000Z","applyUrl": "https://boards.greenhouse.io/stripe/jobs/4012345007","jobUrl": "https://boards.greenhouse.io/stripe/jobs/4012345007","descriptionText": null,"compensation": null,"fetchedAt": "2026-10-16T12:00:00.000Z"}
Ashby and Lever jobs carry compensation as { "min": 295000, "max": 440000, "currency": "USD", "interval": "1 YEAR", "summary": "$295K - $440K" } when the company publishes it.
Records from the newer sources have the same fields, with provider set to rippling, gem, breezy, teamtailor, personio, manatal, jobscore, usajobs or jsonld. USAJOBS and JobPosting records add closesAt, the application deadline when the source publishes one. On USAJOBS, companyName is the hiring organization, department the federal department and team the job series; on a JobPosting record, boardId is the careers URL the crawl started from. A USAJOBS record (pay as published by OPM):
{"type": "job","provider": "usajobs","boardId": "VA","companyName": "Veterans Health Administration","jobId": "845100200","title": "Registered Nurse - Medical Surgical","department": "Department of Veterans Affairs","team": "Nurse","location": "Denver, Colorado","city": "Denver","country": "United States","remote": false,"employmentType": "full-time","postedAt": "2026-11-02T00:00:00.000Z","updatedAt": null,"applyUrl": "https://www.usajobs.gov:443/GetJob/ViewDetails/845100200?PostingChannelID=","jobUrl": "https://www.usajobs.gov:443/GetJob/ViewDetails/845100200","descriptionText": null,"compensation": { "min": 84520, "max": 129855, "currency": "USD", "interval": "year", "summary": "Per Year" },"closesAt": "2026-11-16T23:59:59.997Z","fetchedAt": "2026-11-07T12:00:00.000Z"}
A new-role signal (the other signal types share the shape; title-changed adds previousTitle, location-changed adds previousLocation):
{"type": "new-role","provider": "lever","boardId": "spotify","jobId": "a1b2c3d4-0000-4000-8000-000000000001","title": "Staff Software Engineer, Platform","department": "Engineering","location": "New York, NY","remote": false,"applyUrl": "https://jobs.lever.co/spotify/a1b2c3d4-0000-4000-8000-000000000001/apply","postedAt": "2026-10-14T10:26:40.000Z","job": { "jobId": "a1b2c3d4-…", "title": "Staff Software Engineer, Platform", "team": "Platform", "city": "New York", "country": "United States" },"detectedAt": "2026-10-16T12:00:00.000Z"}
A board-summary record (one per board per signals run):
{"type": "board-summary","provider": "lever","boardId": "spotify","companyName": null,"baseline": false,"openRoles": 312,"previousOpenRoles": 298,"newSinceLastRun": 21,"removedSinceLastRun": 7,"changedSinceLastRun": 3,"netChange": 14,"topDepartments": [{ "name": "Engineering", "count": 140 }, { "name": "Sales", "count": 45 }],"topLocations": [{ "name": "Stockholm, Sweden", "count": 120 }, { "name": "New York, NY", "count": 80 }],"remoteShare": 0.18,"hiringVelocityScore": 58,"truncated": false,"previousSnapshotAt": "2026-10-09T12:00:00.000Z","detectedAt": "2026-10-16T12:00:00.000Z"}
Error items look like { "type": "error", "provider": "lever", "boardId": "nonexistent", "error": "BOARD_NOT_FOUND", "errorMessage": "HTTP 404 ..." }. Error codes: BOARD_NOT_FOUND, UNKNOWN_PROVIDER, UNRECOGNIZED_URL, ATS_NOT_DETECTED (a careers URL whose page names no supported board), BLOCKED, WORKABLE_BLOCKED, RATE_LIMITED, TIMEOUT, FETCH_FAILED, and for the newer sources API_KEY_MISSING and INVALID_API_KEY (USAJOBS), ROBOTS_DISALLOWED, ROBOTS_UNAVAILABLE and NO_JOBPOSTING_MARKUP (JobPosting crawl), SOURCE_NOT_SUPPORTED (Workday, Oracle and SuccessFactors sites). They are charged like a job record because the work to discover the problem was done.
The run's key-value store also gets a SUMMARY record with counts, charges and all board summaries; the same payload is POSTed to webhookUrl when set.
If the output saves you time, a review on the Store page helps other buyers find this Actor; the Store invites you to leave one after you have run it a few times.
Alerts and delivery
Signals mode is built to run on a schedule; this is how the results reach the place you work in.
- Schedule in the Console. Save the input as a Task so it is stored, then create a schedule under Schedules (daily or weekly presets, or a cron expression) and attach the Task. Every run compares against the snapshot of the previous one; use a different
stateStoreNamefor each schedule that watches the same boards. - The Actor's own webhook. Set
webhookUrland the Actor POSTs one JSON document when the run finishes (10 second timeout, two retries; a failed delivery is recorded aswebhookDelivered: falsein theSUMMARYrecord and never fails the run). The body is the run summary:actor,runId,mode,boards, the countsjobs,signals,summariesanderrors,charges,limitReached,stateStoreName,results(one entry per board: provider, board id, company name, baseline job count, signal count, truncation or error) and, in signals mode,summarieswith the fullboard-summaryrecords. Individualjoband signal records are not in the body; read them from the dataset. - Apify run webhooks. On the Actor's Integrations tab add a webhook for run events such as
ACTOR.RUN.SUCCEEDED,ACTOR.RUN.FAILEDorACTOR.RUN.TIMED_OUT; Apify POSTs the run id and the default dataset id to your URL, which is all your own code needs to fetch the items. - Slack, Make, Zapier, Google Sheets, email. The same Integrations tab lists Apify's ready-made integrations: a Slack message when a run finishes, Make and Zapier modules that start runs and read the dataset, an export of each run's dataset to a Google Sheet, and an email notification. They are configured per Actor or per task, without code.
- API and dataset endpoints. Start a run with
POST https://api.apify.com/v2/acts/owlabee~job-postings-api/runs, read the newest results withGET https://api.apify.com/v2/acts/owlabee~job-postings-api/runs/last/dataset/items?format=json(alsocsvorxlsx, andfieldsto pick columns), or read any run's dataset athttps://api.apify.com/v2/datasets/<datasetId>/items. For short runsrun-sync-get-dataset-itemsstarts the run and returns the items in one call. Filter on thetypefield (new-role,removed-role,board-summary, …) on your side.
Pricing
Pay per event. You only pay for what the Actor produces; set a maximum cost per run in the run options to cap spend.
| Event | Price | Notes |
|---|---|---|
Job record (job-scraped) | $0.001 | Per job record, including baseline job records on the first signals run and error items |
Hiring signal (hiring-signal) | $0.005 | Per new-role, removed-role, title-changed, location-changed and per board-summary record |
Board request (board-fetched) | $0.008 | Per request to a job board's listing API (one per page of up to 100 jobs on Lever and SmartRecruiters, one for the whole board on Greenhouse, Ashby and Workable), including requests that time out, are blocked or return no jobs; ATS job detail requests are not charged |
Job page request (job-page-fetched) | $0.0005 | Per job page fetched while reading a careers site's schema.org JobPosting markup (jsonld: boards and extendedDetection fallbacks only), with or without a job on it, including pages that time out or carry no markup; never charged on ATS boards |
| Actor start | $0.00005 | Apify platform event |
Examples: 1,000 jobs ≈ $1.00. A weekly check of 50 companies ≈ 50 summaries = $0.25 + $0.005 per detected change, after a one-off baseline charged at the per-job price (50 companies × ~100 jobs ≈ $5.00). A quiet week with 50 companies and 60 changes costs ≈ $0.55 plus about $0.40 for 50 board requests (≈ $0.95). A single-board run of 100 jobs ≈ $0.10 + $0.008 = $0.108.
Board requests on the newer sources use the same events: one board request for the whole board on Rippling, Gem, Breezy HR, Teamtailor, Personio and JobScore; one per page of 20 jobs on Manatal; one per page of up to 500 postings on USAJOBS. For JobPosting markup the careers page and each sitemap read (at most three) are board requests, and each job page fetched is one job page request ($0.0005) whether or not it carries a job, so a JobPosting job costs $0.0015 all-in (one request per job, against one request per board or per 100 jobs on an ATS API). robots.txt is never charged. A careers site with 50 jobs read from its markup ≈ $0.008 + 55 × $0.0005 + 50 × $0.001 ≈ $0.09; a signals check of that site with nothing changed ≈ 50 page requests + one summary ≈ $0.04.
Store pricing discounts: users on the Scale plan (Silver) pay 10% less per event, Business (Gold) 20% less.
Limits and fair use
- Only the providers' public, unauthenticated job-board APIs and feeds are used:
boards-api.greenhouse.io,api.lever.co(andapi.eu.lever.co),api.ashbyhq.com/posting-api,api.smartrecruiters.com/v1/companies,apply.workable.com/api,api.rippling.com/platform/api/ats/v1/board,api.gem.com/job_board/v0,<company>.breezy.hr/json,<company>.teamtailor.com/jobs.rss,<company>.jobs.personio.de/xml,www.careers-page.com/api/v1.0/c,careers.jobscore.com/jobs/<company>/feed.json; plusdata.usajobs.gov/api/searchwith your own key. Private or password-protected boards are not supported. - USAJOBS needs your own key and its registration email (
usajobsApiKey, a secret input, andusajobsEmail). The Actor never ships or shares a key; without one, eachusajobs:board becomes oneAPI_KEY_MISSINGerror item and nothing is requested. Eachusajobs:entry is one agency code (VA,HE38,AF); USAJOBS's own rate limits apply to your key. - JobPosting markup is read only from the careers site you name (the same registrable domain), never from job boards, aggregators, Workday, Oracle Recruiting Cloud or SAP SuccessFactors (those three are not supported yet). robots.txt is checked before the first page and for every page after it (a robots.txt that cannot be read because the server fails counts as "disallowed"), its Crawl-delay is honored, and pages are fetched one at a time. Job pages are read up to 512 KB with a 10 second deadline; after 5 job pages without markup, or once the crawl has spent more than 15 seconds plus 3 seconds per job found, it stops and keeps what it found (
truncated). Careers sites that publish no markup give oneNO_JOBPOSTING_MARKUPerror item. - Not covered, by design: Indeed, LinkedIn, Glassdoor, ZipRecruiter, Monster, Dice, Wellfound, Upwork and the remote-job aggregators. Their own rules forbid reuse of their listings, so their hosts are never fetched.
- Requests to each provider host are rate-limited to about 2 per second with exponential backoff on 429/5xx; very large boards or
includeDescriptionon SmartRecruiters/Workable (one extra request per job) take proportionally longer. - Workable's career-page API sits behind a WAF. The Actor first tries the v3 search endpoint, then falls back to the v1 widget endpoint; if both are blocked you get a
WORKABLE_BLOCKEDerror item for that board and the run continues. No residential proxies are used. city/countryare best-effort parses of free-text locations and may benull;remoteistruewhen the provider flags it or the title/location says so.- Snapshots in signals mode store only the fields needed to diff (no descriptions), so a board with 2,000 roles uses well under 1 MB of key-value storage. If a board hits
maxJobsPerBoardthe summary is markedtruncatedand removals are not reported for it. - Careers URL detection reads one page per URL with a plain request (no browser), up to 5 MB and 20 seconds including retries, inside the board's time budget; without
extendedDetectionit never follows links beyond the page, and it never fetches aggregator or social-network hosts. - Time budget per board. Each board gets
maxSecondsPerBoardseconds (default 900) and is cut off earlier when it has produced nothing for 60 seconds (a stalling, timing-out or blocking provider). Every request, retries included, is limited to 20 seconds and aRetry-Afterlonger than 10 seconds is not waited for. A cut-off board keeps the jobs already fetched (truncated: "TIME_BUDGET"in the run summary; in signals mode removals are not reported for it); a board that produced nothing becomes oneTIME_BUDGETerror item, charged like every error item. Remaining descriptions are left empty when the budget ends during detail requests. - Default run memory is 512 MB (the platform default is set in the Actor's run options); Ashby and Lever boards are downloaded whole, so very large boards may need more.
- The Store's daily automated test runs with the prefilled boards (
greenhouse:stripe,lever:spotify) injobsmode andmaxJobsPerBoard: 50.
Related Actors
Other pay-per-event Actors from the same account, all limited-permission and agent-friendly:
- SPF, DMARC & DKIM Checker — Bulk Domain WHOIS, DNS & SSL — enrich each hiring company's domain with registrar, mail provider, tech stack and TLS status.
- Website Change Monitor — Sitemap Monitor & Page Diff — watch a company's own careers or pricing pages for content changes between runs.
- Grants.gov API & SAM.gov Scraper — Federal Grants Feed — see which target accounts are bidding for or winning federal grants and contracts.
Guide and code examples
- Guide: Greenhouse, Lever and Ashby Jobs API and Hiring Signals, covering the source, its fields and limits, and curl and MCP examples.
- Runnable examples (curl, Python, Node.js and an MCP config): owlabee/owlabee on GitHub.
Use from AI agents (MCP)
Pin this Actor in the Apify MCP server with one link: https://mcp.apify.com?tools=owlabee/job-postings-api, or let the agent find it with the search-actors tool. It is pay-per-event with limited permissions, so agents can discover it, inspect the input schema with fetch-actor-details and pay per run through agentic payments. Prompts that map directly onto the input:
- "Pull every open role from Stripe's Greenhouse board and Spotify's Lever board, including department, location and whether it is remote, as a CSV."
- "Watch these 40 companies' career pages (Greenhouse, Lever, Ashby and SmartRecruiters URLs attached) every Monday and tell me which ones opened new sales or engineering roles since last week, with a hiring velocity score per company."
- "Which of our target accounts started hiring for 'Head of Data' or 'Data Platform' roles in the last 30 days? Use their public job boards, not LinkedIn."
The agent receives the same dataset records shown in the output example above.
To call it from an agent that already has the Apify MCP server connected, copy this tool call and change only the input object (shown with the quick-start input; any input that validates in the Console works here too). The server returns the run's dataset items, and its per-call maximum total charge (maxTotalChargeUsd) caps spend the same way the run option does in the Console.
{"tool": "call-actor","arguments": {"actor": "owlabee/job-postings-api","input": {"boards": ["greenhouse:stripe","lever:spotify"],"mode": "jobs","includeDescription": false,"maxJobsPerBoard": 50}}}
FAQ
Does this need proxies or an API key? No. Greenhouse, Lever, Ashby and SmartRecruiters publish job-board APIs that need no credentials and work from datacenter IPs. Workable is the exception; see "Limits".
How is cost controlled? Set maxJobsPerBoard, keep includeDescription off unless you need the text, and set the run's maximum total charge. The Actor charges each record as it is written and stops cleanly when the limit is reached; in signals mode it then leaves the snapshot untouched so the next run re-detects the same changes.
How do I use USAJOBS? Request a free API key at developer.usajobs.gov, put it in USAJOBS API key (a secret input: it is stored encrypted, sent only to data.usajobs.gov and never written to the log or the output) and the email you registered with in USAJOBS registration email, then add one usajobs:<agency code> line per agency (usajobs:VA, usajobs:HE38). Each agency is treated as one board, so signals mode reports its new and closed openings run to run. The Actor does not ship a key of its own because the government's rules for the API do not allow keys to be shared.
What is JobPosting markup and when is it used? Many careers sites embed schema.org JobPosting data so search engines can show their openings; it carries the title, location, employment type, posted date, salary and deadline. The Actor reads it when you add jsonld:<careers URL>, or automatically with extendedDetection when a careers URL has no supported ATS board. It checks robots.txt first, then reads the careers page, the job pages it links on the same site (or the job URLs in the site's sitemap), one at a time; each job page read is one job page request ($0.0005) on top of the job records it yields. Workday, Oracle Recruiting Cloud and SAP SuccessFactors sites are not read yet.
How do I find a company's board id? Open the company's careers page and look at the URL of a job: boards.greenhouse.io/<token>, jobs.lever.co/<company>, jobs.ashbyhq.com/<org>, jobs.smartrecruiters.com/<Company>/..., apply.workable.com/<subdomain>/.... Paste that URL as-is; the Actor extracts the id. Or skip the lookup and paste the careers page itself; see the next question.
Can I give a company website instead of a board URL? Yes. Paste the company's own careers URL (https://www.example.com/careers) into boards. The Actor fetches that page once with a plain request, follows redirects (a careers. subdomain often lands straight on the ATS), and looks for a Greenhouse, Lever, Ashby, SmartRecruiters or Workable board in the final URL or the HTML: board and job links, the Greenhouse for= embed, the Ashby embed script, the Workable whr_embed snippet. The board it finds is then scraped exactly like a board you listed yourself, with the same records and events. The careers page fetch counts as one board request. Careers pages that render their job list only in the browser, without any link to the ATS in the HTML, cannot be detected: you get one ATS_NOT_DETECTED error item, charged like any error item, and the run continues; paste the board URL for those, or turn on extendedDetection, which also looks for the seven newer ATSs and then reads the site's JobPosting markup. Aggregator and social-network hosts are never fetched.
What is in a company preset? A curated list of boards for one theme: ai-labs (50 boards), developer-tools (57) and fintech (59). Every board was taken from the company's own careers page or the public ATS board URL it exposes, no directory or list site, and verified on 2026-10-27 to answer with at least one open job; the per-company table with sources is in docs/presets.md in the Actor's repository. Presets merge with your own boards, duplicates are dropped, and each board is charged like any other board. Boards move between ATS vendors over time, so a preset board that stops answering shows up as a BOARD_NOT_FOUND error item until the list is refreshed.
What happens on the first signals run? There is no previous snapshot, so the Actor writes every current job as a job record (charged at $0.001 each) plus a board-summary with baseline: true. Change events start with the second run. Use a different stateStoreName per schedule if you monitor the same board at different cadences.
Can an AI agent use this? Yes; see "Use from AI agents (MCP)" above for the pin link and example prompts. Schedules and webhooks work the same way from the Console or the API.
Does it include closed or unlisted jobs? No. Only jobs the provider currently lists publicly are returned; Ashby jobs with isListed: false are skipped. A job that disappears between runs shows up as removed-role.
Why is department or postedAt null for some jobs? Providers expose different fields: Greenhouse has no posted date on some boards (first_published can be null), Lever has no updatedAt, SmartRecruiters departments are optional. The Actor never guesses these.
Can I try it for free? Yes. The Apify free plan comes with monthly platform credit, and the quick-start input above costs a few cents per run, so you can test it on your own inputs before paying anything.
How do I find this Actor again? Bookmark it on the Store page (the bookmark icon next to the title); bookmarked Actors are listed in your Console, and the Store page shows new versions as they ship.
Support
Questions, bugs or a source you'd like added? Open an issue on the Actor's Issues tab, or email jacob@owlabee.com.
Changelog
- 2026-11-08 — Pricing: new
job-page-fetchedevent ($0.0005; Silver $0.00045, Gold $0.0004) per job page fetched while reading schema.org JobPosting markup, with or without a job on it. Onlyjsonld:boards andextendedDetectionfallbacks charge it; every ATS board, USAJOBS and the prefill cost exactly what they did before. - 2026-11-07 — More sources, all opt-in or new board types, so saved inputs return the same results at the same cost: seven more ATSs (Rippling, Gem, Breezy HR, Teamtailor, Personio, Manatal, JobScore) as
provider:boardIdor board URL; USAJOBS agencies with your own API key (usajobs:<agency code>, new secret inputusajobsApiKeyandusajobsEmail); schema.org JobPosting markup from any careers site (jsonld:<careers URL>), honoring robots.txt; newextendedDetectioninput (off by default) that looks for the newer ATSs and then for JobPosting markup behind a careers URL. New optionalclosesAtfield on USAJOBS and JobPosting records. More job-board and aggregator hosts are refused without a request (oneUNRECOGNIZED_URLerror item, as for LinkedIn and Indeed). Events and prices unchanged. - 2026-11-07 — Renamed from
owlabee/ats-hiring-signalstoowlabee/job-postings-apiso the address matches what people search for. Input, output and pricing are unchanged; calls by Actor ID, saved tasks and schedules are unaffected. Name-based calls to the old address stop resolving: update API URLs and MCP tool lists. - 2026-10-27 —
boardsaccepts a company's own careers URL: one plain fetch, ATS detected from the redirect or the HTML, then scraped like any board (the careers page fetch counts as one board request;ATS_NOT_DETECTEDerror item otherwise). NewcompanyPresetinput with three verified lists (ai-labs50,developer-tools57,fintech59 boards). README: comparison table, ready-to-run inputs per ATS, alerts and delivery, MCP call example, changelog. - 2026-10-25 — Pricing round: the board request became its own work-based event (charged even when a board returns nothing), event titles pluralized, Store discount tiers for the Scale and Business plans described; applied in the Console on 2026-10-26.
- 2026-10-23 — Time budget per board (
maxSecondsPerBoard), 20 second request deadline including retries, idle cut-off, chargedTIME_BUDGETerror items, worst-case margin tests. Listing: new title, SEO fields, MCP section, quick start, task examples; Related Actors use the new display titles. - 2026-10-17 — Public task examples published next to the Actor.
- 2026-10-16 — First release on the Store: five ATS providers,
jobsandsignalsmodes, end-of-run webhook summary.
Legal
Only public job postings published by the companies themselves through their applicant-tracking systems are accessed, with no authentication and at polite rates. Use the data in compliance with each provider's terms and applicable law. This Actor is not a consumer reporting agency; its output describes job openings, not people, and must not be used for employment, credit, insurance or tenant screening decisions.