# Career Site Jobs API: Greenhouse, Lever, Ashby, Workday +4 (`ailu_studio/career-site-jobs-api`) Actor

Pull every open job with full description and salary from any company careers site on Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Recruitee, Workable or Personio. No login, no proxies.

- **URL**: https://apify.com/ailu_studio/career-site-jobs-api.md
- **Developed by:** [Ailu Studio](https://apify.com/ailu_studio) (community)
- **Categories:** Jobs, Lead generation, Agents
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job postings

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Site Jobs API: every open job with full description and salary from Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Recruitee, Workable and Personio

Give this Actor a list of company careers pages and get **every open job** back as clean rows: title, department, locations, remote flag, employment type, posting date, salary when the company publishes it, the **full job description** (plain text or HTML) and the apply link. It reads the same public, unauthenticated job-board endpoints that power each company's careers site, so there is no login, no proxy and no browser. Eight ATS platforms are covered: Greenhouse, Lever (global and EU), Ashby, Workday, SmartRecruiters, Recruitee, Workable and Personio.

> Not affiliated with Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Recruitee, Workable or Personio. Job content belongs to the employers who published it. Removal requests: open a ticket in the **Issues** tab of this Actor; verified requests are handled within 5 business days.

### Use cases

- **Job feeds and job boards**: pull full postings from hundreds of companies into your own database or site.
- **Sales and recruiting signals**: see what roles a target account is hiring for, with locations and seniority in the description.
- **Salary and market research**: structured salary fields from Lever, Ashby and Recruitee, descriptions for the rest.
- **AI agents**: one call returns ready-to-read text for matching, summarising or classifying roles.
- **Change tracking**: pair it with the companion Actor *Job Change Tracker* when you only want new, updated and removed postings.

### Input

| Field | Default | Meaning |
|---|---|---|
| `companies` | two demo boards | Careers URLs (`https://boards.greenhouse.io/airbnb`, `https://jobs.lever.co/palantir`, `https://jobs.ashbyhq.com/ramp`, `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`, `https://jobs.smartrecruiters.com/Ubisoft2`, `https://bunq.recruitee.com`, `https://apply.workable.com/huggingface/`, `https://nextbike.jobs.personio.de`), `platform:slug`, or bare slugs (probed on every platform except Workday). |
| `keywords` | – | Keep jobs whose title or description contains any of these words (case-insensitive). |
| `locations` | – | Keep jobs whose location contains any of these strings. `Remote` also matches remote-flagged jobs. |
| `remoteOnly` | `false` | Only remote-flagged jobs. |
| `includeDescription` | `true` | Return the full description. Off = lighter and faster listing. |
| `descriptionFormat` | `text` | `text`, `html` or `both`. |
| `maxDescriptionChars` | 20000 | Truncate very long descriptions. |
| `maxJobsPerCompany` | 1000 | Cap per company after filtering. |
| `maxItems` | 500 | Cap for the whole run. |
| `workdayMaxDetails` | 300 | Workday needs one request per job for the description; beyond the cap jobs come without it. |
| `minRequestIntervalMs` | 300 | Politeness delay per job-board host. |

```json
{ "companies": ["https://jobs.lever.co/palantir", "https://jobs.ashbyhq.com/ramp", "stripe"], "keywords": ["engineer"], "locations": ["Remote", "London"], "maxItems": 1000 }
```

### Output

| Field | Type | Meaning |
|---|---|---|
| `id` | string | Stable key `platform:companySlug:sourceId`. |
| `source` | string | `greenhouse`, `lever`, `lever-eu`, `ashby`, `workday`, `smartrecruiters`, `recruitee`, `workable`, `personio`. |
| `company`, `companySlug` | string | Display name and board slug (Workday: `tenant/site`). |
| `title`, `department`, `team` | string | As published. |
| `locations` | string\[] | Locations as published. |
| `isRemote`, `workplaceType` | boolean, string | Remote flag and `remote` / `hybrid` / `onsite` when known. |
| `employmentType` | string | Full-time, contract, intern, etc. |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryInterval`, `salaryRaw` | number, string | Structured salary when published (Lever, Ashby, Recruitee); otherwise `null`. |
| `postedAt`, `updatedAt` | ISO 8601 | Publication and last edit time when the platform provides it. |
| `url`, `applyUrl` | string | Public posting and application links. The Actor never applies. |
| `country` | string | Workday only. |
| `descriptionText`, `descriptionHtml` | string | Full description in the requested format(s). |
| `fetchedAt` | ISO 8601 | Run time. |

```json
{
  "id": "ashby:ramp:34413f8d-26bf-4bbc-8ade-eb309a0e2245", "source": "ashby", "company": "Ramp", "companySlug": "ramp",
  "title": "Security Engineer, Cloud", "department": "Engineering", "team": "Security", "locations": ["New York, NY (HQ)", "Remote (US)"],
  "isRemote": true, "workplaceType": "hybrid", "employmentType": "Full Time",
  "salaryMin": 211400, "salaryMax": 260000, "salaryCurrency": "USD", "salaryInterval": "year", "salaryRaw": "$211.4K – $260K",
  "postedAt": "2026-10-28T15:02:11.000Z", "url": "https://jobs.ashbyhq.com/ramp/34413f8d-…", "applyUrl": "https://jobs.ashbyhq.com/ramp/34413f8d-…/application",
  "descriptionText": "ABOUT RAMP Ramp is building the smart infrastructure for finance teams …", "fetchedAt": "2026-11-03T15:00:00.000Z"
}
```

The run summary (jobs found, matched and returned per company, errors) is stored in the `OUTPUT` record of the key-value store.

### How it works and limits

- One request per board for Greenhouse, Lever, Ashby, Recruitee, Workable and Personio (descriptions are included in the board feed). SmartRecruiters and Workday need one extra request per job for the description; both are capped (`workdayMaxDetails`, 300 by default) and rate-limited per host.
- Workday lists 20 jobs per request, so a 2,000-job site takes about 100 list requests plus the detail requests. Use `keywords`/`locations` and the caps to keep runs small. Workday `postedAt` has day precision.
- Salary is returned only where the platform publishes a structured range. Greenhouse, Workday, SmartRecruiters and Workable rarely do.
- Unlisted or inactive postings are skipped (Ashby `isListed:false`, non-public SmartRecruiters postings, unpublished Recruitee offers). Workable's public widget endpoint is undocumented and may change.
- One failing company never fails the run; it is reported in the summary and the Actor finishes with the other companies.

### Pricing

Pay per result: **$1.00 per 1,000 jobs** (`job` event). Platform usage is billed separately by Apify. Jobs dropped by your filters are not charged.

### Legal

Not affiliated with any of the ATS vendors. Uses only their public job-board endpoints (Greenhouse Job Board API, Lever Postings API, Ashby Job Posting API, Workday careers JSON, SmartRecruiters Posting API, Recruitee offers API, Workable widget API, Personio XML feed). Read-only; never submits applications. Respect the employers' terms when you reuse the content.

### FAQ

**How do I find a company's board?** Open their careers page and copy the URL; it contains the platform host (`boards.greenhouse.io`, `jobs.lever.co`, `jobs.ashbyhq.com`, `*.myworkdayjobs.com`, `jobs.smartrecruiters.com`, `*.recruitee.com`, `apply.workable.com`, `*.jobs.personio.de`). A bare slug such as `stripe` is probed on every platform except Workday.

**Why is a Workday job missing its description?** Descriptions need one request per job; raise `workdayMaxDetails` or narrow the listing with filters.

**Can I only get what changed since yesterday?** Use the companion Actor *Job Change Tracker* (same platforms), which keeps a snapshot per watchlist and returns new, updated and removed jobs.

**Does it support iCIMS, Taleo, BambooHR or Teamtailor?** Not yet. Workday is supported.

# Actor input Schema

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

Careers-page URLs or board slugs. Examples: "https://boards.greenhouse.io/airbnb", "https://jobs.lever.co/palantir", "https://jobs.ashbyhq.com/ramp", "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite", "https://jobs.smartrecruiters.com/Ubisoft2", "https://bunq.recruitee.com", "https://apply.workable.com/huggingface/", "https://nextbike.jobs.personio.de", or "platform:slug" (greenhouse:, lever:, lever-eu:, ashby:, smartrecruiters:, recruitee:, workable:, personio:). A bare slug like "stripe" is probed on every platform except Workday (Workday needs its URL).

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

Only return jobs whose title or description contains at least one of these words (case-insensitive). Example: \["engineer", "data"]. Leave empty for all jobs.

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

Only return jobs whose location contains one of these strings (case-insensitive), e.g. \["London", "Remote"]. "Remote" also matches jobs flagged remote.

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

When true, only jobs the platform marks as remote are returned.

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

Return the full job description. Turn off for a lighter, cheaper listing (title, locations, dates, links only). Workday and SmartRecruiters need one extra request per job for descriptions.

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

Plain text is best for AI processing and spreadsheets; HTML keeps headings and bullet lists.

## `maxDescriptionChars` (type: `integer`):

Descriptions longer than this are cut (default 20000 characters, which keeps almost every posting intact).

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

Cap per company after filtering (default 1000). Workday boards with more jobs than this are read partially.

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

Upper limit on returned rows for the whole run (default 500). Raise it for full exports.

## `workdayMaxDetails` (type: `integer`):

Workday needs one request per job for the description; jobs beyond this cap are returned without description (default 300).

## `minRequestIntervalMs` (type: `integer`):

Politeness delay between two requests to the same job-board host (default 300 ms).

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/airbnb",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ramp",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "https://apply.workable.com/huggingface/"
  ],
  "remoteOnly": false,
  "includeDescription": true,
  "descriptionFormat": "text",
  "maxDescriptionChars": 20000,
  "maxJobsPerCompany": 1000,
  "maxItems": 500,
  "workdayMaxDetails": 300,
  "minRequestIntervalMs": 300
}
```

# Actor output Schema

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

All rows in the default dataset.

# 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",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "https://apply.workable.com/huggingface/"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ailu_studio/career-site-jobs-api").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",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ramp",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
        "https://apply.workable.com/huggingface/",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ailu_studio/career-site-jobs-api").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",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ramp",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "https://apply.workable.com/huggingface/"
  ]
}' |
apify call ailu_studio/career-site-jobs-api --silent --output-dataset

```

## MCP server setup

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

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/OFLbCQTdmdgKIqPha/builds/S9umS3vdD8JGS1cCx/openapi.json
