# Greenhouse, Lever & Ashby Jobs API + Hiring Signals (`northloop-hq/jobs-api-ats-feed`) Actor

Career Site Jobs API for Greenhouse, Lever, Ashby, Workday and 5 more ATSs. Domain in: open jobs, new/closed jobs, or one flat hiring-signals row for Clay, CRMs and AI agents. Pay only for jobs and signals you use.

- **URL**: https://apify.com/northloop-hq/jobs-api-ats-feed.md
- **Developed by:** [North Loop Agents](https://apify.com/northloop-hq) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 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

## Greenhouse jobs API + hiring signals for Clay (also Lever, Ashby, Workday)

**Jobs API for Greenhouse, Lever, Ashby, Workday, Workable, Personio, SmartRecruiters, Teamtailor and Recruitee.** Give it company domains. It finds each company's ATS, reads its public job board and returns either **every open job as clean JSON**, **only the new and closed jobs since your last run**, or **one flat hiring-signal row per domain** (open jobs, new jobs, closed jobs, top departments, top locations, sample titles and URLs) that drops straight into **Clay**, a CRM or an AI agent.

- **Domain in, signal out.** `stripe.com` in, one row out: `openJobs`, `newJobs`, `closedJobs`, `newJobsLast7d`, `topDepartments`, `topLocations`, `sampleTitles`, `newJobUrls`. Flat fields only, no nested arrays, so Clay mapping is one click per column.
- **Pay only for what's new.** Change tracking is stored in your own Apify account. Jobs you already received are never charged again, and a company that didn't change costs **$0**.
- **No browser, no proxy, no login.** Official public job-board APIs only, the same endpoints the companies' own career pages call. Fast, cheap and stable.
- **Built for agents.** Pay per event, events only, limited permissions, no Standby: it can be run by AI agents through the Apify MCP server and the Apify API.

### Quick start

```json
{
  "mode": "signals",
  "domains": ["notion.so", "n26.com", "pleo.io"]
}
```

That's the whole input. Example output row (shortened):

```json
{
  "recordType": "hiring-signal",
  "input": "n26.com",
  "company": "N26",
  "ats": "greenhouse",
  "boardUrl": "https://job-boards.greenhouse.io/n26",
  "status": "ok",
  "changed": true,
  "openJobs": 37,
  "newJobs": 2,
  "closedJobs": 1,
  "netChange": 1,
  "newJobsLast7d": 5,
  "newJobsLast30d": 15,
  "topDepartments": "Finance (5); Group Internal Audit (5); Risk (3); Legal (3); Business (2)",
  "topLocations": "Berlin, DE (20); Barcelona, ES (9); Madrid, ES (5); Paris, FR (3)",
  "newJobTitles": "Treasury Trader; ICT Risk Assessment Manager",
  "newJobUrls": "https://job-boards.greenhouse.io/n26/jobs/… | https://job-boards.greenhouse.io/n26/jobs/…",
  "summary": "N26 opened 2 and closed 1 job(s) since 2026-10-22; most new roles in Treasury.",
  "checkedAt": "2026-10-23T05:40:12.000Z",
  "billedEvent": "hiring-signal"
}
```

### Modes and price per result

You pay per event, and **only** for events. No platform-usage surcharge, no per-company fee.

| Mode | What you get | Price |
|---|---|---|
| `signals` | One flat **hiring-signal** row per domain | **$0.025 per changed domain.** A domain counts as changed on its first check (if it has open jobs) and afterwards only when jobs were opened or closed since your last check. Unchanged, zero-job and not-found domains get a **free** row. |
| `jobs` (default) | Every open job matching your filters, one row per job | **$0.0015 per job** ($1.50 per 1,000 jobs) |
| `new-jobs` | Only jobs that are **new** or **closed** since your last run | **$0.0015 per new or closed job.** Jobs already delivered are never charged again. |
| `new-jobs-and-signals` | Both of the above | Both of the above |

Apify also charges its standard **actor-start** event ($0.00005 per run, which pays for the first 5 seconds of compute).

Examples:

- Enrich 1,000 Clay rows once: if 800 of the domains have open jobs, 800 × $0.025 = **$20**. Domains with no jobs or no ATS cost nothing.
- Re-check the same 1,000 domains every week: you pay only for the ones that changed, typically a fraction of the list.
- Daily new-jobs feed for 50 companies with about 40 new or closed jobs a day: 40 × $0.0015 = **$0.06/day**.

Set *Maximum cost per run* in the run options. The Actor stops cleanly at your limit, and anything it couldn't deliver is still "new" next time, so you never pay for rows you didn't get.

### Reliability

**Tested on 23+ platform runs before launch, with 0 failures** (21–24 Oct 2026: our own test and validation runs across Greenhouse, Lever, Ashby, Workday and Personio). The "runs succeeded" figure on the Store page counts only other users' runs from the last 30 days, so it reads 0% until the first public runs come in.

Every row comes from an official public ATS API, so there are no CAPTCHAs, proxies or browser crashes to fail on. A domain whose ATS can't be found is reported as a free `not-found` row; it doesn't fail the run.

### Use it in Clay

Clay's native **Run Apify Actor** enrichment works on every Clay plan, Free included. It runs on your own Apify account, so you only need an Apify API token.

1. **Create a Task in Apify.** Open this Actor in Apify Console, click **Create task**, switch the input from **Manual** to **JSON** and paste:
   ```json
   { "mode": "signals", "domains": ["stripe.com"] }
   ```
   Save the task (for example "Hiring signal for one domain").
2. **Connect Apify in Clay** (once). In Clay go to **Settings → Connections → Add connection → Apify** and paste your Apify API token from **Apify Console → Settings → API & Integrations**. You can also add it from the enrichment panel the first time.
3. **Add the enrichment.** In your Clay table click **Add enrichment**, search for **Apify** and choose **Run Apify Actor**. Pick your Apify account and the task from step 1.
4. **Map the domain column.** In **Input Data** enter the JSON body and insert your domain column as a token (type `/` and pick the column):
   ```json
   { "mode": "signals", "domains": [ /Company Domain ] }
   ```
   Clay's rule: keep the key in quotes but **don't put quotes around the token**. (If Clay reports invalid JSON for your column type, wrap the token in quotes.)
5. **Control spend.** Turn **auto-update off** while you test, and use a **conditional run** (for example, only when *Company Domain* is not empty) so you only pay for rows you want.
6. **Run and map columns.** Run the column on a few rows, open a cell and click the fields you want as new columns: `openJobs`, `newJobs`, `closedJobs`, `newJobsLast7d`, `topDepartments`, `topLocations`, `sampleTitles`, `newJobUrls`, `summary`. Every field is a plain string, number or boolean.
7. **Make it a weekly signal.** Re-run the column every week (scheduled re-runs on Clay's paid plans, or manually). Each re-run compares the domain with its last check, so `newJobs`/`closedJobs` show what changed that week, and unchanged domains cost $0.

Good Clay triggers: `newJobs >= 3`, `hiringSurge = true`, `newJobsTopDepartments` contains "Sales" or "Engineering", `topLocations` contains your territory.

**Clay Growth plan: HTTP API instead.** `POST https://api.apify.com/v2/acts/northloop-hq~jobs-api-ats-feed/run-sync-get-dataset-items?maxTotalChargeUsd=0.05` with the header `Authorization: Bearer <your Apify token>` and the JSON body above. The call returns the dataset rows directly; it must finish within 300 seconds, which one or a few domains always do.

Clay Free plan tables hold up to 200 rows.

### For AI agents and developers

- **Input:** `domains` (array of domains), `mode` (`signals` | `jobs` | `new-jobs` | `new-jobs-and-signals`), optional filters (`keywords`, `countries`, `departments`, `workplaceTypes`, `employmentTypes`, `seniorities`, `postedWithin`).
- **Output:** dataset rows with `recordType` = `hiring-signal` or `job`. Run summary (per-company status, charged events, estimated charge) in the `OUTPUT` key-value record.
- **Sync call:** `POST /v2/acts/northloop-hq~jobs-api-ats-feed/run-sync-get-dataset-items` returns rows in one request.
- **Agent payments:** pay-per-event, events only, limited permissions, no Standby, which is what Apify requires for agentic payments (x402 and pay-per-request agents).
- **State:** change tracking lives in the named key-value store `jobs-api-ats-feed-state` in the caller's own account, per company and per filter set (or per `monitorId`). Deleting that store resets it.

### Output: hiring-signal rows

One row per input domain per run (`recordType: "hiring-signal"`), in every mode that includes signals.

| Field | Meaning |
|---|---|
| `input`, `companyDomain`, `company` | What you passed, the domain, and the company name from the job board |
| `ats`, `atsSlug`, `boardUrl` | Detected ATS, board name and public board URL |
| `status`, `error` | `ok`, `not-found`, `error`, `duplicate` or `invalid-input`, plus the reason |
| `changed`, `billedEvent` | Whether this row was charged (`hiring-signal`) or free (`null`) |
| `isFirstSnapshot` | `true` on the first check of this domain for this watch list |
| `openJobs`, `openJobsBefore` | Open jobs now and at the last check |
| `newJobs`, `closedJobs`, `netChange`, `growthPct` | Changes since the last check (`null` on the first snapshot) |
| `hiringSurge` | `true` when at least 5 jobs and at least 10% of the previous open jobs were opened |
| `newJobsLast7d`, `newJobsLast30d` | Open jobs posted in the last 7 / 30 days (from ATS dates; works on the first run) |
| `remoteJobs`, `remotePct` | Remote open jobs |
| `topDepartments`, `topLocations`, `topCountries` | Top 5 of all open jobs, e.g. `"Engineering (12); Sales (5)"` |
| `newJobsTopDepartments`, `newJobsTopLocations` | Top 5 of the new jobs |
| `sampleTitles`, `sampleJobUrls` | 5 newest open titles / URLs |
| `newJobTitles`, `newJobUrls`, `closedJobTitles` | Up to 10 new titles / URLs and closed titles |
| `latestPostedAt`, `periodStart`, `checkedAt`, `lastChangeAt` | Dates (ISO 8601) |
| `summary` | One sentence, ready for an email opener or a Slack alert |

Lists inside a field are joined with `"; "` (titles) or `" | "` (URLs).

### Output: job rows

One row per job (`recordType: "job"`). Example, with the description shortened:

```json
{
  "recordType": "job",
  "company": "Pleo",
  "companyDomain": "pleo.io",
  "ats": "ashby",
  "atsSlug": "pleo",
  "jobId": "5b0f0144-e153-4468-a626-3baf79e2342c",
  "jobKey": "ashby:pleo:5b0f0144-e153-4468-a626-3baf79e2342c",
  "title": "Sales Development Representative - Nordics",
  "department": "SDR",
  "city": "Lisbon",
  "countryCode": "PT",
  "countryCodes": ["PT", "DK"],
  "workplaceType": null,
  "employmentType": "FULL_TIME",
  "seniority": null,
  "salaryMin": null, "salaryMax": null, "salaryCurrency": null, "salaryPeriod": null,
  "postedAt": "2026-10-20T09:14:57.321Z",
  "jobUrl": "https://jobs.ashbyhq.com/pleo/5b0f0144-e153-4468-a626-3baf79e2342c",
  "applyUrl": "https://jobs.ashbyhq.com/pleo/5b0f0144-e153-4468-a626-3baf79e2342c/application",
  "descriptionMarkdown": "## **About Pleo**\n\nMessy spend management is tricky business. …",
  "status": "open",
  "changeType": null,
  "firstSeenAt": "2026-10-21T06:21:34.020Z",
  "resolvedBy": "careers-page-link"
}
```

Values are normalised across all ATSs:

- **employmentType:** FULL_TIME, PART_TIME, CONTRACT, TEMPORARY, INTERNSHIP, WORKING_STUDENT, APPRENTICESHIP, FREELANCE
- **seniority:** INTERN through EXECUTIVE. It comes from the title, or from the ATS field when the title has no hint.
- **workplaceType:** remote, hybrid or onsite
- **Countries:** ISO 3166 alpha-2 codes. Country names in many languages are recognised, as are US-state formats ("Austin, TX") and Workday's "USA, CA, Santa Clara".
- **Salary:** filled in when the company publishes it (Ashby, Lever, Recruitee).

In `new-jobs` modes, job rows carry `changeType: "new"` or `"closed"` (with `closedAt`). A job that only falls outside your date filter is *not* reported as closed.

### Supported ATSs

| ATS | Typical customers | Public endpoint used |
|---|---|---|
| **Greenhouse** | US/EU tech (Airbnb, Stripe, Figma, Datadog…) | `boards-api.greenhouse.io/v1/boards/{board}/jobs` (Job Board API) |
| **Lever** | Tech scale-ups (Spotify, Palantir…) | `api.lever.co/v0/postings/{site}` (Postings API, US and EU instances) |
| **Ashby** | Start-ups (Notion, Pleo, OpenAI…) | `api.ashbyhq.com/posting-api/job-board/{board}` (Job Posting API) |
| **Workday** | Enterprises (NVIDIA, Salesforce, Adobe, Workday…) | `{tenant}.wdN.myworkdayjobs.com/wday/cxs/…` (the career site's own JSON API) |
| **Workable** | SMBs worldwide | `apply.workable.com/api/v1/widget/accounts/{account}` |
| **Personio** | DACH SMEs and scale-ups | `{company}.jobs.personio.de/xml` (official XML feed) |
| **SmartRecruiters** | Large enterprises (Bosch, Visa…) | `api.smartrecruiters.com/v1/companies/{id}/postings` (Posting API) |
| **Teamtailor** | Nordics, Benelux, UK | Career-site RSS `/jobs.rss` (custom domains work too) |
| **Recruitee** | Netherlands, CEE | `{company}.recruitee.com/api/offers/` |

#### How auto-detection works

1. The Actor opens the website and up to 6 career-related pages and looks for links, embeds or redirects to one of the 9 ATSs, including Workday career sites the company links to.
2. If nothing is found, it tries the company name as a board name on each ATS. It accepts the guess only when the board's company name matches the domain, or when exactly one board exists. Each row says how its company was resolved (`resolvedBy`).
3. Resolutions are **cached in your account for 30 days**, and domains without a detectable ATS for 1 day.

You can also pass job-board URLs or `ats:slug` entries (`greenhouse:airbnb`, `lever:spotify`, `ashby:pleo`, `workday:nvidia.wd5/NVIDIAExternalCareerSite`) in the `companies` field.

### Privacy and data protection

- The Actor only outputs **job advertisements**. It never copies recruiter or contact fields (e.g. SmartRecruiters `creator`, Recruitee `mailbox_email`).
- **Personal e-mail addresses and phone numbers in descriptions are removed.** Role mailboxes such as `careers@` are kept.
- Names of people in free text can't be detected reliably. If you republish descriptions, review them for that.

### Limits and notes

- Only **published** jobs are covered. Internal and hidden jobs aren't in the public feeds.
- **Workday:**
  - Pass the career-site URL (e.g. `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`) or `workday:tenant.wdN/site`. A bare domain is only detected when the company's site links to its Workday career site.
  - Workday shows at most **2,000 jobs** per search. Larger tenants are flagged `truncated`; use keywords to narrow the search.
  - Requests are rate-limited (about 2.5/s per site) to be polite, so large tenants take 1–4 minutes.
  - Country, remote and employment-type filters need one detail request per candidate job, capped by `maxDetailRequestsPerCompany`.
  - Turn off `workdayDepartments` for faster runs without department labels.
- **SmartRecruiters:** descriptions need one request per job, so they're only fetched for jobs that are output. Listing is capped at 5,000 jobs.
- **Teamtailor:** the RSS feed has no employment type or salary.
- **Personio:** descriptions are requested in English, with the company's default language as a fallback.
- Career sites built entirely in JavaScript may not be auto-detected. Pass the board URL or `ats:slug` instead.

### FAQ

**Is this legal?** The Actor reads the public endpoints that ATS vendors provide so companies can show their jobs on their own websites. It doesn't log in, doesn't bypass protections and collects no personal data. You remain responsible for how you use the data.

**Can I use it as an API?** Yes. Call it through the Apify API, SDKs, or MCP from your own code or AI agent, and read the dataset as JSON or CSV. See *For AI agents and developers* above.

**My company isn't detected or its ATS isn't supported.** Pass the job-board link or `ats:slug`. For other ATSs (SAP SuccessFactors, iCIMS, Join…), open an issue and tell us which one you need.

# Actor input Schema

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

<b>jobs</b>: every open job that matches your filters, one row per job ($0.0015/job). <b>signals</b>: domain in, signal out. One flat hiring-signal row per company (open jobs, new and closed since your last run, top departments and locations, sample titles and URLs). Charged $0.025 only when the company changed; unchanged or not-found companies get a free row. Ideal for Clay. <b>new-jobs</b>: only jobs that are new or closed since your last run ($0.0015 each); jobs you already received are never charged again. <b>new-jobs-and-signals</b>: both.

## `domains` (type: `array`):

One company website domain per line, e.g. <code>stripe.com</code>. The ATS (Greenhouse, Lever, Ashby, Workday, Workable, Personio, SmartRecruiters, Teamtailor, Recruitee) is detected automatically and cached for 30 days. In Clay use <code>"domains": \["{{Company Domain}}"]</code>.

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

Optional, combined with <b>Company domains</b>. One per line. Any of: a company domain (<code>stripe.com</code>), a careers-page URL, a job-board URL (<code>https://job-boards.greenhouse.io/airbnb</code>, <code>https://jobs.lever.co/spotify</code>, <code>https://jobs.ashbyhq.com/pleo</code>, <code>https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite</code>) or <code>ats:slug</code> (<code>greenhouse:airbnb</code>, <code>lever:spotify</code>, <code>ashby:pleo</code>, <code>workday:nvidia.wd5/NVIDIAExternalCareerSite</code>, <code>workable:huggingface</code>, <code>personio:stark</code>, <code>smartrecruiters:BoschGroup</code>, <code>teamtailor:centra</code>, <code>recruitee:bunq</code>). For a bare domain the ATS is detected automatically (Workday: pass the career-site URL).

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

Keep jobs whose title, department or team contains any of these words (case-insensitive). Leave empty for all jobs.

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

Drop jobs whose title contains any of these words, e.g. <code>intern</code>, <code>werkstudent</code>.

## `searchInDescription` (type: `boolean`):

Search keywords in the full job description too (finds e.g. jobs mentioning 'Kubernetes').

## `countries` (type: `array`):

Two-letter ISO country codes, e.g. <code>DE</code>, <code>FR</code>, <code>LU</code>. A job matches if any of its locations is in one of them.

## `includeJobsWithoutCountry` (type: `boolean`):

When filtering by country, also keep jobs whose location has no country (e.g. 'Remote - Europe').

## `workplaceTypes` (type: `array`):

Keep only these workplace types. Jobs where the ATS does not say are excluded when this is set.

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

Keep jobs whose department or team contains any of these, e.g. <code>Engineering</code>, <code>Sales</code>.

## `employmentTypes` (type: `array`):

Keep only these (normalised) employment types.

## `seniorities` (type: `array`):

Keep only these seniority levels (from the title, or from the ATS field when the title has no hint).

## `postedWithin` (type: `string`):

Only jobs posted in this window, e.g. <code>7 days</code>, <code>2 weeks</code>, <code>1 month</code>, or a date <code>2026-10-01</code>. Jobs without a posting date are kept.

## `monitorId` (type: `string`):

Optional name for this watch list. State is kept per company and per filter set in the named key-value store <code>jobs-api-ats-feed-state</code> in your account, so the same domain is compared with its last check even when you batch domains differently (e.g. one Clay row per run). Use a different ID to keep separate watch lists.

## `firstRunOutputs` (type: `boolean`):

Mode new-jobs only. If off, the first run only records a baseline (no rows, no charges).

## `reportClosed` (type: `boolean`):

In new-jobs modes, output (and charge) a row for each job that was removed from the board since the last run.

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

Newest jobs first. In monitor mode this caps new jobs per company per run.

## `maxJobs` (type: `integer`):

Stop after this many dataset rows in total (all companies).

## `descriptionFormat` (type: `string`):

Markdown is clean and ready for LLMs/RAG; HTML is the cleaned original.

## `descriptionMaxChars` (type: `integer`):

0 = full text.

## `redactContacts` (type: `boolean`):

Recruiter/contact fields are never output; this also strips e-mails and phone numbers written inside the description text.

## `allowSlugGuess` (type: `boolean`):

If no ATS link is found on the website, try the company name on each ATS (e.g. bunq.com -> bunq.recruitee.com). Guesses are only accepted when the board's company name matches the domain, or when exactly one unverifiable board exists.

## `resolutionCacheDays` (type: `integer`):

Detected domain -> ATS mappings are cached in your account and not re-detected (or re-charged) within this period.

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

How many companies are processed at the same time.

## `workdayDepartments` (type: `boolean`):

Workday lists no department per job; the Actor re-queries the career site once per job-family group to add it (about 2x the list requests). Turn off for faster Workday runs.

## `maxDetailRequestsPerCompany` (type: `integer`):

Workday's list has no country/remote/employment type. When you filter on those, the newest N candidates per company get a detail request (rate-limited to ~2.5 requests/s per site).

## Actor input object example

```json
{
  "mode": "signals",
  "domains": [
    "n26.com"
  ],
  "searchInDescription": false,
  "includeJobsWithoutCountry": false,
  "firstRunOutputs": true,
  "reportClosed": true,
  "maxJobsPerCompany": 100,
  "maxJobs": 100,
  "descriptionFormat": "both",
  "descriptionMaxChars": 0,
  "redactContacts": true,
  "allowSlugGuess": true,
  "resolutionCacheDays": 30,
  "maxConcurrency": 4,
  "workdayDepartments": true,
  "maxDetailRequestsPerCompany": 300
}
```

# Actor output Schema

## `results` (type: `string`):

Every row in the default dataset (jobs, new/closed jobs and hiring-signal rows).

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

Job rows: company, title, department, location, country, workplace, type, seniority, posted date, ATS and job URL.

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

Jobs that are new or closed since the last run for the same filters / monitorId.

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

One flat hiring-signal row per company domain: open jobs, new and closed jobs, growth, top departments/locations, sample titles and URLs. Clay-ready.

## `llm` (type: `string`):

Job rows with the description as Markdown, for AI agents and RAG.

# 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 = {
    "domains": [
        "n26.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northloop-hq/jobs-api-ats-feed").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 = { "domains": ["n26.com"] }

# Run the Actor and wait for it to finish
run = client.actor("northloop-hq/jobs-api-ats-feed").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 '{
  "domains": [
    "n26.com"
  ]
}' |
apify call northloop-hq/jobs-api-ats-feed --silent --output-dataset

```

## MCP server setup

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

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/3RTWxucNlh4evmGpH/builds/mjeZT8LUvj8HLBuZK/openapi.json
