# Company Jobs Scraper: Workday, Greenhouse, Lever & Ashby (`jay_hong/jobboard-actor`) Actor

Get fresh job postings for any list of companies, read live from public job-board APIs. Works with Greenhouse, Lever, Ashby, Workable and Recruitee. Finds boards by name or domain, keeps published salaries, and can return only jobs that are new since your last run.

- **URL**: https://apify.com/jay_hong/jobboard-actor.md
- **Developed by:** [SeongJe Hong](https://apify.com/jay_hong) (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.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

## Company Jobs Scraper: Workday, Greenhouse, Lever & Ashby

**You pay only for confirmed company matches.**

Give it a list of companies and get back every open job they publish, in one clean table. Company Jobs Scraper reads each company's own job board at run time from nine applicant tracking systems (ATS): **Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters, Workday, Rippling and Gem**. Use it as a jobs API for company career pages: run it daily in "new" mode and you get only the postings that appeared since the last run.

- **Type a name, a domain or a URL.** "Canva", `zendesk.com` and `https://jobs.lever.co/spotify` all work. Every row says how its company was matched (`confidence`, `matchedVia`). Only a board URL, or a board the website you gave links to, counts as confirmed and is charged. A match found from the name alone is returned free and marked `medium`.
- **One schema for every ATS.** Title, department, locations, remote/hybrid/onsite, employment type, salary range, posting date, job URL and apply URL use the same field names whatever the source.
- **Salary where the employer publishes it.** Pay ranges come from the ATS's structured fields, with currency and period (year, month, hour).
- **New-since-last-run tracking.** Each row carries `changeType` (`new`, `updated`, `unchanged`, `removed`). Pay only for the rows you ask for.
- **Live data.** Jobs are fetched from each board's API during your run; there is no database in between.

### Who uses it

| You are | You use it to |
|---|---|
| Sales or partnerships team | Watch target accounts for hiring signals: a company posting its first "Head of Security" role is a buying signal. |
| Recruiter or talent-intelligence analyst | Track competitors' openings, team growth and published salary bands. |
| Job board or newsletter builder | Pull fresh postings from a curated list of companies every day, with a stable `id` for de-duplication. |
| AI agent builder | Give an agent a tool that answers "Which of these companies is hiring ML engineers in Berlin right now?" |

### Supported job boards

| ATS | Enter it as | Found from a company name? | Salary | Posting date |
|---|---|---|---|---|
| Greenhouse | `Stripe`, `https://boards.greenhouse.io/stripe`, `greenhouse:stripe` | Yes (published name checked) | When published | Yes |
| Lever | `Spotify`, `https://jobs.lever.co/spotify`, `lever:spotify`, EU: `https://jobs.eu.lever.co/acme` | Yes | When published | Yes |
| Ashby | `Notion`, `https://jobs.ashbyhq.com/notion`, `ashby:notion` | Yes | When published | Yes |
| Workable | `Hugging Face`, `https://apply.workable.com/huggingface`, `workable:huggingface` | Yes (published name checked) | No | Yes |
| Recruitee | `bunq`, `https://bunq.recruitee.com`, `recruitee:bunq` | Yes (published name checked) | When published | Yes |
| SmartRecruiters | `ServiceNow`, `https://jobs.smartrecruiters.com/Canva`, `smartrecruiters:Canva` | Yes (published name checked) | No | Yes |
| Workday | `Salesforce`, `https://salesforce.wd12.myworkdayjobs.com/External_Career_Site`, `workday:salesforce.wd12/External_Career_Site` | Yes | No | Day only, up to 30 days back |
| Rippling | `Rippling`, `https://ats.rippling.com/rippling/jobs`, `rippling:rippling` | Yes | No | No |
| Gem | `Retool`, `https://jobs.gem.com/retool`, `gem:retool` | Yes | No | Yes |

In our test run on 2026-10-04 (25 real boards, 4,130 jobs), the share of jobs with a structured salary range was 71% on Ashby, 30% on Recruitee, 25% on Greenhouse, 15% on Lever and 0% on Workable. It depends entirely on what each employer chooses to publish.

SmartRecruiters, Workday and Rippling rows have title, location, workplace type (when given), job URL and posting date (except Rippling), but no description: their job lists do not include it.

In our test on 2026-10-08 with 90 real company names in three lists (one of them chosen by an outside tester), the actor matched 64 to the right board. All were found from the name alone, so all were returned free as `medium`. One more free `medium` match was a subsidiary's Workday site (ASML's Berlin site, whose main site is closed to crawlers). The other 25 were not found and not charged: they use systems this actor does not read (iCIMS, Oracle, Avature, Deel, in-house career sites), do not show their board on their careers page under a token their name gives, or block automated requests. Typing each company's domain instead of its name gave 22 confirmed and charged matches, where the company's careers page links the board. No charged match was wrong.

