# ATS Jobs Monitor — Change Tracking + Hiring Signal Score (`goldenrod_serrano/ats-hiring-signals`) Actor

Pull every open job from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee boards by company slug or careers URL. Normalized fields, salary, new-since-last-run diff and a per-company hiring-signal score. Optional change tracking and an explainable 0–100 signal score.

- **URL**: https://apify.com/goldenrod_serrano/ats-hiring-signals.md
- **Developed by:** [Paopao Studio](https://apify.com/goldenrod_serrano) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 jobs

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## ATS Jobs Monitor for Recruiter BD — Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee

Get **every open job** from a company's job board, plus a **hiring-signal summary**, in one run, across **6 applicant tracking systems**:

| ATS | What you can paste |
|---|---|
| Greenhouse | `boards.greenhouse.io/stripe`, `job-boards.greenhouse.io/anthropic`, `greenhouse:stripe` |
| Lever | `jobs.lever.co/palantir`, `lever:palantir` |
| Ashby | `jobs.ashbyhq.com/ramp`, `ashby:ramp` |
| Workable | `apply.workable.com/huggingface`, `workable:huggingface` |
| SmartRecruiters | `jobs.smartrecruiters.com/Ubisoft2`, `smartrecruiters:Ubisoft2` |
| Recruitee | `bunq.recruitee.com`, `recruitee:bunq` |

You don't need to know the ATS. Paste a **bare slug** (`ramp`) and the Actor tries all six, keeping the board with the most open jobs. You can also paste a **company careers page** (`https://www.anthropic.com/careers`). The Actor finds the embedded board, and if the page is JS-rendered it falls back to the domain name.

Every row carries `match_confidence`. It is `exact` when you gave an ATS URL or `ats:slug`, and `guessed` for a bare slug or domain fallback. A bare slug can collide with another company that has the same slug on a different ATS (for example `clay` or `gong`), so use `ats:slug` or the board URL for accounts that matter. Empty boards are ignored while guessing.

**No login, no cookies, no proxies.** It reads only the public job-board endpoints that each ATS publishes so companies can show their jobs on their own sites. That makes runs fast (a few seconds for dozens of companies) and cheap.

### What's new: change tracking and signal scoring

Two optional switches (both **off by default**):

1. **Change tracking** (`changeTracking`) + **State key** (`stateKey`) — schedule the Actor and get only what changed since the last run with the same key: new jobs, changed fields (title, location, …) and free closed-job notices. First run is a baseline.
2. **Signal scoring** (`signalScoring`) — adds an explainable 0–100 `signal_score`, a hot/warm/cool/cold tier and plain-English `score_reasons` on each company summary.

**Baseline tip.** With change tracking on, *Max jobs per company* only limits how many rows a run outputs. Every scanned job is saved as seen, so capped-out jobs are **not** sent or charged on a later run. If you need every matching job as the baseline, set *Max jobs per company* to **0** (no limit) on the first run. Only rows stopped by your max charge per run are carried over.

Details: [Change tracking](#change-tracking-new-changed-and-closed-jobs-optional) · [Signal score](#explainable-signal-score-optional).

### Who uses this

- **Recruiters and staffing-agency BD (primary).** Watch 100–500 target companies without relying on slow LinkedIn alerts. Deduped rows, long-open / repost flags, and "JD names an internal recruiter" help you pick where to pitch. Attach `company_domain` for outreach sequences.
- **Sales and lead generation.** A company that opens 10 sales roles this month has budget. Run a list of target accounts weekly and sort by `hiring_signal_score` or `posted_last_30_days`.
- **Job boards and aggregators.** Normalized fields across 6 ATS, with salary where the ATS exposes it (Ashby and Lever often do).
- **Job seekers and researchers.** Filter by keywords, location, remote, department and recency.

### Output

**Job rows** (`type: "job"`): `company_name, company_domain, title, seniority, department, team, location, country, remote, workplace_type, work_model, employment_type, posted_at, updated_at, days_open, is_long_open, is_repost, fingerprint, names_internal_recruiter, recruiter_contact, duplicate_count, duplicate_urls, url, apply_url, salary_*, description (optional), ats, company_slug, is_new`

**Company summary rows** (`type: "company_summary"`): `company_domain, total_open_jobs, matched_jobs, new_jobs_since_last_run, closed_jobs_since_last_run, closed_job_ids, net_change_since_last_run, long_open_jobs, repost_jobs_in_output, jobs_naming_recruiter, posted_last_7_days, posted_last_30_days, remote_share, seniority_mix, work_model_mix, top_departments, top_locations, sample_matched_titles, hiring_signal_score (0-100), checked_at`

**Error rows** (`type: "error"`, never charged): an input where no public board was found.

#### Seniority and work model on every row

- `seniority` is one of `intern, entry, mid, senior, lead, manager, director, executive`, inferred from the title with transparent rules (e.g. "Sr." → senior, "Staff/Principal/Architect" → lead, "Head of" → director, "VP/Chief" → executive). "Product/Account/Program/Project Manager" count as `mid` because they are usually not people managers. It's a rule, not AI, so it is fast, free and repeatable; check edge cases before relying on it.
- `work_model` is `remote`, `hybrid`, `onsite`, or `null` when the board doesn't say. It comes from the ATS workplace flag (Lever, Ashby, SmartRecruiters) or the location text.
- Filter with **Seniority levels** (e.g. `senior, lead, director`) and **Work model** (e.g. `remote, hybrid`). You pay only for rows that pass the filters.

Example (real run, Oct 29 2026):

```json
{"type":"job","company_name":"ramp","title":"Machine Learning Engineer","department":"Data","location":"New York, NY (HQ)","salary_text":"$200K – $330K • Offers Equity","ats":"ashby","url":"https://jobs.ashbyhq.com/ramp/..."}
{"type":"company_summary","company_name":"Stripe","ats":"greenhouse","total_open_jobs":724,"posted_last_30_days":235,"hiring_signal_score":92}
```

### Built for recruiter BD (what buyers asked for)

Public demand from recruitment-agency BD threads (e.g. r/RecruitmentAgencies) and GTM engineers who want a daily company + job + domain feed (r/gtmengineering). Competitors already ship monitor mode (panda_studio, webdata_labs) and composite dedupe keys (bovi, fantastic-jobs). This Actor adds the BD-specific flags in one schema:

1. **Cross-post dedupe.** Every row gets a `fingerprint` (normalized company + title + location). With *Merge duplicate jobs* on (default), the run keeps one row per fingerprint and sets `duplicate_count` / `duplicate_urls` on the keeper — so one role across several boards stops looking like eleven.
2. **Long-open and repost flags.** `days_open` and `is_long_open` (default threshold 30 days, configurable). In monitor mode, a new ATS id whose fingerprint matches a role that just disappeared is marked `is_repost: true` — the classic "they've been trying to fill this" entry point for agencies.
3. **JD names an internal recruiter.** When *Include description* is on, we look for labeled contacts (`Recruiter: Jane Doe`), "reach out to Name", or a non-generic mailto. Sets `names_internal_recruiter`, `recruiter_contact`, `recruiter_signal`. No description → fields stay `null` (we never guess). A named internal recruiter is a hint the company may already have TA coverage.
4. **Company domain.** `company_domain` comes from a non-ATS careers URL you pasted (e.g. `https://www.anthropic.com/careers` → `anthropic.com`) or from `companyDomainMap`. We never invent `stripe.com` from the slug `stripe`.

### For investors and equity research (alternative data)

Job postings are one of the most-used alternative datasets on the buy side: in Exabel's 2026 buy-side survey, 57% of fund managers named employment data as the category most likely to give an informational edge.
This Actor gives you the raw, first-party version of that signal at pay-per-event prices:

- **`ticker`, `cik`, `sec_title`** on every company summary (and `ticker` on every job), matched against SEC's public `company_tickers.json`. Matching is conservative: exact normalized name only; ambiguous or private companies stay `null`. Use `tickerMap` to set your own mapping.
- **Monitor mode** gives new jobs, closed jobs and net change per run - schedule it daily to build your own point-in-time hiring series for a watchlist.
- Typical uses: hiring momentum vs. peers before earnings, expansion into new countries (e.g. GCC hiring), AI/engineering hiring mix, hiring freezes (net change turning negative).

Data comes only from employers' own public career sites. No personal data about candidates is collected. Not investment advice.

### Monitor mode (only new jobs)

Turn on **Only new jobs since last run** and schedule the Actor (daily or weekly). Job IDs are stored per company in the named key-value store `ats-hiring-signals-state` under your **Monitor state key**. Later runs output, and charge for, only jobs that weren't there before. New jobs cut by *Max jobs per company* are kept for the next run.

From the second run on, each company summary also tells you what **closed**: `closed_jobs_since_last_run` (jobs that disappeared from the board since the previous run, i.e. filled or pulled), up to 50 `closed_job_ids`, and `net_change_since_last_run` (new minus closed). A board that is growing fast is a stronger buying signal than one that is just reposting. Closed counts are free (they live in the summary row) and are skipped when a board listing may be truncated (SmartRecruiters boards above 2,000 jobs). Connect the dataset to Slack, Google Sheets, n8n, Make or Zapier through Apify integrations.

### Hiring-signal score

Every company summary has `hiring_signal_score` (0-100), which adds three parts:

- volume (up to 40, from the number of open jobs)
- freshness (up to 40, from jobs posted in the last 7 and 30 days)
- relevance (up to 20, from jobs matching your filters)

It is a ranking aid, not a prediction.

### Change tracking: new, changed and closed jobs (optional)

Turn on **Change tracking** (`changeTracking: true`) and schedule the Actor. The first run is a baseline: every matching job is output as `change_type: "new"`. Later runs output only:

- **new** jobs (`change_type: "new"`, charged as a normal job row)
- **changed** jobs (`change_type: "changed"`, charged as a job row). A job counts as changed when its title, location, department, team, work model, employment type or salary changed. `changed_fields` lists what changed and `previous_values` holds the old values.
- **closed** jobs (`type: "job_closed"`, `change_type: "closed"`, **free**). These are jobs you got before that are gone from the board now.

State is kept per company in the named key-value store `ats-hiring-signals-state` under your **Monitor state key**. If a scan is incomplete (a SmartRecruiters board above 2,000 jobs), the new results are merged into the saved state and nothing is reported as closed. **Every job fetched from the board is saved as seen, including jobs cut by *Max jobs per company*.** The cap only limits how many rows a run outputs; capped-out jobs are not sent or charged on a later run, and closures are judged against the full list. If you need every matching job, set the cap to 0 (no limit) on the baseline run. The only rows carried to the next run are rows your *max charge per run* stopped, so no row is charged twice. (The older *Only new jobs since last run* mode keeps its own behavior.) The company summary adds `new_jobs_since_last_run`, `changed_jobs_since_last_run`, `closed_jobs_since_last_run`, `net_change_since_last_run`, `is_baseline_run` and `scan_complete`. This setting is off by default, and when it is on it replaces *Only new jobs since last run* for that run.

### Explainable signal score (optional)

Turn on **Signal scoring** (`signalScoring: true`) to add a company-level `signal_score` (0-100), a `signal_tier` (hot ≥70, warm ≥45, cool ≥20, cold) and `score_reasons` (one plain-English line per component) to each summary. Job rows get `job_function`, `company_signal_score`, `company_signal_tier` and `score_reasons`.

| Component | Max | What it measures |
|---|---|---|
| new demand | 25 | roles posted in the last 30 / 7 days, plus "N new since the last run" when tracking |
| velocity | 20 | growth of open roles once tracking spans 7+ days (before that, this week's posting pace vs the 30-day average) |
| seniority | 15 | share of manager/director/executive and senior roles |
| department | 15 | open roles in your `scoreFunctions` (sales, customer_success, marketing, data_ai, engineering, product_design, finance_legal, people_ops), or in the largest function |
| hard to fill | 10 | share of roles open 30+ days |
| volume | 10 | total open roles |
| remote | 5 | share of remote roles |

Example from a real run (Oct 30 2026, `greenhouse:anthropic`, `scoreFunctions: ["sales"]`, a later tracked run with no changes):

```json
{"type":"company_summary","total_open_jobs":669,"new_jobs_since_last_run":0,"closed_jobs_since_last_run":0,"signal_score":81,"signal_tier":"hot",
 "score_reasons":["+25 new demand: 188 roles posted in the last 30 days (45 in the last 7); 0 new since the last run",
  "+15 department: 123 open roles in target functions (sales)",
  "+13 seniority: 126 manager/director/executive roles (19%), 48% senior-or-above",
  "+10 hard-to-fill: 491 roles open 30+ days (73%)","+10 volume: 669 open roles",
  "+7 velocity: 45 postings this week vs 43.7/week 30-day average (1.0x pace)","+1 remote: 9% of roles are remote"]}
```

A changed row looks like this: `{"type":"job","change_type":"changed","changed_fields":["title"],"previous_values":{"title":"..."},"first_seen_at":"2026-10-30T..."}`.

### Pricing (pay per event)

- **$0.001 per job row** ($1 per 1,000 jobs)
- **$0.005 per company summary**
- Error rows and the empty-input demo are free.

You can set a max charge per run, and the Actor stops output cleanly when it is reached.

### Limits and notes

- Only companies that use one of the 6 supported ATS are covered. Workday, iCIMS, Taleo and custom boards are not. For Workday career sites use our sister Actor [Workday Jobs & Hiring Signals](https://apify.com/goldenrod_serrano/workday-hiring-signals).
- SmartRecruiters doesn't return descriptions in its list endpoint, so `description` stays empty there.
- `posted_at` is the ATS's publish or first-published date. Greenhouse's `updated_at` changes on any edit.
- Data belongs to the companies that published it. Respect each ATS's terms and applicable law when you reuse it.

### Support

Report issues at https://github.com/paopao-studio-ai/ats-hiring-signals/issues · https://paopao-studio.pages.dev

# Actor input Schema

## `companies` (type: `array`):

One per line. Any of: a careers/job-board URL (boards.greenhouse.io/stripe, jobs.lever.co/palantir, jobs.ashbyhq.com/ramp, apply.workable.com/x, jobs.smartrecruiters.com/x, x.recruitee.com), a company careers page that embeds one of those boards, 'ats:slug' (e.g. greenhouse:stripe), or a bare slug (auto-detected across all 6 ATS).

## `keywords` (type: `array`):

Keep jobs whose title/department (or description, if included) contains any of these. Case-insensitive. Empty = all jobs.

## `excludeKeywords` (type: `array`):

Drop jobs whose title contains any of these (e.g. intern, senior).

## `locations` (type: `array`):

Substring match on location/country, e.g. 'London', 'US', 'Remote'.

## `departments` (type: `array`):

Substring match on department/team, e.g. 'Sales', 'Engineering'.

## `remoteOnly` (type: `boolean`):

Keep only jobs marked remote (by the ATS flag or the location text).

## `seniorityLevels` (type: `array`):

Keep only these levels, inferred from the job title: intern, entry, mid, senior, lead, manager, director, executive. Empty = all. Every job row has a 'seniority' field either way.

## `workModels` (type: `array`):

Keep only remote, hybrid and/or onsite jobs (normalized 'work_model' field from the ATS workplace flag or location text). Jobs whose board doesn't say are dropped when this is set.

## `postedWithinDays` (type: `integer`):

Keep jobs first published in the last N days. 0/empty = no limit. (Workable/SmartRecruiters/Recruitee/Lever/Ashby give a publish date; Greenhouse gives first_published.)

## `onlyNewSinceLastRun` (type: `boolean`):

Remembers job IDs per company in a named key-value store, so scheduled runs output (and charge) only newly opened jobs. First run outputs everything that matches. The company summary also reports closed_jobs_since_last_run (jobs that disappeared from the board) and net_change_since_last_run.

## `stateKey` (type: `string`):

Name for the saved state. Use different keys for separate watch lists (e.g. 'sales-roles', 'clients-q4'). Required for change tracking and for the older monitor mode.

## `changeTracking` (type: `boolean`):

Keeps one small state record per company in the named key-value store and outputs only what changed since the last run with the same Monitor state key: change_type='new' (charged as a normal job row), change_type='changed' (a tracked field - title, location, department, team, work model, employment type and salary - changed; charged as a job row, with changed_fields and previous_values) and free type='job_closed' rows for jobs that disappeared. First run = baseline (everything matching is 'new'). If a listing could be truncated, no closures are reported and the old state is merged, never overwritten. Every scanned job is saved as seen: maxJobsPerCompany only limits output, and capped-out jobs are never sent or charged later. Only rows stopped by your max charge are carried to the next run. Replaces 'Only new jobs since last run' when both are on.

## `signalScoring` (type: `boolean`):

Adds signal_score, signal_tier (hot/warm/cool/cold), score_reasons (one plain-English line per component, with points) and score_components to each company summary, and company_signal_score + score_reasons to each job row. Components: new demand 25, growth velocity 20 (real open-role trend when change tracking has history, else posting pace), seniority 15, department focus 15, hard-to-fill/long-open roles 10, volume 10, remote share 5. The legacy hiring_signal_score is unchanged.

## `scoreFunctions` (type: `array`):

Optional. Functions that matter to you for the 'department focus' part of the score: sales, customer_success, marketing, data_ai, engineering, product_design, finance_legal, people_ops. Empty = reward the company's biggest build-out.

## `includeDescription` (type: `boolean`):

Adds plain-text descriptions (bigger output). Not available for SmartRecruiters.

## `longOpenDays` (type: `integer`):

Mark is_long_open when the posting is at least this many days old. Long-open / reposted roles are the classic recruiter BD entry point (role hard to fill).

## `dedupeJobs` (type: `boolean`):

Collapse rows that share a fingerprint within the run. The kept row gets duplicate_count and duplicate_urls. Turn off to keep every ATS id.

## `companyDomainMap` (type: `object`):

Map company name or board slug to a website domain, e.g. {"anthropic":"anthropic.com"}. Used when the input is an ATS URL that does not reveal the company site. Never invented from the slug alone.

## `outputJobs` (type: `boolean`):

Push one row per matching job (charged per job). Turn off to get only the company summaries.

## `outputCompanySummary` (type: `boolean`):

One row per company: open jobs, posted in last 7/30 days, remote share, top departments/locations and a 0-100 hiring-signal score. Great for sales prospecting.

## `maxJobsPerCompany` (type: `integer`):

0 = no cap. With change tracking on, every scanned job is saved as seen: this cap only limits how many rows this run outputs. Jobs cut by the cap are not sent or charged later. For a full baseline (every matching job delivered once), set this to 0 on the first run.

## `maxConcurrency` (type: `integer`):

How many companies to fetch in parallel.

## `addTickers` (type: `boolean`):

Adds ticker, cik and sec_title to each company summary (and ticker to each job) using SEC's public company_tickers.json. Conservative exact-name match: unmatched or ambiguous names stay null - no guessing. Free, no extra charge.

## `tickerMap` (type: `object`):

Optional. Overrides automatic matching, e.g. {"amazon": "AMZN", "meta": "META"}. Keys are the company name or slug as it appears in the output.

## Actor input object example

```json
{
  "companies": [
    "greenhouse:anthropic",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ramp"
  ],
  "keywords": [
    "engineer"
  ],
  "remoteOnly": false,
  "onlyNewSinceLastRun": false,
  "stateKey": "default",
  "changeTracking": false,
  "signalScoring": false,
  "includeDescription": false,
  "longOpenDays": 30,
  "dedupeJobs": true,
  "outputJobs": true,
  "outputCompanySummary": true,
  "maxJobsPerCompany": 0,
  "maxConcurrency": 5,
  "addTickers": true,
  "tickerMap": {}
}
```

# Actor output Schema

## `jobs` (type: `string`):

Matched job postings from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee boards (dataset view 'jobs').

## `hiringSignals` (type: `string`):

One row per company: open jobs, new jobs since last run, jobs posted in the last 7/30 days, top departments and locations, and a 0-100 hiring signal score (dataset view 'signals').

## `runSummary` (type: `string`):

JSON with counts of companies, boards found, jobs pushed and errors for this run.

## `changes` (type: `string`):

With change tracking on: new and changed job rows plus free job_closed rows (dataset view 'changes').

# 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 = {
    "companies": [
        "greenhouse:anthropic",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ramp"
    ],
    "keywords": [
        "engineer"
    ],
    "tickerMap": {}
};

// Run the Actor and wait for it to finish
const run = await client.actor("goldenrod_serrano/ats-hiring-signals").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 = {
    "companies": [
        "greenhouse:anthropic",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ramp",
    ],
    "keywords": ["engineer"],
    "tickerMap": {},
}

# Run the Actor and wait for it to finish
run = client.actor("goldenrod_serrano/ats-hiring-signals").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 '{
  "companies": [
    "greenhouse:anthropic",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ramp"
  ],
  "keywords": [
    "engineer"
  ],
  "tickerMap": {}
}' |
apify call goldenrod_serrano/ats-hiring-signals --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,goldenrod_serrano/ats-hiring-signals"
        }
    }
}
```

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/OAIzXLJCKh7C6lW29/builds/Fbl2CZcqnf974uIUh/openapi.json
