Hiring Signals Tracker: Job Openings by Company avatar

Hiring Signals Tracker: Job Openings by Company

Pricing

from $4.00 / 1,000 company report delivereds

Go to Apify Store
Hiring Signals Tracker: Job Openings by Company

Hiring Signals Tracker: Job Openings by Company

Hiring signals tracker for company job boards on Greenhouse, Lever and Ashby: per company, the count of job openings, open roles by department and location, new job postings, roles opened and closed since the last run, and your role rules. A job board monitor: schedule it to track company hiring.

Pricing

from $4.00 / 1,000 company report delivereds

Rating

0.0

(0)

Developer

Edge

Edge

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

21 hours ago

Last modified

Share

Hiring signals tracker for company job boards on Greenhouse, Lever and Ashby: per company, the count of job openings, open roles by department and location, new job postings, roles opened and closed since the last run, and your role rules. A job board monitor: schedule it to track company hiring. Try it: run the prefilled input (GitLab on Greenhouse, Palantir on Lever, Linear on Ashby) and open the Hiring signals by company table.

What it does

Give it the job boards of the companies you follow; it returns one report per company. Each report counts open roles by department and location, applies your own role rules, and says how many roles opened and closed since the last run. It reads the public job board endpoints of Greenhouse, Lever and Ashby. It honours robots.txt and its Crawl-delay on every host it reads: when a host states a Crawl-delay, the Actor waits at least that long between two requests to that host (a value over 30 seconds is honoured as 30 seconds and noted in the run summary).

Who uses it

  • Sales teams who treat new openings in a department as a buying signal ("three new data engineering roles at this account").
  • Investors and analysts who watch hiring at a list of companies week by week.
  • Recruiters who track where competitors are hiring.

Input

FieldTypeDefaultWhat it does
boardslistrequiredBoard addresses such as https://boards.greenhouse.io/<board>, https://jobs.lever.co/<board>, https://jobs.ashbyhq.com/<board>, or objects {"platform": "lever", "slug": "<board>"}
ruleslist of objectsempty{"name": "sales", "titleKeywords": ["account executive"], "departments": ["Sales"]}: counts the open roles whose title contains a keyword as a whole word (letters and digits of any alphabet belong to a word, so rations does not match Opérations) and, when departments are given, whose department or team is one of them
deltaModetrue or falsetrueCompares with the last run that read the same board

Output

One record per company board. A board that cannot be read gives one record with status set to not_found, blocked or error. Before it reads a board, the Actor reads the robots.txt of the board's host, once per host per run. When that robots.txt does not allow this Actor, the board gives one blocked record with error set to robots_disallow. When that robots.txt cannot be read (a server error, a "too many requests" answer, a timeout, a network failure, a redirect to another site or more than five redirects), the board gives one error record with error set to robots_unreadable. A redirect of robots.txt inside the same site is followed. When a host name does not resolve, the board gives one error record with error set to name_not_resolved. In both cases nothing is read from the board, nothing is charged and nothing is remembered. A robots.txt that answers with another 4xx code, such as 404, counts as no rules. When the departments list of a Greenhouse board cannot be read (a request that still fails after three retries, or a robots.txt that disallows it), the board gives one error record with error set to departments_unreadable instead of a report with every role under unknown: not charged and not remembered. Board names are read in lower case, so boards.greenhouse.io/GitLab and boards.greenhouse.io/gitlab are one board, read and charged once. Every record keeps the board as you gave it in board_input. Sample record (SYNTHETIC: example.com data, not a real company):

{
"id": "greenhouse:examplecorp",
"platform": "greenhouse",
"company_slug": "examplecorp",
"open_roles": 42,
"new_roles_since_last_run": 3,
"closed_roles_since_last_run": 1,
"first_run": false,
"by_department": {"Engineering": 20, "Sales": 12, "Support": 10},
"by_location": [{"location": "Remote, Europe", "count": 18}, {"location": "Berlin", "count": 14}, {"location": "London", "count": 10}],
"rule_matches": [{"name": "data", "count": 4, "examples": [{"title": "Senior Data Engineer", "job_url": "https://jobs.example.com/examplecorp/101"}]}],
"new_role_examples": [{"title": "Senior Data Engineer", "job_url": "https://jobs.example.com/examplecorp/101"}],
"closed_role_examples": [{"title": "Office Manager", "job_url": null}],
"source_url": "https://api.example.com/v1/boards/examplecorp/jobs",
"fetched_at": "2026-10-07T18:00:00Z",
"status": "ok",
"error": null,
"error_detail": null
}

Sample record (REAL: the board ashby:linear of the prefilled input, read 2026-10-08T01:55:11Z on a first run with no memory, so the new and closed fields are null):

