# ATS Jobs Scraper: Workday, Greenhouse, Lever & 4 More (`tinlark/ats-jobs-hiring-signals`) Actor

Open jobs from company career pages on Workday, Greenhouse, Lever, Ashby, Workable, Recruitee and Personio, hiring signals per company (new roles, departments, spikes) and new-only monitoring for schedules. Public endpoints, no login, no proxy.

- **URL**: https://apify.com/tinlark/ats-jobs-hiring-signals.md
- **Developed by:** [Tinlark](https://apify.com/tinlark) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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 Scraper: Workday, Greenhouse, Lever, Ashby, Workable, Recruitee and Personio

Get every open job from company career pages that run on **Workday**, **Greenhouse**, **Lever**, **Ashby**, **Workable**, **Recruitee** or **Personio**, as clean, uniform records. Switch to **signals** mode for one hiring summary per company, or to **new-only** mode to receive only the jobs that appeared since your last run.

The Actor reads the public job-board endpoints that these applicant-tracking systems (ATS) provide for company career sites. It needs no login, no browser and no proxy.

### Use cases

- **Workday jobs scraper, Greenhouse jobs API, Lever postings, Ashby, Workable, Recruitee and Personio in one Actor.** Give it board names, job-board or career-site URLs or company domains and get the same fields for all seven vendors.
- **Hiring signals for sales and recruiting teams.** One row per company: open roles, roles by department, new roles in the last 7 and 30 days, roles that closed, seniority mix and a hiring-spike flag.
- **Daily monitoring.** Schedule the Actor with a *State name* and use `new-only` mode. It returns just the jobs that are new since the last run, so a daily schedule stays cheap.
- **Filter at the source.** Keywords, departments, locations, remote only, posted within N days.
- **Find a company's job board from its domain.** Enter `notion.so` and the Actor looks for a linked board of any of the seven vendors on the company's home and careers pages, where the site's robots.txt allows it.

### Who it is for

Recruiters and sourcers tracking competitors' openings, sales and RevOps teams who use hiring as a buying signal, job-board and newsletter builders, and analysts who study hiring trends.

### Input

| Field | What it does |
|---|---|
| `companies` (required) | Board name (`stripe`), vendor and board name (`lever:palantir`), job-board or career-site URL (`https://jobs.ashbyhq.com/ramp`) or company domain (`notion.so`). See the table below for each vendor. |
| `mode` | `jobs` (default), `signals` or `new-only`. |
| `atsFilter` | Limit to some of `greenhouse`, `lever`, `ashby`, `workable`, `recruitee`, `personio`, `workday`. Empty means all seven. |
| `keywords`, `excludeKeywords` | Matched against title, department and team, not case sensitive. |
| `departments`, `locations` | Text that the department/team or any location must contain. |
| `remoteOnly` | Keep remote jobs only. |
| `postedWithinDays` | Keep jobs first published within N days. |
| `includeDescription` | Add the job description as plain text (larger output). |
| `maxJobsPerCompany` | Newest jobs first. Default 25. |
| `maxItems` | Stop after this many billable rows. Default 1000. |
| `stateKey` | A name such as `daily-sales-hiring`. Saves what was seen so later runs can report new and closed jobs. Required for `new-only`. |
| `emitExistingOnFirstRun` | In `new-only` mode, return all current jobs on the first run instead of just recording them. |
| `includeClosed` | With a `stateKey`, add a free row (`status: "closed"`) for each job that disappeared. |

#### How to name a company on each vendor

| Vendor | Board name or `vendor:board` | URL you can paste |
|---|---|---|
| Greenhouse | `greenhouse:stripe` | `https://boards.greenhouse.io/stripe` |
| Lever | `lever:palantir` | `https://jobs.lever.co/palantir` |
| Ashby | `ashby:ramp` | `https://jobs.ashbyhq.com/ramp` |
| Workable | `workable:huggingface` (the name in `apply.workable.com/<name>`) | `https://apply.workable.com/huggingface/` |
| Recruitee | `recruitee:bunq` (the name in `<name>.recruitee.com`) | `https://bunq.recruitee.com` |
| Personio | `personio:matrix42` (the name in `<name>.jobs.personio.de`) | `https://matrix42.jobs.personio.de` |
| Workday | `workday:nvidia.wd5/NVIDIAExternalCareerSite` (tenant, data-centre number and career-site name) | `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite` |

A bare name such as `stripe` is tried on Greenhouse, Lever, Ashby, Workable, Recruitee and Personio in that order, and the first board that lists jobs is used. Workday needs the career-site name too, so use the URL or `workday:` form. Custom careers domains that sit in front of Recruitee or Workable are not recognised from the URL; use `recruitee:name` or `workable:name`.

#### Example input

```json
{
  "companies": ["stripe", "lever:palantir", "https://jobs.ashbyhq.com/ramp", "workable:huggingface", "recruitee:bunq",
                "personio:matrix42", "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite", "notion.so"],
  "mode": "jobs",
  "keywords": ["account executive", "sales"],
  "postedWithinDays": 30,
  "maxJobsPerCompany": 25
}
```

#### Example: watch for new jobs every day

```json
{
  "companies": ["ramp", "notion", "vercel"],
  "mode": "new-only",
  "stateKey": "gtm-watchlist",
  "departments": ["Sales", "Marketing"]
}
```

The first run records the jobs that are open today and returns nothing, so you are not charged for the backlog. Every later run returns only jobs that were not there before. Use a different `stateKey` for each watch list.

### Output

Results go to the default dataset. Download them as JSON, CSV, Excel or XML, or read them through the API. The *Jobs*, *Company signals* and *Problems* views show the main fields.

#### Job row (real output, trimmed)

```json
{
  "recordType": "job",
  "atsVendor": "ashby",
  "company": "Ramp",
  "boardToken": "ramp",
  "jobId": "0d731586-3626-48fb-9dc5-3061ae5fd240",
  "title": "Customer Experience Associate - London",
  "department": "Customer Experience",
  "team": "CX Frontline",
  "locations": ["London"],
  "isRemote": false,
  "workplaceType": "hybrid",
  "employmentType": "full-time",
  "seniority": "junior",
  "salaryMin": 39000,
  "salaryMax": 43000,
  "salaryCurrency": "GBP",
  "salaryInterval": "year",
  "postedAt": "2026-10-01T18:38:56Z",
  "jobUrl": "https://jobs.ashbyhq.com/ramp/0d731586-3626-48fb-9dc5-3061ae5fd240",
  "applyUrl": "https://jobs.ashbyhq.com/ramp/0d731586-3626-48fb-9dc5-3061ae5fd240/application",
  "sourceUrl": "https://api.ashbyhq.com/posting-api/job-board/ramp",
  "status": "open"
}
```

#### Company signal row (real output, trimmed)

```json
{
  "recordType": "signal",
  "company": "Notion",
  "domain": "notion.so",
  "atsVendor": "ashby",
  "openRoles": 134,
  "rolesByDepartment": { "Sales": 44, "Engineering": 16, "Outcomes Architect": 14, "People": 11 },
  "seniorRoles": 47,
  "remoteRoles": 0,
  "newLast7d": 10,
  "newLast30d": 29,
  "closedLast30d": null,
  "hiringSpike": false,
  "latestTitles": ["Software Engineer, Mobile Core (Android)", "Forward Deployed Architect", "Product Manager"]
}
```

#### Field notes

- `postedAt` is the vendor's first-published date (Greenhouse `first_published`, Lever `createdAt`, Ashby `publishedAt`, Workable `published_on`, Recruitee `published_at`, Personio `createdAt`), in UTC. Workable gives a date only (midnight UTC). **Workday's list only says "Posted Today", "Posted 5 Days Ago" or "Posted 30+ Days Ago"**: `postedAt` is then the day (midnight UTC), and empty for "30+". With `includeDescription` the Actor also reads each returned Workday job's page and sets the exact start date.
- Salary fields are filled only when the employer publishes a pay range on the posting (Greenhouse pay transparency, Lever `salaryRange`, Ashby compensation, Recruitee salary). Most postings have none. Workable, Personio and Workday publish no structured salary in these feeds. Greenhouse postings with several regional ranges report the widest range in the first currency, and the full list is in `salaryRanges`.
- `company` comes from the vendor for Greenhouse, Workable and Recruitee. Lever, Ashby, Personio and Workday do not name the company, so it is derived from the board name (`ramp` becomes `Ramp`).
- `seniority` is a heuristic based on the title only (`executive`, `director`, `staff+`, `senior`, `manager`, `junior`, `intern`, `unspecified`).
- `isRemote` uses the vendor's workplace type where it exists (Lever, Ashby, Workable, Recruitee) and the word "remote" in the location or title for Greenhouse, Personio and Workday (with `includeDescription`, Workday's own remote type is used too).
- **Workable** lists a job once per location; the Actor merges them into one job with all locations. Locations the employer hides on its job page (usual for remote roles) are not returned.
- **Workday** has no department or employment type in its list, and shows "5 Locations" instead of names. `department` stays empty (so `rolesByDepartment` in signals mode is "Unspecified" for Workday and the `departments` filter finds nothing); `employmentType`, all locations and the description come with `includeDescription`. Filter Workday jobs with `keywords` on the title.
- **Personio** feeds often contain no description text at all; `descriptionText` is then empty. `department` is the department set in Personio.
- `closedLast30d` and `openRolesChangeSinceLastRun` are `null` until you use a `stateKey` and the Actor has run at least twice. `openRolesChangeSinceLastRun` compares all open roles on the board with the previous run, whatever your filters are; `openRoles` counts the roles that match your filters.
- `hiringSpike` is `true` when at least 3 roles were posted in the last 7 days and that is at least twice the weekly average of the 23 days before.
- Rows with `recordType: "error"` are free and list entries that could not be resolved to a board, with the reason.
- A run summary (rows, errors, requests, duration) is saved under the `SUMMARY` key of the run's key-value store.

