Job Board Hiring Signals: Greenhouse, Lever, Ashby
Pricing
from $3.00 / 1,000 hiring signals
Job Board Hiring Signals: Greenhouse, Lever, Ashby
Find companies hiring for the tools you sell or support. Reads public Greenhouse, Lever and Ashby job boards, flags posts that mention your tools with the matching sentence as proof, and tracks changes week over week. Also returns clean, filtered job listings.
Pricing
from $3.00 / 1,000 hiring signals
Rating
0.0
(0)
Developer
Will Emery
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
17 hours ago
Last modified
Categories
Features
Share
What is Job Board Hiring Signals: Greenhouse, Lever, Ashby?
Job Board Hiring Signals: Greenhouse, Lever, Ashby is an Apify Actor that reads public job listings from company career sites through the official, unauthenticated job-board APIs of Greenhouse, Lever, and Ashby. Only those three ATS platforms are supported.
The default mode is signals (hiring-signal mode): you name a tool or technology (for example, Snowflake or Salesforce), and the Actor flags companies whose posts mention it, with the matching sentence, a signal type, and a confidence score. A second jobs mode returns a normalized job feed from the same boards, without the matcher.
This Actor is not affiliated with Greenhouse, Lever, Ashby, or any tool vendor named in an example. It only reads what those public APIs already publish.
Try it: open the Actor, leave the prefilled hiring-signal example (Duolingo on Greenhouse, Spotify on Lever, Linear and Supabase on Ashby, plus a short tool list), and click Start. The prefilled run finishes in well under a minute (about 10–12 seconds on Apify at 512 MB). You can also call it from the Apify API, schedule it weekly, attach a webhook, or export the dataset as JSON or CSV.
Main features:
- Official Greenhouse, Lever, and Ashby job-board APIs (no API key)
- Hiring-signal mode is the default: tool aliases, section-aware matching, confidence, and a snippet of evidence
- Jobs mode: a normalized listing feed from the same boards
- Filters for keywords, location, remote, department, posting date, published pay, and inferred experience
- Optional company-name discovery that only probes official board endpoints (no search-engine scraping)
- Scheduled runs with a
stateKeyso only new or changed signals are emitted - In signals mode,
removeRepeatedText(on by default) skips repeated employer boilerplate so it does not inflate signal counts - Pay-per-event pricing: $0.003 per hiring signal, $0.001 per job, $0.01 per company rollup when the company has at least one signal (see pricing below)
How to try it
- Open this Actor in Apify Console. A free Apify account is enough to run the prefill.
- Leave the prefilled input:
modeissignals(the default),boardsis Duolingo (greenhouse/duolingo), Spotify (lever/spotify), Linear (ashby/linear), and Supabase (ashby/supabase),toolsincludessnowflake,dbt,salesforce,workday, andgo, andmaxItemsis 20. These are verified public boards. This run takes about 10–12 seconds on Apify and writes signal and rollup rows. - Click Start and wait for a Succeeded run.
- Open the Output tab. In signals mode, use the Signals view; company totals appear in the Company rollups view. Jobs mode uses the Jobs view. A free summary row is always included (Run summary view).
- Export JSON or CSV, or pass the dataset URL into a spreadsheet, webhook, or your own job.
For a weekly watch, save the input with a fixed stateKey and add an Apify Schedule (for example Monday 06:00 in your timezone). Attach a webhook on ACTOR.RUN.SUCCEEDED if you want a Slack or email ping.
The Actor's default memory is 512 MB (minimum 256 MB, maximum 1024 MB). We recommend 1024 MB for lists of 50 or more boards.
Use cases
- Sales prospecting: find companies whose posts mention a tool you sell against, including phrases about replacing or migrating from it.
- Partnership and integration research: find companies standing up a stack you complement (for example Snowflake plus dbt).
- Recruiting and agencies: watch named employers or a department and location for roles that mention a platform you staff or implement.
- Job-board and data pipelines: use jobs mode to pull a clean feed from boards you already have tokens for.
Input
mode defaults to signals. You can pass boards as boards objects, as career-site URLs or slugs in companies, or both. Unknown input fields are rejected. Passing a field this Actor does not support will fail the run.
| Field | Type | What it does |
|---|---|---|
mode | signals or jobs | Default is signals (hiring-signal mode). jobs is the plain feed |
boards | array of {ats, token, companyName?} | ats is greenhouse, lever, lever_eu, or ashby. token is the board slug (the last part of the public board URL). companyName is an optional label you supply; it is stored separately and never overwrites the name the ATS returns |
companies | string or object array | Board URLs or slugs, or {url or slug, platform, companyName}. Supported hosts include boards.greenhouse.io, job-boards.greenhouse.io, jobs.lever.co, jobs.eu.lever.co, and jobs.ashbyhq.com |
platform | string | Default auto: try Greenhouse, then Lever, then Ashby, and use the first board that exists (up to 3 requests per slug) |
discovery | object | {enabled, companyNames[], maxProbesPerCompany}. Builds slug guesses and probes only official board APIs; 404s are skipped. Default is off, 6 probes |
tools | string array | Signals mode. Built-in ids (for example salesforce, snowflake, dbt) or any other name, matched as written |
toolAliases | object | Extra aliases, or {"contextRequired": false} to relax context checks for ambiguous names |
requireAllTools | boolean | When true, a post must match every listed tool |
signalTypes | string array | Empty = all. Options: replacing, migrating_from, migrating_to, implementing, experience_with, nice_to_have, mention |
minConfidence | number 0–1 | Signals below this are dropped and not charged (default 0.6) |
outputLevel | signals, rollups, or both | Which charged rows to write in signals mode. Default both. A free summary row is always added |
onlyNewOrChanged | boolean | Default true. Uses the store named by stateKey (default default). Later runs emit only new or changed signals (post text changed, or confidence change ≥ 0.1) |
stateKey | string | Names the persistent store hiring-signals-state-{stateKey} |
includeSelfPostings | boolean | Default false. Off drops hits where the employer is the tool's own vendor |
removeRepeatedText | boolean | Signals mode, default true. Skip sentences that appear in at least half of a company's posts (at least 3 posts; boards with 4+ posts), or in 25+ of its posts, so boilerplate does not inflate signal counts. Job rows and descriptions are not changed |
keywords | string array | Case-insensitive whole-word phrases, in order and adjacent |
keywordsMode | any or all | Default any |
keywordsIn | string | Where keywords and exclude keywords are looked for. Default title_or_description |
excludeKeywords | string array | Drop a job if any of these phrases is found |
locations | string array | Case-insensitive substring of any location string as the ATS gives it. Remote also matches when isRemoteDerived is true |
remote | string | Default any. Uses isRemoteDerived. Hybrid alone is not remote |
departments | string array | Case-insensitive substring on department or team |
lookbackDays | integer | Uses updatedAt, falling back to postedAt. Empty = 30 in signals mode, no limit in jobs mode. 0 = no limit. Jobs with no date are kept |
postedAfter | string | Keep jobs whose postedAt is on or after this date (YYYY-MM-DD or relative, for example 30 days). Jobs without postedAt are dropped when this filter is set |
postedBefore | string | Keep jobs whose postedAt is before this date |
salaryMin | integer | Keep jobs whose published yearly pay range reaches at least this amount. Uses only pay Lever and Ashby publish; Greenhouse job lists carry no pay |
salaryMax | integer | Keep jobs whose published yearly pay range starts at or below this amount |
salaryCurrency | string | Default USD. Only pay in this currency is compared; nothing is converted |
includeUnknownSalary | boolean | Default false. When a salary filter is set, off drops jobs with no published yearly pay in that currency (including all Greenhouse jobs) |
experienceBands | string array | Keep jobs whose inferred minimum years fall in 0, 1-2, 3-4, 5-7, 8-10, or 11+ |
includeUnknownExperience | boolean | Default false. When bands are set, off drops jobs where no requirement could be read |
includeDescription | boolean | Jobs mode: add the plain-text description (larger dataset) |
maxItems | integer | Cap on charged rows (jobs, signals, and rollups together). Default 500; prefill 20. 0 = no cap. The free summary row is not counted |
maxRequestsPerMinute | integer | Global throttle. Each host is also limited to 1 request per second |
debugLog | boolean | Verbose logs |
This Actor does not take start URLs, a browser crawler, or a proxy: it is plain HTTP JSON to official APIs. robots.txt is always respected.
Example input (real public boards; this is the same set used in a local signals run whose example output is below):
{"mode": "signals","companies": ["https://job-boards.greenhouse.io/gitlab","https://jobs.lever.co/spotify","https://jobs.ashbyhq.com/linear","https://jobs.ashbyhq.com/ramp"],"tools": ["snowflake","dbt","salesforce","workday","go","looker","tableau","zendesk","C++","Node.js"],"toolAliases": {"salesforce": ["SFDC"]},"minConfidence": 0.6,"outputLevel": "both","onlyNewOrChanged": true,"stateKey": "e2e-demo","maxItems": 0}
The Store prefill (what the Try button and Apify's daily test run) uses the same four boards as the how-to-try steps — Duolingo, Spotify, Linear, and Supabase — with maxItems 20.
Output
Each dataset row has a recordType of signal, companyRollup, summary, or job. Fields the source does not provide are null; they are never invented. Recruiter and hiring-manager emails or phone numbers are stripped from snippets even if a post includes them.
A value is copied verbatim from the ATS unless the field name ends in Derived (a fixed rule) or Inferred (read from the post text, with evidence).
Signal rows use: company (a label: your display name, else the ATS company name, else companyNameDerived), companyName (ATS value; null for Lever and Ashby), source, boardToken, jobId, jobTitle, jobUrl, location, isRemote, department, postedAt, updatedAt (Greenhouse only), tool, toolName, aliasHit, snippet, section, signalType, confidence, matchCount, firstSeen, isNew, changed, reposted, contentHash, scrapedAt.
Company rollup rows use: company, source, boardToken, tools, matchingPosts, matchingPostsLastRun, trend (new, up, down, or flat), strongestSnippet, strongestConfidence, topSignalType, jobUrls (up to 5), billed, scrapedAt. billed is true when the company has at least one current signal (the $0.01 event fires); it is false on a free "down to zero" row.
Job rows (jobs mode) use different names: id, platform, companySlug, companyName, companyNameInput, companyNameDerived, companyNameSource, title, team, employmentType, workplaceType, applyUrl, compensation, description (only when includeDescription is on), sourceId, jobUrl, department, postedAt, updatedAt, scrapedAt, location, allLocations, isRemoteDerived, jobUrlNormalized, experienceYearsMinInferred, experienceBandInferred, experienceEvidenceInferred. There is no job-row field named company. companyNameDerived is filled only when the ATS gives no name (Lever, Ashby): the bundled starter-list name, else the slug in title case. companyNameSource is starter-list or slug, or null when companyNameDerived is null.
Summary rows (free, both modes; also saved as RUN_SUMMARY) include mode, runAt, boardsChecked, boardsSucceeded, boardsFailed, jobsScanned, duplicatesRemoved, jobsAfterFilters, filteredOut, httpRequests, jobsReturned, signalsCurrent, signalsNew, signalsChanged, signalsUnchangedSkipped, signalsNotPushedDueToLimit, belowMinConfidence, filteredBySignalType, companiesWithSignals, rollupsPushed, rollupsDownToZeroFree, repeatedSentencesSkipped, companiesWithRepeatedText, topCompanies, stateStore, runIndex, robots, durationSecs, signalsReposted, and scrapedAt.
Example output, signal row, from the local run of the input above:
{"recordType": "signal","company": "GitLab","companyName": "GitLab","source": "greenhouse","boardToken": "gitlab","jobId": "8883003002","jobTitle": "Director, Analytics Engineering","jobUrl": "https://job-boards.greenhouse.io/gitlab/jobs/8883003002","location": "Remote, Canada; Remote, United States","isRemote": true,"department": "Data","postedAt": "2026-10-13T14:52:13Z","updatedAt": "2026-11-06T20:25:07Z","tool": "snowflake","toolName": "Snowflake","aliasHit": "Snowflake","snippet": "Build and own company-wide data applications, from Claude-built single-page apps to apps inside BI tools, that combine Snowflake data, API calls, AI-powered deep dives, and write-back to Postgres or Snowflake","section": "responsibilities","signalType": "implementing","confidence": 0.92,"matchCount": 4,"firstSeen": "2026-11-10T03:51:07Z","isNew": true,"changed": false,"reposted": false,"contentHash": "78092c8783440c1f","scrapedAt": "2026-11-10T03:51:07Z"}
Example output, company rollup row (billed is true because the company has current signals). On Lever and Ashby, the company label uses your display name or companyNameDerived (here "Spotify" from the starter list), not the raw slug:
{"recordType": "companyRollup","company": "Spotify","source": "lever","boardToken": "spotify","tools": ["c_plus_plus","go","salesforce"],"matchingPosts": 6,"matchingPostsLastRun": 6,"trend": "flat","strongestSnippet": "You are comfortable using Salesforce to manage client relationships and sales pipelines, as well as Google Slides and Sheets to create presentations and reports.","strongestConfidence": 1.0,"topSignalType": "mention","jobUrls": ["https://jobs.lever.co/spotify/bb2c10a2-2bf8-4b21-901e-48b0e2e09cc8","https://jobs.lever.co/spotify/66184cac-4d6c-46f6-868c-bac0c184fd22","https://jobs.lever.co/spotify/1ee5dcb7-a5fe-465b-91da-d42ebab374c8","https://jobs.lever.co/spotify/47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d","https://jobs.lever.co/spotify/9f66e598-8587-4a57-8552-2cdb8672014a"],"billed": true,"scrapedAt": "2026-11-10T03:51:17Z"}
Example output, a free rollup after a later run when a company has dropped to zero signals (trend is down, billed is false — this row is not charged):
{"recordType": "companyRollup","company": "Duolingo","source": "greenhouse","boardToken": "duolingo","tools": [],"matchingPosts": 0,"matchingPostsLastRun": 1,"trend": "down","strongestSnippet": null,"strongestConfidence": null,"topSignalType": null,"jobUrls": [],"billed": false,"scrapedAt": "2026-11-10T04:14:10Z"}
Example output, job row, from a separate local jobs-mode run (Ramp on Ashby). companyName is null because Ashby does not publish one; companyNameDerived is filled from the starter list:
{"recordType": "job","id": "ashby:ramp:6a508863-352b-4f39-b299-5a3b6693605a","platform": "ashby","companySlug": "ramp","companyName": null,"companyNameInput": null,"companyNameDerived": "Ramp","companyNameSource": "starter-list","title": "Manager, Customer Activation, Mid-Market","department": "Sales","team": "CSM - Mid-Market","location": "New York, NY (HQ)","allLocations": ["New York, NY (HQ)","San Francisco, CA"],"workplaceType": "Hybrid","employmentType": "FullTime","postedAt": "2026-10-22T22:24:53Z","updatedAt": null,"applyUrl": "https://jobs.ashbyhq.com/ramp/6a508863-352b-4f39-b299-5a3b6693605a/application","jobUrl": "https://jobs.ashbyhq.com/ramp/6a508863-352b-4f39-b299-5a3b6693605a","compensation": {"min": 174000,"max": 266000,"currency": "USD","interval": "1 YEAR","summary": "$174K - $266K"},"description": null,"sourceId": "6a508863-352b-4f39-b299-5a3b6693605a","isRemoteDerived": false,"jobUrlNormalized": "https://jobs.ashbyhq.com/ramp/6a508863-352b-4f39-b299-5a3b6693605a","experienceYearsMinInferred": 5,"experienceBandInferred": "5-7","experienceEvidenceInferred": "5+ years of implementation, CSM or AM experience as an individual contributor, with a proven, consistent track record exceeding goals","scrapedAt": "2026-11-10T04:09:59Z"}
How much will a run cost?
This Actor uses pay-per-event pricing. You pay for the events below, not for a separate platform-usage line (except in Standby mode, where Apify always adds usage). Plan-tier (Silver/Gold) discounts are not set.
| Event | When it fires | Price |
|---|---|---|
apify-actor-start | Each run | $0.00005 (Apify's default) |
signal-found (primary) | Each charged signal row | $0.003 |
company-rollup | Each companyRollup row for a company with at least one current signal (billed: true) | $0.01 |
job-returned | Each charged job row in jobs mode | $0.001 |
These items are not charged: the summary row; jobs that were scanned but did not match; signals dropped under minConfidence; and rollup rows where a company dropped to 0 signals (trend: "down", billed: false). maxItems is enforced before charging, so a test with maxItems: 20 cannot bill more than 20 result events of the mode you ran.
Formula:
run cost = (start events × $0.00005)+ (charged signal rows × $0.003)+ (billed rollup rows × $0.01)+ (charged job rows × $0.001)
Worked examples (one start event per run):
- 1,000 jobs in jobs mode (set
maxItemsto 1000 or 0; the default cap is 500):(1 × $0.00005) + (1,000 × $0.001) = $1.00005(about $1.00, or $1.00 per 1,000 jobs plus the start fee). - 50 hiring signals and 10 billed company rollups in signals mode (companies with at least one signal):
(1 × $0.00005) + (50 × $0.003) + (10 × $0.01) = $0.25005(about $0.25). Freebilled: falserollups do not add to this total. - Both in one week (a 1,000-job run plus that signals run):
$1.00005 + $0.25005 = $1.25010(about $1.25).
The two modes are separate runs, so each has its own start event. Scanned but unmatched jobs in signals mode are free.
Default memory is 512 MB. For lists of 50 or more boards, we recommend setting memory to 1024 MB.
Apify free-plan users can run the Actor; we do not earn from free-plan runs, and any free-result cap we add later will be stated here and in the input schema. Prices go live only when the Actor is published.
Limitations
- Sources: Greenhouse, Lever, and Ashby public job-board APIs only. Lever EU (
lever_eu, jobs.eu.lever.co) is supported in code but untested against a live EU board. Workday, Indeed, LinkedIn, and HTML career pages are out of scope. - You need board tokens or discovery: the Actor does not ship a global index of every company. Discovery only tries official slug patterns and will miss unusual tokens.
- Lever and Ashby do not provide a company name.
companyNameis null on those boards. Jobs mode fillscompanyNameDerivedfrom the bundled starter list, or from the slug in title case, and setscompanyNameSourceaccordingly. On signal and rollup rows, thecompanylabel uses your display name, else the ATS company name, elsecompanyNameDerived. - Salary filtering works only with pay that Lever and Ashby publish (Lever
salaryRange, Ashbycompensation). Greenhouse job lists carry no pay, so Greenhouse jobs count as unknown salary and are dropped when a salary filter is on unless you setincludeUnknownSalaryto true. Currencies are not converted. - Matching is heuristic: ambiguous names (for example "Go", "Notion", "Monday") need context words; benefits, EEO, and legal sections are ignored; negation such as "no Salesforce experience needed" is dropped. Expect some false positives and false negatives. Confidence is a rule-based score, not a guarantee.
- Experience bands are inferred from the post text, not a field the ATS always publishes.
includeUnknownExperiencecontrols what happens when nothing can be read. - No invented fields and no applicant data. If a board omits salary, department, or a posting date, the field is
null. - Rate limits and terms: the Actor throttles requests and backs off on 429/5xx. Re-check each provider's API terms before you rely on a large schedule. You are responsible for how you use the output (for example outreach laws).
FAQ
How is this different from a large job-index Actor? Those products search a pre-built database of many career sites. This Actor fetches the boards you specify (or discover) live from official APIs, applies your filters to the current posts, and — in hiring-signal mode, which is the default — returns a snippet and a signal type for a named tool. It does not claim broader coverage or a larger company catalog.
Do I need API keys? No. The official Greenhouse, Lever, and Ashby job-board endpoints used here are unauthenticated.
Can I run it every week and only see new matches? Yes, if you set onlyNewOrChanged (on by default) and a stable stateKey. The first run treats matching posts in the lookback window as new, up to maxItems.
What does a confidence score mean? It combines how specific the alias was, which section of the post it appeared in, the signal type, and whether more than one sentence mentions the tool. Rows under minConfidence are omitted and not billed.
Is this legal? The Actor is designed to call documented public job-board APIs, not to log in, bypass bot checks, or scrape disallowed paths. That is not legal advice. Read the provider terms and your own use case. We are not affiliated with the ATS vendors.
Where do I get help? Open an issue on this Actor's Issues tab in Apify. We aim to address issues within 14 days.