Hiring Signals API - Companies Hiring Now by Role
Pricing
from $11.00 / 1,000 company profiles
Hiring Signals API - Companies Hiring Now by Role
Hiring signals API for sales and recruiting prospecting. Give a company and get a hiring-activity score back, built from its live open roles, so you can find accounts actively hiring for a given function and use that activity as a buying-intent or prospecting signal.
Pricing
from $11.00 / 1,000 company profiles
Rating
0.0
(0)
Developer
Khandji Omar
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Find companies actively hiring for a role and use that hiring activity as a sales or prospecting signal. "These 12 accounts just posted their first sales role."
Paste your target list. Get back the short list that changed, scored 0-100, with the reason for every point. 5 companies free on every run.
Every other jobs Actor on this Store sells you rows. This one sells you the event: who started hiring, who opened an office, who hired their first VP, who froze. That is the thing a revenue team acts on.
The change events
Run it once to set a baseline. Every run after that reports what moved:
| Trigger | What it means | Score |
|---|---|---|
first_sales_hire | Sales roles appear where there were none — the company decided to go to market | +30 |
started_hiring | Was dormant, now hiring | +25 |
exec_hire | A VP, Head of, Director or C-level title appears | +20 |
hiring_accelerating | Posting at least 50% faster than last run | +20 |
new_location | A city that was not there before — an office opening | +15 |
scaling_fast | 10+ roles opened in 30 days and not slowing | +15 |
first_engineering_hire | Engineering roles appear where there were none | +10 |
hiring_decelerating | Posting at least 50% slower | −15 |
hiring_freeze | Was hiring, now zero open roles | −30 |
A real run, on vercel.com:
{"domain": "vercel.com","intent_score": 100,"triggers": ["first_sales_hire", "new_location", "hiring_accelerating", "scaling_fast"],"roles_delta": 40,"roles_delta_pct": 100.0,"velocity_delta": 299.4,"new_functions": ["Sales"],"new_locations": ["Hybrid - London", "Remote - United States"],"intent_reasons": {"first_sales_hire": 30, "recent_activity": 25, "hiring_accelerating": 20,"new_location": 15, "scaling_fast": 15, "hiring_sales": 10,"open_roles": 8, "hiring_engineering": 5},"signal_summary": "Just posted its first sales role; opened a new location; hiring pace is accelerating."}
intent_reasons is not decoration. A score your sales team cannot explain is
a score they will not act on, so every point is attributed to a named component
and the score is their sum, capped at 100 (the Vercel example adds up to 128, so it shows 100). signal_summary is the same reasons in
one plain-English sentence — the line a rep reads without decoding
intent_reasons themselves.
Set Only companies that changed to get just the short list, and Minimum intent score to raise the bar.
Three things this Actor refuses to fake
The first run invents nothing. No history means every company comes back as
is_new with an empty triggers list. Telling a sales team that 200 accounts
all started hiring on the day they first ran it would destroy the product's
credibility in one run.
A new city only counts as an office opening if the company was already hiring. A company going from zero roles to its first roles has "new" locations by definition. That is not an expansion, and calling it one would be a lie.
A company we cannot date is unknown, not zero. Some ATS providers publish no
timestamps, so roles_posted_30d comes back null rather than 0 and no
velocity trigger fires. Reporting a hiring company as dormant is a false
negative you would act on.
The problem this solves
A company's hiring is the cleanest public signal of what it is doing. A team that opened nine engineering roles this month is building something. A company that just posted its first three sales roles has decided to go to market — the classic buying trigger.
That signal is already public, in every company's applicant tracking system. It is just spread across nine different systems, none of which you can query without first knowing which one a given company uses.
You give a domain. This Actor does the rest.
Why use it: not another job scraper
If you want the jobs themselves, use the ATS Jobs API - Greenhouse, Lever, Ashby, Workday Jobs — same data, one row per opening, $0.002 each.
This Actor is for the other question. Prospecting 500 accounts through a job scraper means 40,000 rows you have to aggregate yourself. Here it is 500 rows, already aggregated, already ranked.
What one row looks like
{"domain": "stripe.com","ats": "greenhouse","is_hiring": true,"total_open_roles": 545,"roles_posted_7d": 31,"roles_posted_30d": 118,"roles_posted_90d": 402,"roles_per_week_30d": 29.5,"latest_posting": "2026-08-03","by_function": {"Engineering": 210, "Sales": 96, "Other": 239},"by_seniority": {"Senior": 288, "Mid": 190, "Junior": 67},"top_locations": {"New York": 88, "Remote - US": 74, "Dublin": 51},"top_titles": {"Account Executive": 9, "Software Engineer": 8},"hiring_engineering": true,"hiring_sales": true,"hiring_marketing": true,"hiring_support": false,"checked_at": "2026-08-04"}
| Field | What it holds |
|---|---|
domain | the company you asked about |
ats | which system it publishes from, or null if it runs its own careers page |
is_hiring | whether any role is currently open |
total_open_roles | every open role right now |
roles_posted_7d / 30d / 90d | how many opened in that window |
roles_per_week_30d | hiring velocity — what the ranking sorts on |
by_function / by_seniority | the shape of the hiring |
top_locations / top_titles | where, and for what |
hiring_engineering / _sales / _marketing / _support | quick booleans to filter on |
latest_posting | date of the most recent opening |
Two things this Actor refuses to fake
A company we cannot date is reported as unknown, not as zero. Some ATS
providers publish no timestamps. Reporting roles_posted_30d: 0 for them would
mark a company that is actively hiring as dormant — a false negative you would
act on. Those companies come back with null and dated_roles: 0, and the
ranking places them below companies we could actually measure rather than
dropping them.
A company with no public ATS still gets a row. is_hiring: false,
ats: null. For a prospecting list, "we looked and they publish nothing" is a
usable answer; a missing row just looks like the lookup failed.
Free tier — 5 companies on every run
The first 5 companies of every run are free, on every run you ever make, not just the first. Point it at your own target list and see the real output before a cent is billed.
The free allowance never covers more than half of a run, so a run of 6 companies gets 3 free rather than 5 — that is what stops it becoming an unlimited free plan for anyone willing to split one list into many tiny runs.
Pricing — $0.02 per company looked up
You are billed per company checked, not per row returned. If you scan 200 companies and ask for only those that changed, you may get 12 rows back, and you pay for the 200 lookups that produced them.
That is deliberate and it is the honest way round. The lookup is the work: we resolve the ATS, read the board and compare it to last run whether or not the answer turns out to be interesting. Billing per returned row would mean charging you nothing for a scan that correctly told you "none of your accounts moved this week" — which is a useful answer, and one you would stop trusting if we had an incentive to invent movement.
Companies that turn out not to be hiring are billed for the same reason: the negatives are only worth having because we actually looked.
Set Maximum charge (USD) to cap any single run.
Where the data comes from
Each company's own applicant tracking system, through the public endpoint that system already publishes: Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Rippling, Breezy HR, Personio, BambooHR, Recruitee, Teamtailor, Workable, Jobvite, Pinpoint, Gem, JOIN, Homerun, HireHive, Manatal, Dover, Avature, PageUp, Zoho Recruit, Oracle Recruiting Cloud, Eightfold, JazzHR, Comeet, iCIMS, Trakstar Hire, UKG UltiPro, Paylocity, ApplicantPro, iSolved Hire, Hireology, HiBob, HiringThing, Cornerstone, softgarden, Factorial.
No cookies, no logins, no proxies, no third-party aggregator. Nothing here can be blocked, because none of it is scraping — it is the employers' own public job feeds, read as published.
Limits
- 200 companies per run. Each one costs at least two HTTP round trips.
- 25 companies per request in HTTP mode, so a request finishes inside Apify's five-minute ceiling.
- Velocity is computed over dated roles only.
Questions
Which companies are hiring right now?
Pass your target list and read is_hiring and roles_posted_30d. Companies with
no public applicant tracking system come back with ats: null and
is_hiring: false rather than being dropped, so a prospecting list stays the
length you gave it.
How do I turn hiring data into a sales trigger?
Run it on a schedule against the same list. From the second run on, triggers
carries the events — first_sales_hire, started_hiring, new_location,
exec_hire, hiring_accelerating. Set Only companies that changed and you
get just the accounts worth a call this week.
Can I use this for ICP scoring?
Yes, and the score is meant to be argued with. intent_score is 0-100 and
intent_reasons breaks out every point by name, so you can drop the components
you disagree with and re-score on the raw fields — open roles, roles posted in
7/30/90 days, roles per week, functions, locations, titles.
What is a hiring signal worth as buying intent?
A company posting its first sales role has decided to go to market. One opening an office in a new city has budget. One that just hired a VP has a new decision maker. Those are the three events this Actor weights highest, and they are public information every company publishes itself.
How is this different from a job scraper?
A job scraper gives you rows. Scanning 500 accounts through one means 40,000 job rows you have to aggregate yourself. This returns 500 rows, one per company, already aggregated and ranked — or just the dozen that changed.
Does it work without a list of companies?
No. This Actor scores companies you name. If you want to discover jobs rather than score accounts, use the ATS Jobs API - Greenhouse, Lever, Ashby, Workday Jobs.
How fresh is the data?
It is read live from each company's own applicant tracking system at the moment you run it — not from an index built earlier. 25 companies answer in about 25 seconds.
Use it from an AI agent (MCP and x402)
Connect Claude Desktop, Cursor, VS Code or any MCP client to Apify's MCP server
at https://mcp.apify.com and add this Actor, om_kh/company-hiring-signals, as a tool — the
agent passes the same JSON as the run input and gets the dataset back.
AI agents that pay with x402 can run it too, without an Apify account: the Actor charges only per result delivered, so an agent pays exactly for what it gets.
Related tools
- Want the raw current job listings behind the signal? → Company Careers Page Scraper - Jobs from Any Career Site
- Want LinkedIn's own job listings as a second source? → LinkedIn Jobs Scraper - Listings, Companies, Location Data
All input fields
Every field the Start form accepts, so nothing in the schema is undocumented. Most runs only need the fields already covered above — these are the rest, including advanced/bring-your-own-data options.
companyDomains(Company websites) — The companies to score. Just the domain - stripe.com, figma.com. Companies with no public ATS still get a row saying so. Max 200 per run.minIntentScore(Minimum intent score) — Drop companies scoring below this (0-100). Every score comes with the reasons that produced it, so you can justify the cut-off.onlyTriggers(Only companies that changed) — Return only companies with at least one change event since your last run - first sales hire, started hiring, new location, accelerating, executive hire. This is the short list a sales team works from. You are still charged per company looked up, because the lookup is the work.trackChanges(Track changes between runs) — Remember this run so the next one can report what changed. The first run on a list is a baseline: every company is reported as new, with no change events invented.
How to use it in 3 steps
- Click Try for free and fill in Company websites (
companyDomains). - Optional: adjust the other fields; every one has a description and a sensible default.
- Click Start and download the results as JSON, CSV or Excel, or read them from the API.
What data do you get?
Each result contains structured records.
Use it from code (API)
Every Apify Actor is an API. Start a run and read the results with one call.
Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("om_kh/company-hiring-signals").call(run_input={"companyDomains": ["stripe.com", "figma.com", "ramp.com", "notion.so"], "onlyTriggers": False, "minIntentScore": 0, "trackChanges": True})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('om_kh/company-hiring-signals').call({"companyDomains": ["stripe.com","figma.com","ramp.com","notion.so"],"onlyTriggers": false,"minIntentScore": 0,"trackChanges": true});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
One HTTP call (cURL) — runs the Actor and returns the dataset in the same response:
curl -X POST "https://api.apify.com/v2/acts/om_kh~company-hiring-signals/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H "Content-Type: application/json" \-d '{"companyDomains": ["stripe.com", "figma.com", "ramp.com", "notion.so"], "onlyTriggers": false, "minIntentScore": 0, "trackChanges": true}'
Integrations: n8n, Make, Zapier, Google Sheets
- n8n — the official Apify node, operation Run Actor and get dataset, Actor
om_kh/company-hiring-signals. - Make — Apify › Run an Actor, then Apify › Get Dataset Items.
- Zapier — Apify › Run Actor; map the dataset items into your next step.
- Google Sheets, webhooks, Slack — add an integration from the Integrations tab of this Actor.
- Schedules — run it every hour or day from Schedules in Apify Console.
FAQ
Is it legal to collect these hiring signals? This Actor reads only public job boards (company career pages on Greenhouse, Lever, Ashby and other ATS) and never logs in. You are responsible for how you use it; check each job board's terms and your local law (GDPR, CCPA) if you store personal data, and ask a lawyer if unsure.
Do I need an account, cookies or an API key? No. You only need an Apify account to run it.
What data do I get? Structured records. Download it as JSON, CSV, Excel, HTML or XML, or read it from the API.
Am I charged when something fails? No. An input that fails is listed with its reason in the run summary and is never charged.
Can I run it on a schedule? Yes. Create a schedule in Apify Console (hourly, daily, weekly) and connect webhooks, Google Sheets, Slack, n8n, Make or Zapier.
Can I use it from Python, JavaScript or an AI agent?
Yes: see the code samples above, or connect AI agents through MCP with the company_hiring_signals tool.
Your feedback
Did this Actor save you time? A short review on the Reviews tab helps other people find it, and every review is read. Something missing or broken? Open an issue on the Issues tab: it is answered and fixed fast.