### Pricing

**Free during launch (until 31 October 2026).** You pay only Apify's own platform usage for your runs.

Measured platform usage: about $0.003 to $0.005 per 1,000 job rows on our measurements (a run of 22 boards on all seven vendors with 7,756 jobs cost $0.026 in platform usage and took under 2 minutes; a run of 19 Greenhouse, Lever and Ashby boards with 5,859 jobs cost $0.03 and took 6 seconds). On the Apify free plan that usage is covered by your monthly credit.

**From 1 November 2026: pay per event.** Planned prices, shown here so you can budget:

| Event | Price | When it is charged |
|---|---|---|
| Job row | $1.50 per 1,000 ($0.0015 each) | Each job row in `jobs` and `new-only` modes |
| Company signal row | $5.00 per 1,000 ($0.005 each) | Each company row in `signals` mode |
| Board detected from a domain | $3.00 per 1,000 ($0.003 each) | Each company domain that was matched to a board. Not charged when no board is found, and not charged for board names or URLs. |

Not charged: error rows, closed-job rows, the baseline run of `new-only` mode, and a company signal row when no role matches your filters (`openRoles` is 0). Volume discounts apply on higher Apify plans (see the event prices shown on this page once they are active). Cost examples at the planned prices:

- 10 companies, 25 jobs each: 250 jobs, $0.375.
- 200 company signals: $1.00.
- A daily `new-only` watch of 50 companies that posts 30 new jobs a day: about $0.045 a day.

