# Hiring Signals API: Who Is Hiring, and Who Quietly Stopped (`datasignalslab/jobs-api`) Actor

Which companies opened roles this week and which quietly closed them, straight from the applicant tracking systems of 6,374 employers. 231,554 open positions and a change feed: the closings are the half a snapshot throws away. Live coverage at /jobs/v1/coverage, no key needed.

- **URL**: https://apify.com/datasignalslab/jobs-api.md
- **Developed by:** [DataSignals Lab](https://apify.com/datasignalslab) (community)
- **Categories:** Jobs, Lead generation, AI
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 job rows

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Hiring signals: who is hiring, and who quietly stopped

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.

This API reads the applicant tracking systems of 6,374 employers directly and
keeps the events underneath: every opening, every closing, in order, with a
cursor so you can poll it without duplicates or gaps.

### Why this is different

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

In the last seven days this set recorded **28,631 openings and 26,079
closings**. The closings are the part a snapshot throws away, and they are the
part that says a team froze, a budget moved, or a project shipped.

- **Straight from the source.** Eight applicant tracking systems publish a public
  JSON endpoint for their customers' career pages: Greenhouse, Lever, Ashby,
  Workable, SmartRecruiters, Teamtailor, Breezy and Rippling. No aggregator in
  between, no bot protection to work around.
- **The full description**, as the employer wrote it, on 178,740 of the 231,554
  open positions. Off by default; ask for it with `include_description=true`.
- **Every row says how long it has been open.** A role open for eleven weeks
  says something a role posted yesterday does not.
- **Cursor-based changes.** Pass back the cursor from your last response and you
  get exactly what happened after it: no duplicates, no gaps, however often you
  poll.
- **Checkable before you pay.** `/v1/health` and `/v1/coverage` need no key.

### What people use it for

- **Sales triggers.** A company hiring three DevOps engineers is buying tooling
  this quarter. Ask `/v1/signals/hiring?direction=hiring&days=7&min_change=3` and
  you get the employers who just told the world what they need, dated, biggest
  first. No aggregating a raw event stream yourself.
- **Hiring freezes.** `direction=freezing` gives the other half, and this is the
  one nobody else sells. In a week where 26,079 postings closed, the interesting
  rows are the companies that closed dozens and opened none.
- **Competitive and market intelligence.** Watch a competitor's departments open
  and close over time. A team that stops hiring is a signal months before it
  shows up anywhere else.
- **Investment and research.** Hiring is a leading indicator that is public,
  timestamped and hard to dress up. The change feed makes it measurable per
  company instead of per press release.
- **Job boards and agents.** The same set also serves the ordinary case: live
  openings with apply links, straight from the employer's own system.

### What is in it

| | |
|---|---|
| open positions | 231,554 |
| companies with an opening | 6,374 |
| largest market, United States | 110,952 |
| countries with 100 or more open roles | 35 |
| with the full description | 178,740 |
| openings and closings on record | 507,982 |
| closings in the last 7 days | 26,079 |

Measured 11 September 2026, from events recorded since 4 August 2026. Call
`/v1/coverage` for today's numbers; `/v1/health` says how fresh the set is.

### Endpoints

| endpoint | what it does | key |
|---|---|---|
| `GET /v1/health` | how fresh the set is, and how much is in it | no |
| `GET /v1/coverage` | what is in the set, per country | no |
| `GET /v1/jobs` | search by keyword, location, country, remote, company | yes |
| `GET /v1/jobs/changes` | what opened and what closed since your cursor | Pro and up |
| `GET /v1/signals/hiring` | per company: opened, closed and the net change in a 7 or 30 day window, sorted by size | Pro and up |
| `GET /v1/usage` | what you used this period | yes |

### Plans

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

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

### Honest limits

- **Not real time.** Sources are refreshed once a night. The freshest a row can
  be is last night's run, and `/v1/health` says so itself.
- **No salary fields.** They are not in the source, so they are not in the answer.
- **One country, one name.** Sources hand over the country as the employer's
  applicant tracking system wrote it, so the same place arrived under several
  spellings: `United States of America` next to `United States`, and a handful of
  rows in the employer's own language. Those are mapped to one English name on
  the way in, and a spelling we do not recognise is kept as it is rather than
  dropped. `/v1/coverage` lists every value in the set, so you can see exactly
  what you are filtering on before you pay. `Worldwide` is in that list: it is
  not a country, it is what an employer put on a fully location-independent role.
- **6,374 companies, not the whole internet.** fantastic.jobs indexes 200,000+
  and sells at roughly $1 per 1,000 jobs, 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 is the source and the change: the posting comes from
  the employer's own applicant tracking system, not from a scrape, and every
  closing is kept instead of dropped.

### About DataSignals Lab

This API is one of two subscription products from DataSignals Lab; the other one
turns official US filings into scored signals. The two share a house rule and a
front door, not a dataset.

Scored signals from SEC, FDA, Congress and other official filings. The daily output is hashed and anchored, so past signals cannot be edited. Agents call it over MCP.

Every score in every report lists the terms it was built from, so you can check the number instead of trusting it.

That second sentence is about the signal products and not about this one: job
postings are not scored here. What this API promises instead is coverage of the
change - every row carries how long it has been open, and the change feed says
what disappeared.

# Actor input Schema

## Actor input object example

```json
{}
```

# Actor output Schema

## `webInterface` (type: `string`):

Call /v1/health and /v1/coverage without a key; /v1/jobs, /v1/jobs/changes and /v1/signals/hiring return rows and are charged per row.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("datasignalslab/jobs-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("datasignalslab/jobs-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call datasignalslab/jobs-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datasignalslab/jobs-api"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Y6cAQBLXPZceYyGJI/builds/rkJd3hS30ktt1mNWJ/openapi.json