### How to use it

1. Add companies to **Companies**, one per line: names, website domains, careers-board URLs or `ats:token`.
2. Optional: add **Keywords** (matched in titles), **Locations**, **Remote jobs only**, **Only jobs with a published salary** or **Posted within (days)**.
3. Pick an **Output mode**: `all` for every open job, `new` for jobs not seen before in this watchlist, `changes` for new, updated and removed jobs.
4. Run it. Results are in the **Jobs** table; the **Run summary** shows which board each company resolved to, and why any entry was not found.
5. To get daily alerts, save the input as a task, set output mode to `new` and add a schedule. Connect the dataset to Google Sheets, Slack, Zapier, Make or a webhook through Apify integrations.

#### Input example

```json
{
    "companies": ["Stripe", "huggingface.co", "https://jobs.lever.co/spotify", "ashby:ramp"],
    "keywords": ["engineer", "data"],
    "locations": ["Remote", "London"],
    "outputMode": "new",
    "watchlistName": "eng-roles",
    "descriptionFormat": "text",
    "maxJobs": 500
}
```

#### Output example

One row per job. This is a real posting from a public Lever board, with the description shortened:

```json
{
    "id": "lever:zoox:f4746da4-8eb8-43e2-b7ce-bf3c7cf9640d",
    "ats": "lever",
    "boardToken": "zoox",
    "jobId": "f4746da4-8eb8-43e2-b7ce-bf3c7cf9640d",
    "company": "zoox",
    "title": "Autonomy System Test Engineer",
    "department": "Software",
    "team": "Software Platforms and Product",
    "location": "Foster City, CA",
    "locations": ["Foster City, CA"],
    "countryCode": "US",
    "workplaceType": "hybrid",
    "employmentType": "full_time",
    "employmentTypeRaw": "Full-time",
    "salary": { "min": 144000, "max": 193000, "currency": "USD", "period": "year", "text": null },
    "url": "https://jobs.lever.co/zoox/f4746da4-8eb8-43e2-b7ce-bf3c7cf9640d",
    "applyUrl": "https://jobs.lever.co/zoox/f4746da4-8eb8-43e2-b7ce-bf3c7cf9640d/apply",
    "publishedAt": "2026-05-04T23:11:01.125Z",
    "updatedAt": null,
    "descriptionText": "Autonomous vehicles have some of the largest, most complex software ever shipped in a safety-critical environment. Solving that problem is one of the most excit…",
    "changeType": "new",
    "firstSeenAt": "2026-10-04T11:20:05.120Z",
    "boardUrl": "https://jobs.lever.co/zoox",
    "confidence": "exact",
    "matchedVia": "url",
    "query": "https://jobs.lever.co/zoox",
    "scrapedAt": "2026-10-04T11:20:05.120Z"
}
```

`company` is the name the ATS publishes. Lever and Ashby publish none, so the actor uses the name you typed, or the board token when you gave a URL.

#### Run summary

The `SUMMARY` record in the run's key-value store lists every input with its status (`resolved`, `not_found`, `invalid`, `duplicate`, `unsupported`, `error`, `skipped`), the board used, `confidence` and `matchedVia`, other boards found under the same name, and counts of jobs on the board, matched, returned, new, updated and removed. `totals.unconfirmed` counts the companies returned free as `medium`.

#### How a company is matched

How a name or domain is looked up:

1. **A domain or careers-page URL you give** (`zendesk.com`, `https://www.figma.com/careers`): the actor reads that site's careers pages (the page you gave, `/careers`, and `careers.` and `jobs.` on the domain) and takes the job boards they link to. Pages the site asks crawlers not to read, and pages that block the request, are skipped.
2. **Only when that finds no usable board, or for a plain name**: the actor reads the careers pages of `<name>.com` and tries the name as a board token on each ATS ("Hugging Face" → `huggingface`, `hugging-face`). Both are guesses from the name, so they are weighed alike.

Every row and every summary entry carries:

- `matchedVia`: `url` (you gave the board URL or `ats:token`), `site` (the website you gave links to the board), `name` (found from the company name alone).
- `confidence`:
  - `exact`: you gave a board URL or `ats:token`. Charged.
  - `high`: the website you gave links to the board, and the ATS publishes no company name (Lever, Ashby, Workday, Rippling, Gem) or the same name as your domain's, ignoring case, spaces and suffixes such as "Inc." (Greenhouse, Workable, Recruitee, SmartRecruiters). Charged.
  - `medium`: nothing confirms the match. Either the board was found from the name alone, even under the same published name (unrelated companies share names: the Recruitee board "GONG" is a Polish ad agency, not Gong; a Workday tenant found by name may be a subsidiary's site), or the website you gave links to a board published under a name other than your domain's (`toasttab.com` links the board named "Toast"). **Returned free.** Give the board URL, or the company's domain when its careers page links the board, to confirm it.

A board is not used at all when it has no jobs or only jobs posted over a year ago (ATSs keep empty and abandoned accounts under many company names), or when it was found from the name and the ATS publishes another company's name, even a longer one that starts with yours ("Wise" does not match "Wise Worksite Field Sales"). When no board qualifies, the entry is `not_found`, is not charged, and lists the boards it skipped under `alternatives`. To watch a company with no openings right now, give its board URL.

### Track only new jobs

Set **Output mode** to `new` and keep the same **Watchlist name** between runs. The actor remembers the jobs it has seen per watchlist and board in a named key-value store in your Apify account (`jobboard-watchlists`), so:

- The first run returns all current jobs, because nothing has been seen yet. For a baseline run, set **Max jobs per company** to 1: jobs beyond that cap are stored as seen (cost: about 1 row + 1 company check per company). Set it back to 0 for the following runs.
- Later runs return only jobs that were not on the board before.
- `changes` mode also returns jobs whose title, location, department, workplace type, employment type or salary changed (`updated`), and jobs that disappeared (`removed`). Description-only edits are ignored on purpose. Removed jobs are filtered by the title, location, workplace type, employment type and salary they had when last seen.
- If a run stops at **Max jobs per run** or at your spending limit, the new, updated and removed jobs it did not return come back on the next run.

### How much does it cost?

This actor uses pay-per-event pricing. You pay for:

| Event | Price | When it is charged |
|---|---|---|
| Job | $1.00 per 1,000 jobs ($0.001 each) | Each row from a confirmed match (`exact` or `high`) written to the dataset |
| Company checked | $0.50 per 1,000 companies ($0.0005 each) | Each confirmed company match. Unconfirmed (`medium`) and not-found companies are free. |
| Actor start | Apify's standard start fee | Once per run |

Examples:

- 20 companies, all open jobs (about 2,000 rows): 20 × $0.0005 + 2,000 × $0.001 = **about $2.01**.
- 100 companies checked every day in `new` mode, about 40 new jobs a day: $0.05 + $0.04 = **about $0.09 a day, $2.70 a month**.

Use **Max jobs per run** and Apify's maximum cost per run to cap spending. The actor stops cleanly at either limit.

### Use with AI agents (MCP)

This actor works as a tool for AI agents through the [Apify MCP server](https://mcp.apify.com). Each input field has a plain-language description, and the output uses stable field names.

- Add the actor to your MCP client (for example Claude or Cursor) through the Apify MCP server, then ask, for example: "Use Company Jobs Scraper to list remote data engineering jobs at Stripe, Ramp and Hugging Face posted in the last 7 days."
- Good agent inputs: `companies` (names or URLs), `keywords`, `locations`, `remoteOnly`, `postedWithinDays`, and `descriptionFormat: "none"` when the agent only needs titles and links (smaller, cheaper context).
- The run's status message gives a one-line result (for example "60 jobs from 4/5 companies (1 not found, 0 errors)"), and the `SUMMARY` record explains every miss so the agent can retry with a URL.

#### Call it from your code

```bash
curl -X POST "https://api.apify.com/v2/acts/jay_hong~jobboard-actor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["Stripe", "https://jobs.lever.co/spotify"], "keywords": ["engineer"], "descriptionFormat": "none"}'
```

### Limits

- Only companies whose job board runs on one of the nine ATSs above. iCIMS, Oracle Recruiting, SuccessFactors, Taleo, Eightfold, Deel, LinkedIn and Indeed are not supported. There is no search across all companies on an ATS; you supply the companies.
- Workday: the first career site the tenant lets crawlers read is used (for example Salesforce's `External_Career_Site`, not its separate intern site); pass a site URL to pick another. If a company's main site is closed to crawlers, that may be a subsidiary's site, which is why a Workday tenant found by name alone is `medium` and free. Workday's search returns at most 2,000 jobs per career site. Workday career sites that ask crawlers to stay away are skipped (`not_found`, not charged).
- Some companies link their careers page to a board that has no public feed, or load the link only in the browser. Those need the board URL.
- Recruitee will require an employer token for its public API from 2027-02-10. From that date Recruitee entries return `unsupported`.
- Personio and Pinpoint boards are not supported at this time. Entries for them return `unsupported` and are not charged.
- EU-hosted Greenhouse boards (`job-boards.eu.greenhouse.io`) are not supported at this time. Entries for them return `invalid` and are not charged.
- Greenhouse, Workday and Rippling publish no employment type, so the **Employment types** filter drops their jobs. Workable does not distinguish hybrid from onsite.
- Name lookups try likely board tokens ("Hugging Face" → `huggingface`, `hugging-face`). Companies that use an unusual token and do not link their board from their careers page need the board URL.
- Data is what each employer publishes. Salary and locations are copied from the ATS fields. Remote status comes from the ATS's remote field, or from the word "remote" or "hybrid" in the location when the ATS has no such field (Greenhouse). Nothing is generated by AI.

### FAQ

**Where does the data come from?**
From each ATS's public job-board feed, the same one the employer's own careers page uses. Greenhouse, Lever, Ashby, Recruitee, SmartRecruiters and Gem document these APIs for building careers pages and job listings; Workable documents its public account endpoint in its help center. For Workday and Rippling there is no documented API: the actor reads the public JSON their career sites load in the browser. To find a board, the actor also reads the HTML of the company's careers pages. It does not log in, does not run a browser, and does not use proxies.

**How fresh is the data?**
As fresh as the employer's board at the moment of your run. Nothing is served from a cache or a database.

**Why did a company return "not_found"?**
It uses an ATS this actor does not support, its careers page does not link a supported board and it uses an unusual board token, or the only boards under its name had no recent jobs or publish a different company name (for example a longer legal name that only starts with yours). The summary lists which ATSs and tokens were tried and the boards that were skipped. Paste the board URL to fix it.

**Can I get every job on Greenhouse or Lever?**
No. ATSs publish no directory of boards. You bring the list of companies.

**Does it collect personal data?**
It returns job postings only. Fields such as the per-job application mailbox some ATSs expose are dropped. Job descriptions are employer text and can occasionally name a contact person; handle the data under the rules that apply to you (for example GDPR).

**How fast is it?**
In our test run, 25 boards with 4,130 jobs took 29.6 seconds of fetching. A name lookup reads a few careers pages and tries several ATSs, so it takes longer than a board URL: 30 names took 100 to 170 seconds on 2026-10-08. Workday returns 20 jobs per request, so a site with 2,000 jobs takes about two minutes. The actor waits between requests to the same host (1 second for Lever and Workable), so very long lists take longer.

**Is `descriptionHtml` safe to show on my site?**
It is the employer's HTML exactly as the ATS publishes it. Sanitize it before rendering it in a web page, as you would any third-party HTML.

**Can I filter by salary amount?**
Turn on **Only jobs with a published salary**, then filter `salary.min` / `salary.max` in the dataset or your own code. Currencies and periods differ between jobs, so the actor does not convert them.

### Changelog

- 0.1 (2026-10): first version. Five ATSs, name/domain/URL lookup, change detection, pay-per-event.
- 2026-10-08: a board found from the company name alone is no longer charged, even when the ATS publishes the same company name. Before, "Gong" was charged for the Recruitee board of GONG, a Polish ad agency. Only a board URL or `ats:token`, or a board the website you gave links to, is charged.
- 2026-10-08: name lookups use a board only when it has open jobs and, where the ATS publishes one, the same company name. Before, an empty Workable account or a board of a company whose name only started the same way could be returned as a match and charged.
- 2026-10-08: added SmartRecruiters, Workday, Rippling and Gem. Names and domains are looked up on the company's careers pages first. Boards whose jobs are all over a year old no longer count as a match.

Company Jobs Scraper is not affiliated with or endorsed by Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters, Workday, Rippling or Gem.

# Actor input Schema

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

One company per line. Accepted forms: a company name ("Stripe"), a website domain ("stripe.com"), a careers-board URL ("https://jobs.lever.co/spotify", "https://boards.greenhouse.io/figma", "https://jobs.ashbyhq.com/ramp", "https://apply.workable.com/huggingface", "https://acme.recruitee.com", "https://jobs.smartrecruiters.com/Canva", "https://salesforce.wd12.myworkdayjobs.com/External_Career_Site", "https://ats.rippling.com/rippling/jobs", "https://jobs.gem.com/retool"), or "ats:token" ("greenhouse:figma", "lever:eu:acme", "workday:salesforce.wd12/External_Career_Site"). For a domain, the actor reads that site's careers pages for links to its job board; for a plain name (or when the site links none) it reads "<name>.com" and tries the name as a board token on each ATS. A board is used only when it has jobs posted in the last year and, where the ATS publishes a company name, the same name. Only confirmed matches are charged: a board URL or ats:token (confidence "exact"), or a board the website you gave links to ("high"). A match found from the name alone is returned free with confidence "medium", even when the ATS publishes the same company name; give the board URL to confirm it. URLs and ats:token skip the lookup (use one to watch a company with no openings right now). Personio and Pinpoint boards are not supported (status "unsupported", not charged). Up to 1000 entries.

## `outputMode` (type: `string`):

"all": every open job that matches your filters. "new": only jobs not seen in earlier runs of the same watchlist (the first run returns everything, because nothing was seen before). "changes": new jobs, jobs whose title, location, department, workplace, employment type or salary changed, and jobs that were taken down since the last run. Every job row has a changeType field (new, updated, unchanged, removed).

## `watchlistName` (type: `string`):

Name for the memory of jobs already seen, used by "new" and "changes" modes. Runs with the same name share that memory; use different names for separate trackers. Letters, digits, "-" and "\_" only.

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

Keep jobs whose title contains any of these words or phrases (case-insensitive, partial match: "engineer" also matches "Engineering Manager"). Leave empty to keep all jobs.

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

Drop jobs whose title contains any of these words or phrases (case-insensitive).

## `searchDescription` (type: `boolean`):

When on, keywords and exclude keywords are also matched against the job description, not only the title.

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

Keep jobs whose location contains any of these (case-insensitive), for example "Berlin", "New York", "Germany". Two- or three-letter entries such as "US" or "DE" match the country code or a whole word. "remote" matches remote jobs. Leave empty for any location.

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

Keep only jobs marked as remote by the ATS (or whose location says remote when the ATS has no remote field).

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

Keep only these employment types. Leave empty for all. Jobs whose ATS gives no employment type (Greenhouse, Workday, Rippling) are dropped when this filter is set.

## `requireSalary` (type: `boolean`):

Keep only jobs where the employer published a structured pay range through the ATS (available on Greenhouse, Lever, Ashby and Recruitee boards that choose to publish it). Workable, SmartRecruiters, Workday, Rippling and Gem jobs have no salary field, so this drops them.

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

Keep jobs first published in the last N days. Jobs without a published date are kept (Rippling publishes none). Workday shows older postings only as "30+ days ago": they are dropped for N under 30 and kept above.

## `atsPlatforms` (type: `array`):

Limit the lookup of names and domains to these ATSs. Leave empty to try all of them. Board URLs and ats:token entries are always used as given.

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

"text" returns plain text (best for AI agents and spreadsheets), "html" the original HTML, "both" both fields, "none" no description (smallest output). SmartRecruiters, Workday and Rippling jobs come without a description.

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

Stop after this many job rows in total. Protects your budget: each row is one charged "job" event. In "new" and "changes" modes, jobs cut off by this limit are returned again on the next run.

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

Return at most this many jobs per company (newest first). 0 means no per-company limit. Jobs beyond this limit are treated as seen and are not returned later.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/figma",
    "Ramp",
    "huggingface.co",
    "zendesk.com"
  ],
  "outputMode": "all",
  "watchlistName": "default",
  "keywords": [
    "engineer",
    "product manager"
  ],
  "excludeKeywords": [
    "intern",
    "senior"
  ],
  "searchDescription": false,
  "locations": [
    "London",
    "Remote"
  ],
  "remoteOnly": false,
  "requireSalary": false,
  "descriptionFormat": "text",
  "maxJobs": 1000,
  "maxJobsPerCompany": 0
}
```

# Actor output Schema

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

One row per job posting (or removed posting in "changes" mode).

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

Per company: which board was used (ATS, token, confidence, matchedVia), alternatives found, jobs on the board, jobs returned, new/updated/removed counts, and why an entry was not found. totals.unconfirmed counts companies returned free with confidence medium.

# 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": [
        "https://boards.greenhouse.io/figma",
        "Ramp",
        "huggingface.co",
        "zendesk.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jay_hong/jobboard-actor").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": [
        "https://boards.greenhouse.io/figma",
        "Ramp",
        "huggingface.co",
        "zendesk.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jay_hong/jobboard-actor").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": [
    "https://boards.greenhouse.io/figma",
    "Ramp",
    "huggingface.co",
    "zendesk.com"
  ]
}' |
apify call jay_hong/jobboard-actor --silent --output-dataset

```

## MCP server setup

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

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/ijcLefJugvweIcEdk/builds/zEcVc7OjDBD10MHX5/openapi.json