Set *Maximum cost per run* in the run options to cap spending once pricing is active; the Actor stops cleanly when the cap is reached.

### Limits and honest notes

- **Seven vendors.** SmartRecruiters is left out on purpose: its robots.txt disallows automated access to its posting API. BambooHR, Breezy HR, iCIMS, Taleo, Oracle Recruiting, SuccessFactors and others are not supported.
- **Workday: up to 2,000 jobs per career site per run.** Workday lists 20 jobs per request, read at one request a second, so a 2,000-job career site takes about 2 minutes (a plain jobs run with no filters stops after `maxJobsPerCompany` jobs and is much faster). Larger career sites are cut at 2,000 and the run summary says so. Some large employers run protected career sites that do not answer these requests; those come back as an error row. Career sites on `myworkdaysite.com` are not supported.
- **Only companies on those vendors.** The Actor cannot discover companies by itself. You supply boards, career-site URLs or domains.
- **Domain lookup is best effort.** It finds boards that are linked from the home page or a few standard careers URLs. In a test of 15 well-known company domains it found a board for 9. For the others, enter the board name or URL. Pages that load their links with JavaScript are not read.
- **Bare board names are tried on Greenhouse, Lever, Ashby, Workable, Recruitee, then Personio.** The first board that lists jobs is used. If two companies use the same name on different vendors, enter `vendor:name` or the URL.
- **Public jobs only.** Only postings the employer publishes on its public job board are returned. Internal, unlisted and closed postings are not.
- **Closed jobs need a `stateKey`.** The vendors do not publish closed jobs, so the Actor can only report them by comparing with its own earlier run. If a board suddenly returns zero jobs while it had five or more before, the Actor treats it as a vendor outage and does not mark them closed.
- **Pace.** Greenhouse is read at no more than 4 requests a second, Lever at 1 request a second (its published crawl delay), Ashby and Workable at 2 a second, and Recruitee, Personio and Workday (each company has its own host) at 1 a second. Large lists of boards on one vendor therefore take proportionally longer. Failed requests are retried with backoff (HTTP 429, 5xx, network errors).
- The `new-only` mode keeps each board's state in a named key-value store called `ats-state-<your stateKey>` in your account.

