Hiring signals: who is hiring, and who quietly stopped

Which companies opened roles and which closed them, straight from the applicant tracking systems of 6,366 employers. 240,158 open positions, a cursor-based change feed, 207,670 closings on record. Free tier, then from $45 a month on RapidAPI.

A company that opens five roles is spending money and has a problem to solve. A company that closes eleven in a week has changed its mind. Both are sales triggers, and only one of them is for sale anywhere else.

Most job APIs sell a snapshot. They tell you what is open right now, which answers half a question, and it is the half everyone already has. If a posting vanished overnight, a snapshot cannot tell you that - it can only stop mentioning it, and you find out by noticing an absence.

This API keeps the events underneath. Measured since 4 August 2026: 207,670 postings disappeared from this set. Ask for the change feed and you get them by name, with the company, the role and the moment they went.

Two endpoints need no key at all

Check the data before you pay for it. Every number on this page comes from the second one, and you can call it yourself right now:

curl https://datasignalslab.com/jobs/v1/health
curl https://datasignalslab.com/jobs/v1/coverage

What is in it

open positions 240,158
companies with an opening 6,366
remote 51,665
countries with 100 or more open roles 36
posted in the last seven days 22,865
closing events recorded 207,670

Largest markets: United States 115,414, United Kingdom 10,387, India 8,405, Canada 5,864, Germany 5,426.

Where the data comes from

Eight applicant tracking systems publish a public JSON endpoint for their customers' career pages: Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Teamtailor, Breezy and Rippling. This API reads those directly.

No aggregator in between, no bot protection to work around, and the posting is here before a job board copies it.

Hiring signals: the answer, not the stream

A stream of events is not something anyone buys. /v1/signals/hiring adds the events up per company, so the question you actually have gets an answer:

curl -H "X-RapidAPI-Key: YOUR_KEY" \
     -H "X-RapidAPI-Host: datasignals-jobs.p.rapidapi.com" \
     "https://datasignals-jobs.p.rapidapi.com/v1/signals/hiring?direction=freezing&days=7&min_change=5"
{
  "signals": [
    { "company": "ardentmc", "signal": "freezing", "opened": 2, "closed": 71,
      "net": -69, "open_now": 14, "window_days": 7 },
    { "company": "includedhealth", "signal": "freezing", "opened": 4, "closed": 67,
      "net": -63, "open_now": 85, "window_days": 7 }
  ],
  "window_days": 7, "direction": "freezing", "min_change": 5
}

Two companies that stopped hiring, with a date on it. Ask for direction=hiring and you get the other half: employers who just opened budget. Filter by country, widen the window to 30 days, or lower min_change to catch smaller moves. Part of Pro and up, because it is built on the change feed.

The change feed

/v1/jobs/changes is cursor-based. You pass back the cursor from your last response and you get exactly what happened after it: no duplicates, no gaps, however often you poll.

curl -H "X-RapidAPI-Key: YOUR_KEY" \
     -H "X-RapidAPI-Host: datasignals-jobs.p.rapidapi.com" \
     "https://datasignals-jobs.p.rapidapi.com/v1/jobs/changes?since=196700&limit=2"
{
  "changes": [
    { "cursor": 196701, "change": "opened", "company": "zscaler",
      "title": "Principal Software Development Engineer",
      "country": "India", "posted_at": "2026-08-11T09:14:02Z" },
    { "cursor": 196702, "change": "closed", "company": "acme",
      "title": "Senior Data Engineer", "country": "Germany" }
  ],
  "cursor": 196702,
  "has_more": true
}

Every row in a search result carries open_since. That is what a snapshot cannot give you: a role open for eleven weeks says something a role posted yesterday does not.

The full job description

Every row can carry the job description as the employer wrote it. It is off by default and comes back with include_description=true, because a description runs to a few thousand characters and a page of a hundred jobs would otherwise be megabytes for someone who only wanted titles.

Present on 183,533 of the 240,158 open positions - 76 percent. The rest are employers whose applicant tracking system publishes no description in the feed.

curl -H "X-RapidAPI-Key: YOUR_KEY" \
     -H "X-RapidAPI-Host: datasignals-jobs.p.rapidapi.com" \
     "https://datasignals-jobs.p.rapidapi.com/v1/jobs?q=data+engineer&include_description=true"

Who this is for

  • Job boards that need to keep their own set clean. A stale posting costs you a candidate and a complaint; the change feed tells you which ones to pull.
  • Recruiters and sourcers who want the posting before an aggregator copies it.
  • Growth analysts who want to see a company stop hiring before it is in the news.
  • AI agents that need structured openings instead of scraped HTML.

Pricing

Sold through RapidAPI. Counted in rows returned, not calls: a call that returns a hundred jobs is not the same as one that returns three.

plan price rows / month change feed
Basic free 250 no, and delayed 24 hours
Pro $45 10,000 yes
Ultra $95 25,000 yes
Mega $199 75,000 yes

Subscribe on RapidAPI

Honest limits

Not real time. Sources are refreshed once a night, so the freshest a row can be is last night's run. /v1/health says so itself, and you can check it.

No salary fields. They are not in the source, so they are not in the answer.

The first call after a quiet period takes a moment. The API scales to zero when nobody is calling it. The first request wakes it up, which takes about fifteen seconds; you get a clear starting_up answer with a Retry-After header instead of a silent hang, and the retry succeeds. Nothing is counted against your quota. Once awake it stays warm for a few minutes, and answers in well under a second. /v1/health is the one exception: while the API wakes up it answers from last night's snapshot with "api": "starting", so a monitor never sees a bare 503 there.

6,366 companies, not the whole internet. fantastic.jobs indexes 200,000+ and also sells expired-job and modified-job endpoints, with AI-enriched fields and company data this API does not have. If you need breadth or enrichment, buy theirs. What this one gives you that an aggregator cannot: the posting comes from the employer's own applicant tracking system, not from a scrape of LinkedIn, so it is here before an aggregator copies it and it says what the employer actually published.

FAQ

How is this different from a job scraper?

A scraper reads an aggregator such as LinkedIn or Indeed, a day or two late and behind bot protection. This reads the applicant tracking system the employer already publishes for their own career page, and it keeps the history of what disappeared.

What does "cursor-based" mean in practice?

Every event gets a number that only goes up. You store the last number you saw and send it back next time. You cannot get the same row twice and you cannot skip one, however often or rarely you poll.

Can I check the data before subscribing?

Yes. `/v1/health` and `/v1/coverage` need no key at all. Every figure on this page came from `/v1/coverage`.

How fresh is it?

One refresh per night. `/v1/health` reports the exact age of the newest observation, so you never have to take our word for it.

Do you have salary data?

No. The applicant tracking systems do not publish it in the feed, so inventing it would mean guessing. jobs, job change feed, closed job postings, hiring data API, remote jobs API, job board data feed, recruitment data API