# Lever & Ashby Jobs Scraper: Career Site Job Feed (`fedsignals/career-site-jobs-feed`) Actor

Lever jobs scraper and Ashby jobs scraper: returns postings from companies' public Lever and Ashby job boards in one schema: normalized salary, seniority, remote/hybrid, description and apply URL. Only new jobs, plus closed-job alerts. Posting content belongs to the employers.

- **URL**: https://apify.com/fedsignals/career-site-jobs-feed.md
- **Developed by:** [FedSignals Data](https://apify.com/fedsignals) (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 $2.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

## Lever & Ashby Jobs Scraper: Career Site Job Feed

Many tech and growth companies publish their openings on **Lever** or **Ashby** job boards. This Actor reads those jobs **directly from Lever's and Ashby's public job-posting feeds**: Lever's postings API (`api.lever.co/v0/postings/<company>`) and Ashby's public job posting API (`api.ashbyhq.com/posting-api/job-board/<company>`). It doesn't scrape aggregators, doesn't log in and doesn't need a browser, so runs are fast, cheap and reliable. Every job comes out in **one normalized schema**: title, company, locations, remote, department, employment type, salary range normalized to a min, max, currency and period (plus an estimated yearly figure), seniority, workplace type (remote, hybrid or on-site), description (text or HTML), apply URL and posted/updated dates.

Give it Lever or Ashby board URLs, `lever:slug` / `ashby:slug` pairs or bare company slugs. It filters by keyword, location, remote, department, employment type, seniority, workplace type, minimum yearly pay and posting age. In **incremental mode it returns only jobs you haven't seen before, plus a `closed` record when a job you received disappears from its board**. That makes it a good fit for daily job alerts, job-board backfills, hiring-signal tracking and recruiting pipelines.

No API key or login is needed. **The job postings belong to the employers that published them**; the Actor passes on what each company publishes on its public board, with a link back to the original posting. It doesn't output recruiter or hiring-manager names, and personal email addresses inside descriptions are replaced with `[email removed]`.

### Supported sources

| Source | Board URL | Feed read |
|---|---|---|
| Lever | `https://jobs.lever.co/<company>` (EU: `https://jobs.eu.lever.co/<company>`) | Lever public postings API, `api.lever.co/v0/postings/<company>` |
| Ashby | `https://jobs.ashbyhq.com/<company>` | Ashby public job posting API, `api.ashbyhq.com/posting-api/job-board/<company>` |

Only these two are supported. Any other job board, or a company's own careers page, stops the run **before anything is fetched**, so no jobs are charged (only Apify's $0.00005 start fee applies), and the run message names the entries to change.

### What you can put in `companies`

| Input | Example |
|---|---|
| Board URL | `https://jobs.lever.co/spotify`, `https://jobs.ashbyhq.com/openai` |
| `lever:slug` or `ashby:slug` | `lever:palantir`, `ashby:ramp` |
| Bare slug (auto-detect) | `ramp` (checks Lever and Ashby and uses the board with more jobs; use a URL or `ats:slug` to pick one) |

You can also tick **starter lists**: 36 well-known companies (16 on Lever, 20 on Ashby) whose public boards were checked on Oct 29, 2026.

### Example input

```json
{
  "companies": ["https://jobs.lever.co/spotify", "ashby:openai", "ramp"],
  "keywords": ["data engineer", "machine learning"],
  "locations": ["united states", "new york", "san francisco"],
  "includeRemoteWithLocation": true,
  "seniority": ["senior", "staff", "lead"],
  "workplaceTypes": ["remote", "hybrid"],
  "postedWithinDays": 30,
  "onlyNew": true,
  "descriptionFormat": "text",
  "maxItems": 1000
}
```

### Example output