### Data source, terms and your responsibility

All data comes from the public job-board endpoints of each vendor, which exist so that companies' own career sites and third parties can list the postings:

- Greenhouse Job Board API (`boards-api.greenhouse.io`): the vendor documents that job board data is public and needs no authentication for GET requests.
- Lever Postings API (`api.lever.co`): the vendor documents that postings in the published state are publicly viewable. Its robots.txt asks for a crawl delay of 1 second, which the Actor follows.
- Ashby public job posting API (`api.ashbyhq.com/posting-api`).
- Workable job widget API (`apply.workable.com/api/v1/widget/accounts/<name>`), the public JSON behind Workable's embeddable jobs widget.
- Recruitee Careers Site API (`<name>.recruitee.com/api/offers/`), documented by Recruitee as open without authentication.
- Personio XML job feed (`<name>.jobs.personio.de/xml`), the feed Personio documents for job boards.
- Workday career-site search (`<tenant>.wd<N>.myworkdayjobs.com/wday/cxs/...`), the JSON that every Workday career page loads for its own job list.

For Workable, Recruitee, Personio and Workday the Actor reads the robots.txt of each company's host before every board and skips it if the file disallows the endpoint (Personio answers `Disallow: /` for names that do not exist, which shows up as "not found"). Workday's website terms cover Workday's own sites; the career sites belong to each employer, so check the employer's terms for how you use the data.

The Actor identifies itself with a `TinlarkBot` User-Agent. For company domains it reads the home page and a few standard careers URLs only where the site's robots.txt allows. Job postings are the employers' own advertisements and contain no personal data about applicants; the Actor does not read applicant or recruiter data. Job content belongs to the employers: check their terms and the laws that apply to you (for example on unsolicited contact or on republishing postings) before you reuse the data. Each row carries `jobUrl`, `applyUrl` and `sourceUrl` so you can attribute and link back.

This Actor is not affiliated with Workday, Greenhouse, Lever, Ashby, Workable, Recruitee or Personio.

### FAQ

**Does it need a proxy or a login?** No. The endpoints are public and the Actor is light: it uses plain HTTP requests.

**How fresh is the data?** Each run reads the live board. The data is as fresh as the employer's board.

**How big can a run be?** A cloud run with 22 boards on all seven vendors returned 7,756 jobs in 111 seconds, most of it the paged Workday career sites (5,469 jobs). Boards on the other vendors take about a second each. Memory use stays low (about 150 MB at peak), the default is 512 MB.

**Why did my company return an error row?** Typical reasons: the board name is spelled differently from the company name, the company uses another ATS, or a domain's careers page does not link to a supported board. The `error` field says which. Paste the job-board URL to be sure.

**Can I get the job descriptions?** Yes, turn on `includeDescription`. You get plain text.

**Can I schedule it?** Yes. Use Apify Schedules with a fixed `stateKey` and `new-only` mode for a daily feed of new jobs, or `signals` mode weekly to track hiring trends.

**How do I use it from code or an AI agent?** Call it through the Apify API or any Apify client library, or through Apify's MCP server. The input and output schemas are defined, so the fields are self-describing.

