Job Board Hiring Signals: Greenhouse, Lever, Ashby avatar

Job Board Hiring Signals: Greenhouse, Lever, Ashby

Pricing

from $3.00 / 1,000 hiring signals

Go to Apify Store
Job Board Hiring Signals: Greenhouse, Lever, Ashby

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

Will Emery

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

17 hours ago

Last modified

Features

Limited permissions

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 stateKey so 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

  1. Open this Actor in Apify Console. A free Apify account is enough to run the prefill.
  2. Leave the prefilled input: mode is signals (the default), boards is Duolingo (greenhouse / duolingo), Spotify (lever / spotify), Linear (ashby / linear), and Supabase (ashby / supabase), tools includes snowflake, dbt, salesforce, workday, and go, and maxItems is 20. These are verified public boards. This run takes about 10–12 seconds on Apify and writes signal and rollup rows.
  3. Click Start and wait for a Succeeded run.
  4. 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).
  5. 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.

FieldTypeWhat it does
modesignals or jobsDefault is signals (hiring-signal mode). jobs is the plain feed
boardsarray 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
companiesstring or object arrayBoard 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
platformstringDefault auto: try Greenhouse, then Lever, then Ashby, and use the first board that exists (up to 3 requests per slug)
discoveryobject{enabled, companyNames[], maxProbesPerCompany}. Builds slug guesses and probes only official board APIs; 404s are skipped. Default is off, 6 probes
toolsstring arraySignals mode. Built-in ids (for example salesforce, snowflake, dbt) or any other name, matched as written
toolAliasesobjectExtra aliases, or {"contextRequired": false} to relax context checks for ambiguous names
requireAllToolsbooleanWhen true, a post must match every listed tool
signalTypesstring arrayEmpty = all. Options: replacing, migrating_from, migrating_to, implementing, experience_with, nice_to_have, mention
minConfidencenumber 0–1Signals below this are dropped and not charged (default 0.6)
outputLevelsignals, rollups, or bothWhich charged rows to write in signals mode. Default both. A free summary row is always added
onlyNewOrChangedbooleanDefault 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)
stateKeystringNames the persistent store hiring-signals-state-{stateKey}
includeSelfPostingsbooleanDefault false. Off drops hits where the employer is the tool's own vendor
removeRepeatedTextbooleanSignals 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
keywordsstring arrayCase-insensitive whole-word phrases, in order and adjacent
keywordsModeany or allDefault any
keywordsInstringWhere keywords and exclude keywords are looked for. Default title_or_description
excludeKeywordsstring arrayDrop a job if any of these phrases is found
locationsstring arrayCase-insensitive substring of any location string as the ATS gives it. Remote also matches when isRemoteDerived is true
remotestringDefault any. Uses isRemoteDerived. Hybrid alone is not remote
departmentsstring arrayCase-insensitive substring on department or team
lookbackDaysintegerUses updatedAt, falling back to postedAt. Empty = 30 in signals mode, no limit in jobs mode. 0 = no limit. Jobs with no date are kept
postedAfterstringKeep 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
postedBeforestringKeep jobs whose postedAt is before this date
salaryMinintegerKeep jobs whose published yearly pay range reaches at least this amount. Uses only pay Lever and Ashby publish; Greenhouse job lists carry no pay
salaryMaxintegerKeep jobs whose published yearly pay range starts at or below this amount
salaryCurrencystringDefault USD. Only pay in this currency is compared; nothing is converted
includeUnknownSalarybooleanDefault false. When a salary filter is set, off drops jobs with no published yearly pay in that currency (including all Greenhouse jobs)
experienceBandsstring arrayKeep jobs whose inferred minimum years fall in 0, 1-2, 3-4, 5-7, 8-10, or 11+
includeUnknownExperiencebooleanDefault false. When bands are set, off drops jobs where no requirement could be read
includeDescriptionbooleanJobs mode: add the plain-text description (larger dataset)
maxItemsintegerCap on charged rows (jobs, signals, and rollups together). Default 500; prefill 20. 0 = no cap. The free summary row is not counted
maxRequestsPerMinuteintegerGlobal throttle. Each host is also limited to 1 request per second
debugLogbooleanVerbose 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.

EventWhen it firesPrice
apify-actor-startEach run$0.00005 (Apify's default)
signal-found (primary)Each charged signal row$0.003
company-rollupEach companyRollup row for a company with at least one current signal (billed: true)$0.01
job-returnedEach 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 maxItems to 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). Free billed: false rollups 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. companyName is null on those boards. Jobs mode fills companyNameDerived from the bundled starter list, or from the slug in title case, and sets companyNameSource accordingly. On signal and rollup rows, the company label uses your display name, else the ATS company name, else companyNameDerived.
  • Salary filtering works only with pay that Lever and Ashby publish (Lever salaryRange, Ashby compensation). Greenhouse job lists carry no pay, so Greenhouse jobs count as unknown salary and are dropped when a salary filter is on unless you set includeUnknownSalary to 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. includeUnknownExperience controls 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.