A new job (from our Oct 30, 2026 test on Spotify's Lever board; description shortened):

```json
{
  "recordType": "job",
  "jobId": "lever:spotify:47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d",
  "ats": "lever", "company": "Spotify", "companySlug": "spotify", "atsJobId": "47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d",
  "title": "Director of Sales - Emerging & Scaled (New Business)",
  "location": "New York, NY", "locations": ["New York, NY"], "country": "US",
  "remote": false, "workplaceType": "hybrid",
  "department": "Advertising", "team": "Advertising Sales - Emerging and Scaled Sales", "employmentType": "Full-time", "seniority": "director",
  "salaryMin": 137999.0, "salaryMax": 197142.0, "salaryCurrency": "USD", "salaryInterval": "year",
  "salaryMinYearly": 137999.0, "salaryMaxYearly": 197142.0,
  "salaryText": "$137,999 - $197,142", "salarySource": "description",
  "descriptionText": "Spotify's Emerging & Scaled (E&S) business is growing rapidly across the US and Canada, an ...",
  "jobUrl": "https://jobs.lever.co/spotify/47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d",
  "applyUrl": "https://jobs.lever.co/spotify/47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d/apply",
  "postedAt": "2026-10-23T13:35:03Z", "updatedAt": null,
  "firstSeenAt": "2026-10-30T18:43:59Z"
}
```

A closed job (incremental mode, when a job you received is no longer on its board). This one is illustrative: the job above is still open, and the dates show the format.

```json
{
  "recordType": "closed",
  "jobId": "lever:spotify:47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d", "ats": "lever", "companySlug": "spotify", "atsJobId": "47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d",
  "company": "Spotify", "title": "Director of Sales - Emerging & Scaled (New Business)",
  "jobUrl": "https://jobs.lever.co/spotify/47aeb6ee-f8c9-4f1e-9197-25c4c5676e5d",
  "location": "New York, NY",
  "firstSeenAt": "2026-10-30T18:43:59Z", "lastSeenAt": "2026-11-12T07:00:00Z", "closedAt": "2026-11-13T07:00:00Z"
}
```

Every job row has the same fields: `recordType, jobId, ats, company, companySlug, atsJobId, title, location, locations, country, remote, workplaceType, department, team, employmentType, seniority, salaryMin, salaryMax, salaryCurrency, salaryInterval, salaryMinYearly, salaryMaxYearly, salaryText, salarySource, descriptionText, descriptionHtml, jobUrl, applyUrl, postedAt, updatedAt, firstSeenAt`. A field is `null` when the posting doesn't include it. Closed rows carry only the fields shown in the second example.

**Salary.** Structured pay data from the posting is used first (`salarySource: "ats"`). If there isn't any, the Actor looks for a pay range written in the description, such as "$150,000 - $200,000" (`salarySource: "description"`). Equity, bonus and stipend amounts are ignored. Parsed salaries are best-effort, so check the job page before relying on them.

**Normalization.** `salaryInterval` is always one of `hour`, `day`, `week`, `month` or `year`, and `salaryCurrency` is an upper-case ISO code. `salaryMinYearly`/`salaryMaxYearly` are **estimates** in the job's own currency (hour × 2,080, day × 260, week × 52, month × 12); they are not currency-converted.

**Seniority** (`intern`, `entry`, `mid`, `senior`, `staff`, `lead`, `manager`, `director`, `vp`, `executive`) is taken from the job title first (e.g. "Senior", "Staff", "Principal", "Head of", "Engineer II"). It is `null` when there is no signal; "Product Manager" and similar titles are not tagged as people managers.

**Workplace type** is `remote`, `hybrid` or `onsite`, from the Lever or Ashby posting where it has one, otherwise inferred from the location and title text.

### Test results (build 0.1.9, Oct 30, 2026)

- **Both starter lists (16 Lever and 20 Ashby boards), no descriptions:** **6,053 jobs (Lever 3,440, Ashby 2,613), 0 board errors, 49 seconds.** 2,435 of them (40%) had a salary range.
- **Mixed input with full descriptions** (`https://jobs.lever.co/spotify`, `https://jobs.ashbyhq.com/openai`, `ashby:notion`, the bare slug `ramp` and an unknown slug): **1,221 jobs in about 4 seconds.** `ramp` was auto-detected on Ashby; the unknown slug was skipped for free and reported in `SUMMARY`.
- **Filtered run** ("data" / "machine learning", US plus remote, last 30 days, 36 starter boards): **64 jobs.**
- **Incremental:** a second `onlyNew` run with the same `stateKey` returned only jobs the first run had not delivered (no overlap).
- **Unsupported input:** a run listing a non-Lever/Ashby board or a careers page stops before fetching anything, with 0 jobs charged.

### Use cases

- **Job alerts and niche job boards.** Schedule a daily run with `onlyNew: true` and send new jobs to Slack, email, Google Sheets or your own site.
- **Recruiting and sourcing.** Watch target companies for specific roles, teams or locations.
- **Sales and market intelligence.** Hiring is a buying signal. A burst of "Data Engineer" or "Salesforce Admin" openings tells you what a company is investing in.
- **Labour-market and salary research.** Pay ranges published on Lever and Ashby postings, in one schema.

### Incremental mode

With `onlyNew: true` (the default), job IDs are stored in a named key-value store (`career-site-jobs-feed-state`) under your `stateKey`. Later runs skip jobs that were already delivered. A job is forgotten 45 days after it was **last seen** on its board, so long-open roles are never re-sent. Use a different `stateKey` for each saved task.

**Closed jobs.** With `trackClosedJobs: true` (the default in incremental mode), each run compares every board's full public list (not just your filtered matches) with the jobs you've received. A job that is gone gets one record with `recordType: "closed"` and `closedAt`. If a board returns no jobs at all (an outage or a removed board), closed detection is skipped for that board so you don't get false closures. Filter on `recordType` (or use the **Closed jobs** dataset view) to separate the two record types.

### Known limits

- **Only Lever and Ashby.** Other job boards and companies' own careers pages are not read; a run that lists one fails at the start with no job charges.
- **Company name.** Lever's and Ashby's feeds don't include the company's display name, so it comes from the starter list when the company is on it, otherwise from the slug (`openai` becomes "Openai"). `companySlug` is always exact.
- **`country`** is passed on as the board publishes it: usually a two-letter code on Lever (`US`) and a country name on Ashby (`United States`).
- Seniority and yearly pay are derived values. Treat them as labels for filtering, not as facts published by the employer. Salaries parsed from descriptions are best-effort.
- `includeRemoteWithLocation` keeps **all** remote jobs, including ones restricted to other countries ("Remote UK"). Add a country to `excludeKeywords` or check `location` if that matters.
- Personal email addresses in descriptions are redacted by pattern, so this is best effort.
- **0 jobs?** Since build 0.1.10 the status message says why. Either no listed job matched your filters (it names the active ones, e.g. `keywords`, `locations`, `remoteOnly`, `postedWithinDays`, so you know what to loosen), or every match was already delivered under this `stateKey` in `onlyNew` mode (turn `onlyNew` off or use a new `stateKey`), or the boards have no open jobs. A 0-job run charges no job events.
- The jobs are the companies' own postings. Respect each company's terms when republishing them, and link back with `jobUrl`.

### How much does it cost?

Pay per event: you pay only for the events below plus Apify's $0.00005 run-start fee. Platform compute is included in the price.

- **$2 per 1,000 jobs** ($0.002 per job delivered). In incremental mode you pay only for jobs you haven't received before.
- **$0.001 per closed-job record** (incremental mode with `trackClosedJobs` on), only when a job you received disappears from its board. Turn `trackClosedJobs` off to skip them.

Real examples from our test runs:

- **Quick-start input** (product designer jobs at Spotify, OpenAI and Linear): 10 jobs in our Oct 30 test = 10 × $0.002 = **about $0.02**; `maxItems` 20 caps it at $0.04.
- **Both starter lists (36 Lever and Ashby boards), once**: 6,053 jobs in our Oct 30 test = **about $12.11**. Use keywords, locations or `maxItems` to take only what you need.
- **Daily incremental alert**: you pay only for new jobs, so 5 new postings a day = 5 × $0.002 = **about $0.01 a day**.
- **Filtered search** (data and machine-learning roles, US or remote, last 30 days, 36 starter boards): 64 jobs = **about $0.13**.

Use `maxItems` and Apify's per-run spending limit to cap spend; the Actor stops cleanly when the limit is reached.

### Dates, time zones and currency

- `postedAt`, `updatedAt`, `firstSeenAt`, `lastSeenAt` and `closedAt` are ISO 8601 in UTC (`Z`). When a board gives only a date, it becomes midnight UTC that day.
- `salaryCurrency` is the ISO 4217 code for `salaryMin`/`salaryMax` (e.g. `EUR`, `GBP`, `USD`). When the pay appears only as a symbol in the description, `$` is read as USD, `£` as GBP and `€` as EUR.

### Other languages and regions

Works for Lever and Ashby boards in any country, including EU-hosted Lever boards (`jobs.eu.lever.co`). `country` and `salaryCurrency` come from each posting.

Also searched as: ofertas de empleo, vacantes, bolsa de trabajo (ES) · vagas de emprego, ofertas de trabalho (PT) · offres d'emploi (FR) · Stellenangebote, Jobbörse (DE).

### FAQ

**Which job boards are supported?**\
Lever (`jobs.lever.co`, read through Lever's public postings API at `api.lever.co/v0/postings`) and Ashby (`jobs.ashbyhq.com`, read through Ashby's public job posting API). Other job boards and companies' own careers pages are not read: a run that lists one stops before fetching anything and is not charged, and the message tells you which entries to change.

**Can it tell me when a job closes?**\
Yes. In incremental mode (`onlyNew`) with `trackClosedJobs` on, a job you received that disappears from its board comes back once as a `recordType: "closed"` row with `closedAt`, at $0.001 each. Empty boards are skipped so an outage doesn't look like mass closures.

**How are salary and seniority normalized?**\
Pay periods become hour, day, week, month or year with an upper-case currency code, plus estimated yearly figures (`salaryMinYearly`, `salaryMaxYearly`) in the job's own currency. Seniority (intern to executive) comes from the title; it is null when there is no signal.

**Do I need an API key or a login?**\
No. The Actor reads only the public job-posting feeds that Lever and Ashby publish for each company's board, with no login.

**How do I get only new jobs every day?**\
Turn on `onlyNew`, save a Task and schedule it daily. Each run returns only jobs you haven't received.

**Does it include salary?**\
When the company publishes it: as a structured range where the Lever or Ashby posting has one, otherwise parsed from the description where possible.

**Does it return recruiter names or emails?**\
No. Recruiter and hiring-manager names are not output, and personal email addresses inside a description are replaced with `[email removed]` (shared addresses such as jobs@ or careers@ are kept).

**Who owns the job postings?**\
The employers. The Actor passes on what each company publishes on its public Lever or Ashby board, with a link back to the original posting.

### Reliability

HTTP only, with no browser and no login. Requests identify the Actor with a descriptive User-Agent that includes a contact address, each job-board host gets its own polite rate limit (at least 0.25 s between requests, 0.5 s by default, at most 4 boards in parallel), and errors are retried with backoff. One failing board never fails the run: its error is recorded in the `SUMMARY` record (`boardErrors`, `perBoard`) and the run continues.

Measured on Apify as of Oct 29, 2026: 3 of 4 of our own test runs succeeded (75%), with a median run time of 5 seconds (longest 15 s) on small test inputs. It is a small sample from a new Actor; we will update it as runs accumulate. Build 0.1.9 local tests, Oct 30, 2026: both starter lists (36 Lever and Ashby boards) returned 6,053 jobs in 49 seconds with 0 board errors; a mixed input of Lever and Ashby URLs, an `ashby:` slug and a bare slug returned 1,221 jobs in about 4 seconds; an incremental rerun returned 5 new jobs with no overlap.

### Use it from AI agents (MCP)

Add this Actor as a tool in Claude Desktop, Cursor or any MCP client through the Apify MCP server:

```json
{
  "mcpServers": {
    "career-site-jobs-feed": {
      "url": "https://mcp.apify.com?tools=fedsignals/career-site-jobs-feed",
      "headers": { "Authorization": "Bearer YOUR_APIFY_TOKEN" }
    }
  }
}
```

### Use it from code (API)

One call runs the Actor and returns the dataset items. `maxTotalChargeUsd` caps what the run can charge.

Python:

```python
import requests

items = requests.post(
    "https://api.apify.com/v2/acts/fedsignals~career-site-jobs-feed/run-sync-get-dataset-items",
    params={"maxTotalChargeUsd": 1},
    headers={"Authorization": "Bearer YOUR_APIFY_TOKEN"},
    json={"companies": ["https://jobs.lever.co/spotify", "https://jobs.ashbyhq.com/openai", "https://jobs.ashbyhq.com/linear"], "keywords": ["product designer"], "onlyNew": False, "maxItems": 20},
    timeout=300,
).json()
print(len(items), "items")
```

JavaScript (Node 18+):

```js
const res = await fetch(
  "https://api.apify.com/v2/acts/fedsignals~career-site-jobs-feed/run-sync-get-dataset-items?maxTotalChargeUsd=1",
  {
    method: "POST",
    headers: { Authorization: "Bearer YOUR_APIFY_TOKEN", "Content-Type": "application/json" },
    body: JSON.stringify({"companies": ["https://jobs.lever.co/spotify", "https://jobs.ashbyhq.com/openai", "https://jobs.ashbyhq.com/linear"], "keywords": ["product designer"], "onlyNew": false, "maxItems": 20}),
  }
);
const items = await res.json();
console.log(items.length, "items");
```

### Related FedSignals Actors

- [Website Contact Scraper & Company Enrichment (Tech Stack)](https://apify.com/fedsignals/company-website-enricher): company data, tech stack and generic contacts from a domain
- [SEC Form D Scraper: EDGAR Startup Funding Rounds](https://apify.com/fedsignals/sec-form-d-monitor): new private funding rounds from SEC Form D filings
- [PDF, DOCX & PPTX to Markdown Converter for AI & RAG](https://apify.com/fedsignals/documents-to-markdown): PDF, Word and PowerPoint to AI-ready Markdown

### Feedback

Found a bug or need a filter or source? Open an issue on the Issues tab or email **fedsignals.alerts@gmail.com**.

This Actor is not affiliated with or endorsed by Lever, Ashby or the listed companies. Job posting content belongs to the employers that published it.

# Actor input Schema

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

Returns jobs from these companies' public job boards. One company per line. Accepts a Lever or Ashby job-board URL (jobs.lever.co/x, jobs.eu.lever.co/x, jobs.ashbyhq.com/x), 'lever:slug' or 'ashby:slug' (e.g. lever:palantir, ashby:ramp), or a bare slug (Lever and Ashby are both tried and the board with more jobs is used). Only Lever and Ashby are supported: a URL or 'ats:slug' for any other job board, or a company's own careers page, stops the run before anything is fetched or charged.

## `starterLists` (type: `array`):

Adds popular companies whose public boards were checked on Oct 29, 2026 (Lever 16, Ashby 20).

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

Returns only jobs whose title contains any of these (case-insensitive), e.g. engineer, data, sales.

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

Also look for your keywords in the job description, not only the title.

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

Drop jobs whose title contains any of these, e.g. 'intern', 'senior director'.

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

Keep jobs whose location text contains any of these, e.g. 'New York', 'London', 'Germany', 'US'.

## `includeRemoteWithLocation` (type: `boolean`):

When locations are set, remote jobs are kept too.

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

Keep only jobs flagged remote by the ATS or with 'Remote' in the location.

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

Keep jobs whose department or team contains any of these, e.g. 'Engineering', 'Sales'.

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

Jobs without a stated type are dropped when this is set.

## `seniority` (type: `array`):

Keep only these levels. The level is tagged from the job title (e.g. 'Senior', 'Staff', 'Head of', 'Intern'); jobs whose title gives no signal are 'unspecified'.

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

Keep only these workplace types (normalized from the ATS, or inferred from the location/title text).

## `minYearlySalary` (type: `integer`):

Keep only jobs whose stated pay range reaches at least this amount per year (annualized, in the job's own currency). Jobs without pay data are dropped when this is set.

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

Uses the ATS publish date. Jobs without a publish date are kept.

## `onlyNew` (type: `boolean`):

On: returns (and charges for) only jobs not delivered by an earlier run with the same key. Turn on for scheduled alerts.

## `trackClosedJobs` (type: `boolean`):

With 'Only new jobs' on: when a job delivered by an earlier run disappears from its board's public feed, push one record with recordType 'closed' (charged as a 'closed-job' event). Ignored when 'Only new jobs' is off.

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

Optional. Runs with the same key share memory. By default the key is derived from your companies and filters.

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

Descriptions make rows larger; 'none' skips them.

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

Maximum jobs returned (and charged) per run.

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

Boards read at the same time. Each job-board host is also rate-limited separately.

## `minRequestIntervalSec` (type: `number`):

Polite delay between requests to the same job-board host (at least 0.25 s).

## Actor input object example

```json
{
  "companies": [
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/openai",
    "https://jobs.ashbyhq.com/linear"
  ],
  "keywords": [
    "product designer"
  ],
  "searchDescription": false,
  "includeRemoteWithLocation": false,
  "remoteOnly": false,
  "onlyNew": true,
  "trackClosedJobs": true,
  "descriptionFormat": "text",
  "maxItems": 20,
  "maxConcurrency": 2,
  "minRequestIntervalSec": 0.5
}
```

# Actor output Schema

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

Job postings from public ATS job boards in one schema. One item per row; field definitions are in the dataset schema.

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

JSON summary of the run: jobs pushed, boards read, per-board counts and errors.

# 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://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/openai",
        "https://jobs.ashbyhq.com/linear"
    ],
    "keywords": [
        "product designer"
    ],
    "onlyNew": false,
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("fedsignals/career-site-jobs-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 = {
    "companies": [
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/openai",
        "https://jobs.ashbyhq.com/linear",
    ],
    "keywords": ["product designer"],
    "onlyNew": False,
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("fedsignals/career-site-jobs-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 '{
  "companies": [
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/openai",
    "https://jobs.ashbyhq.com/linear"
  ],
  "keywords": [
    "product designer"
  ],
  "onlyNew": false,
  "maxItems": 20
}' |
apify call fedsignals/career-site-jobs-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fedsignals/career-site-jobs-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/zNmMt7Ezp78xWzg58/builds/L3YXxxQ7M2H2NgkHo/openapi.json