**Disclaimers and legality: can I use this data?** The Actor reads only what employers publish on their own public job boards, through the endpoints the vendors provide for that purpose, and it follows robots.txt and the vendors' stated crawl delays. It does not log in, read applicant data or get around blocks. The postings belong to the employers and are returned as published. You are responsible for how you use them, including the laws on unsolicited contact and on republishing content that apply to you. Tinlark is not affiliated with any of these vendors, and this is not legal advice.

### Support

Something wrong or missing? Open an issue on this Actor's Issues tab with your input (the board name or URL) and what you expected.

# Actor input Schema

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

One entry per company. Accepted: a board name (stripe), a vendor and board name (lever:palantir), a job-board or career-site URL (https://jobs.ashbyhq.com/ramp, https://apply.workable.com/huggingface/, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite), or a company domain (notion.so). A bare name is tried on Greenhouse, Lever, Ashby, Workable, Recruitee and Personio in that order. Workday needs the career-site URL or workday:tenant.wdN/site. For a domain, the Actor reads the company's own home and careers pages, where robots.txt allows, to find a linked board of any supported vendor.

## `mode` (type: `string`):

jobs: one row per open job. signals: one summary row per company (open roles by department, new and closed roles, hiring spike flag). new-only: only jobs not seen in earlier runs (needs a State name).

## `atsFilter` (type: `array`):

Restrict to some vendors. Leave empty for all seven. For a bare board name, vendors are tried in the order greenhouse, lever, ashby, workable, recruitee, personio (Workday needs a career-site URL).

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

Keep jobs whose title, department or team contains any of these words (not case sensitive).

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

Drop jobs whose title, department or team contains any of these words.

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

Keep jobs whose department or team contains any of these texts, for example Sales or Engineering.

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

Keep jobs with a location containing any of these texts, for example Berlin, Germany or United States.

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

Keep only jobs the vendor marks as remote (Ashby, Lever, Workable, Recruitee) or whose location or title says remote (Greenhouse, Personio, Workday).

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

Keep jobs first published within this many days. Leave empty for no limit. Workday's list only says "Posted N days ago" up to 30 days, so jobs older than that have no date there.

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

Add the full job description as plain text. Makes the output much larger. For Workday this reads one extra page per returned job (about one per second) and also adds exact posting dates and all locations.

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

Newest jobs first. Applies to jobs and new-only modes.

## `maxItems` (type: `integer`):

Stops the run once this many billable rows (jobs or company signals) were produced.

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

Lowercase letters, digits and hyphens. Saves which jobs were seen in a named storage so later runs can report new and closed jobs. Use the same name on every scheduled run, and a different name for each watch list. Required for the new-only mode.

## `emitExistingOnFirstRun` (type: `boolean`):

By default the first new-only run for a company only records the current jobs as a baseline and returns nothing. Turn this on to receive all current jobs the first time.

## `includeClosed` (type: `boolean`):

With a State name, add a free row (status closed) for each job that disappeared since the last run.

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "lever:palantir",
    "https://jobs.ashbyhq.com/ramp",
    "workable:huggingface",
    "recruitee:bunq",
    "personio:matrix42",
    "workday:nvidia.wd5/NVIDIAExternalCareerSite",
    "notion.so"
  ],
  "mode": "jobs",
  "remoteOnly": false,
  "includeDescription": false,
  "maxJobsPerCompany": 25,
  "maxItems": 1000,
  "emitExistingOnFirstRun": false,
  "includeClosed": false
}
```

# Actor output Schema

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

Job rows, newest first within each company.

## `signals` (type: `string`):

One hiring summary per company (signals mode).

## `errors` (type: `string`):

Inputs that could not be resolved to a job board.

## `summary` (type: `string`):

Counts, errors, request totals.

# 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": [
        "stripe",
        "palantir",
        "ramp",
        "workable:huggingface",
        "recruitee:bunq",
        "personio:matrix42",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("tinlark/ats-jobs-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": [
        "stripe",
        "palantir",
        "ramp",
        "workable:huggingface",
        "recruitee:bunq",
        "personio:matrix42",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("tinlark/ats-jobs-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": [
    "stripe",
    "palantir",
    "ramp",
    "workable:huggingface",
    "recruitee:bunq",
    "personio:matrix42",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ]
}' |
apify call tinlark/ats-jobs-hiring-signals --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tinlark/ats-jobs-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/eR9ST1qSxDKQheazJ/builds/FrR5oJEwgJkgp3hsI/openapi.json