{
"id": "ashby:linear",
"platform": "ashby",
"company_slug": "linear",
"open_roles": 31,
"new_roles_since_last_run": null,
"closed_roles_since_last_run": null,
"first_run": true,
"by_department": {"GTM": 16, "Operations": 2, "Product": 13},
"by_location": [{"count": 16, "location": "North America"}, {"count": 8, "location": "Europe"}, {"count": 3, "location": "North America; Europe"}, {"count": 2, "location": "London"}, {"count": 2, "location": "Singapore"}],
"rule_matches": [{"count": 12, "examples": [{"job_url": "https://jobs.ashbyhq.com/linear/d3bc1ced-3ce4-4086-a050-555055dbb1ff", "title": "Senior / Staff Fullstack Engineer"}, {"job_url": "https://jobs.ashbyhq.com/linear/cd5ae036-0223-427a-b038-ba16ef9dcb32", "title": "Senior / Staff Fullstack Engineer"}, {"job_url": "https://jobs.ashbyhq.com/linear/069c4628-88d7-4e4d-b393-c996fc7f3076", "title": "Senior / Staff Product Engineer"}], "name": "engineering"}, {"count": 3, "examples": [{"job_url": "https://jobs.ashbyhq.com/linear/c21af93e-210f-4969-8eaa-90fb16a5b720", "title": "Account Executive, Startups"}, {"job_url": "https://jobs.ashbyhq.com/linear/cb8e77a6-4316-45c6-ac8d-7ade980cd65e", "title": "Account Executive, Growth"}, {"job_url": "https://jobs.ashbyhq.com/linear/6dd5500a-4bd4-4f57-ba09-7b07acefecf4", "title": "Account Executive, Enterprise"}], "name": "sales"}],
"new_role_examples": null,
"closed_role_examples": null,
"source_url": "https://api.ashbyhq.com/posting-api/job-board/linear?includeCompensation=true",
"fetched_at": "2026-10-08T01:55:11Z",
"status": "ok",
"error": null,
"error_detail": null
}

Field rules: on the first run for a board, first_run is true and new_roles_since_last_run and closed_roles_since_last_run are empty (null), not zero, because there is nothing to compare with. by_department uses the department a board gives, or the team when the board has no departments, or unknown. by_location lists the five most frequent location texts. Rule examples are real open roles of that board, up to three. Closed roles keep only the title the Actor remembered.

What a run costs

The price is $4.00 per 1,000 company reports, plus the platform's start fee of $0.00005 per run (charged once, because the Actor runs with at most 1 GB of memory). A run over 100 boards costs $0.40005. Boards that fail are not charged.

Limits and what it will not do

  • Three platforms in this version: Greenhouse, Lever, Ashby. Other addresses give an unsupported_board record.
  • SmartRecruiters boards are not read. The robots.txt of its API host (api.smartrecruiters.com, read 2026-10-08) allows one other agent and disallows all others, so a SmartRecruiters address gives one blocked record with error set to robots_disallow, not charged.
  • The comparison is per board: adding a board to the list does not reset the others, and a board seen for the first time starts with empty new and closed counts. Two schedules that read the same board share one comparison point, so each sees the changes since whichever of them ran last. Turning deltaMode off neither reads nor writes the memory.
  • The memory keeps, per open role, its id, title, department and the day it was first seen, in the named key-value store hiring-signals-state of your account. No posting text is kept.
  • Up to 100 pages per board; at most 2 requests per second per platform; GET requests only.
  • Each board has a time budget of 300 seconds, its robots.txt included. A board that is not read in full within it gives one error record with error set to time_budget_exceeded: what was read is dropped, not charged and not remembered, and the next board starts with its own budget.
  • It reads public job board endpoints only: no login, no cookies, no proxies, no browser. A block is reported as blocked, never worked around.
  • It identifies itself as edge-hiring-signals/0.2 in every request. A site owner can block it in robots.txt with User-agent: edge-hiring-signals and Disallow: /. It never pretends to be a browser.
  • It reports on roles, never on people.

Source and terms

Questions and answers

Why are new and closed empty on my first run? There is no earlier run to compare with. From the second run on they are numbers, zero included.

What counts as a new role? A role id the board did not list at the last run that read it. A role that is taken down and posted again under a new id counts as closed and new.

Can I count roles in one department only? Yes: add a rule with departments and no keywords, or both to narrow it.

How do I reset the comparison? Delete the key-value store hiring-signals-state in your account, or the record of one board in it.

Does it read the job descriptions? No. Titles, departments, teams, locations and links are enough for the counts.