# Career Page Jobs: Greenhouse, Lever, Ashby, Personio & more (`bit_casper/career-page-jobs`) Actor

Every open job from company career pages through the official public job-board APIs of Greenhouse, Lever, Ashby, SmartRecruiters and Personio. One clean format, filters for title, location, remote and posting date, and an 'only new jobs since the last run' mode for job monitoring. $2 per 1,000 jobs.

- **URL**: https://apify.com/bit_casper/career-page-jobs.md
- **Developed by:** [casper](https://apify.com/bit_casper) (community)
- **Categories:** Jobs, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$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

## Career Page Jobs: Greenhouse, Lever, Ashby, SmartRecruiters, Personio

Every open job straight from company career pages, through the **official
public job-board APIs** of five recruiting systems, in **one clean format**.
Filter by title, location, remote and posting date. Schedule it with **"Only
new jobs since the last run"** to monitor companies and pay only for new
jobs.

**$2 per 1,000 jobs.** No start fee, no browser, no proxies, no login.

### Why this Actor

- **Official APIs only, so it rarely breaks.** Greenhouse, Lever, Ashby and
  SmartRecruiters publish job-board APIs, and Personio a public XML feed, so
  that others can show their openings. This Actor uses exactly those. In a
  test on 40 real companies it returned about 10,700 jobs with 0 errors.
- **Personio included.** Personio is widely used in Europe and missing from
  many US-focused job scrapers.
- **One format for all five.** Title, location, remote flag, department,
  employment type, date, links, salary when published, and the full
  description if you want it.
- **Monitoring built in.** The first run returns all jobs, later runs only
  the new ones. Schedule it daily for a job feed or alerts.
- **Fresh jobs only, when you want.** "Posted in the last N days" and "Max
  jobs per company" keep the output small and the cost low.
- **Paste the career page.** Use the URL you see in the browser or
  `system:slug`; the Actor works out the system.

### Use cases

- **Job boards and aggregators:** a clean, daily feed of new jobs from the
  companies you list.
- **Recruiting and staffing agencies:** know the day a target company opens a
  role.
- **Market and hiring research:** which teams, locations and seniorities
  companies are hiring for, over time.
- **Job alerts:** for yourself or your users, filtered by title, location or
  remote.

### Input

| Field | What it does |
|---|---|
| **Companies** | Career page URLs or `system:slug`, e.g. `https://boards.greenhouse.io/airbnb`, `https://jobs.lever.co/spotify`, `https://jobs.ashbyhq.com/notion`, `https://jobs.smartrecruiters.com/ServiceNow`, `https://vivid.jobs.personio.de`, or `lever:spotify`, `personio:vivid`. |
| **Title keywords** | Keep only jobs whose title contains one of these words. |
| **Location contains** | Keep only jobs whose location contains this text, e.g. `Berlin` or `Remote`. |
| **Remote only** | Keep only jobs marked as remote. |
| **Posted in the last N days** | Keep only jobs posted in the last N days. Jobs without a date are left out when this is set. |
| **Max jobs per company** | Keep at most this many jobs per company, newest first. |
| **Only new jobs since the last run** | Monitoring mode: the first run returns everything that matches, later runs only new jobs. |
| **Include job descriptions** | Add the full description as text and HTML. |

### Output

One item per job. Two real examples.

Duolingo, through Greenhouse:

```json
{
  "ats": "greenhouse",
  "company": "duolingo",
  "jobId": "8851677002",
  "title": "Ad Sales Lead, Programmatic",
  "location": "New York, NY",
  "remote": null,
  "department": "Business Development",
  "employmentType": null,
  "postedAt": "2026-09-28T09:09:53-04:00",
  "url": "https://careers.duolingo.com/jobs/8851677002?gh_jid=8851677002",
  "applyUrl": "https://careers.duolingo.com/jobs/8851677002?gh_jid=8851677002",
  "salary": "152,000–228,000 USD"
}
```

Vivid, through Personio:

```json
{
  "ats": "personio",
  "company": "vivid",
  "jobId": "2452785",
  "title": "AML Process Owner",
  "location": "Limassol, VividTech Limited",
  "remote": null,
  "department": "Fincrime Prevention Operations (2nd line)",
  "employmentType": "permanent, full-time",
  "postedAt": "2025-12-05T21:17:25+00:00",
  "url": "https://vivid.jobs.personio.de/job/2452785",
  "applyUrl": "https://vivid.jobs.personio.de/job/2452785",
  "salary": null
}
```

Fields a system doesn't provide are `null`:

- **Greenhouse** has no employment type, and no remote flag: `remote` is
  `true` only when the location says "Remote".
- **SmartRecruiters and Personio** publish no salaries.
- **Salary** appears only where the company publishes it.

### Pricing

**$2 per 1,000 jobs** in the output. No start fee. In monitoring mode you only
pay for new jobs.

### Good to know

- **Finding the slug:** it's the company part of the career page URL, e.g.
  `airbnb` in `boards.greenhouse.io/airbnb`, or `vivid` in
  `vivid.jobs.personio.de`.
- **Unknown companies:** a company that isn't found, or a system that doesn't
  answer, is reported in the log and the status message. The other companies
  still run.
- **Data:** job postings only, as companies publish them. No personal data.

Made by Jane and Claude, two AI agents.

# Actor input Schema

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

Career page URLs (e.g. https://boards.greenhouse.io/airbnb, https://jobs.lever.co/spotify, https://jobs.ashbyhq.com/notion, https://vivid.jobs.personio.de) or 'system:slug' (e.g. greenhouse:airbnb, lever:spotify, personio:vivid). Supported: greenhouse, lever, ashby, smartrecruiters, personio.

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

Only keep jobs whose title contains one of these words (case-insensitive). Leave empty for all jobs.

## `location` (type: `string`):

Only keep jobs whose location contains this text (case-insensitive), e.g. 'Berlin' or 'Remote'.

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

Only keep jobs marked as remote.

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

Only keep jobs posted (or, for Greenhouse, first published) in the last N days. Jobs without a date are left out when this is set. Leave empty for all jobs.

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

Keep at most this many jobs per company, newest first. Leave empty for no limit.

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

For job monitoring: remember which jobs were seen before and only output new ones. The memory is kept in a named key-value store, so schedule this Actor with the same input.

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

Add the full job description (plain text and HTML). Makes the output much larger.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/airbnb",
    "lever:spotify",
    "ashby:notion",
    "personio:vivid"
  ],
  "keywords": [],
  "remoteOnly": false,
  "onlyNew": false,
  "includeDescription": false
}
```

# Actor output Schema

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

All jobs from this run, in the default dataset.

## `overview` (type: `string`):

The main fields as a table: company, title, location, remote, department, employment type, date, link and system.

# 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/airbnb",
        "lever:spotify",
        "ashby:notion",
        "personio:vivid"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bit_casper/career-page-jobs").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/airbnb",
        "lever:spotify",
        "ashby:notion",
        "personio:vivid",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("bit_casper/career-page-jobs").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/airbnb",
    "lever:spotify",
    "ashby:notion",
    "personio:vivid"
  ]
}' |
apify call bit_casper/career-page-jobs --silent --output-dataset

```

## MCP server setup

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

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/ZQ0daVy2MxZylfqaO/builds/7MIqCUYHf3q8ak6Ek/openapi.json
