# Career Site Jobs API: Greenhouse, Workday, Lever + 7 more (`trap_check/career-site-jobs`) Actor

Search 1.6M+ open jobs from nearly 30,000 companies' own career sites (Greenhouse, Workday, Lever, Ashby, SmartRecruiters, Workable, BambooHR, Recruitee, Personio, iCIMS). Filter by keyword, location, remote, seniority, pay and job type. Daily new and closed jobs feeds. $3 per 1,000 jobs.

- **URL**: https://apify.com/trap_check/career-site-jobs.md
- **Developed by:** [Chris O'Connor](https://apify.com/trap_check) (community)
- **Categories:** Jobs, Lead generation, AI
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 96.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.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 Site Jobs API: Greenhouse, Workday, Lever + 7 more

Fresh job listings straight from companies' **own career sites**: nearly 30,000 hiring companies that use **Greenhouse, Workday, Lever, Ashby, SmartRecruiters, Workable, BambooHR, Recruitee, Personio or iCIMS**. Every company is checked once a day, so you get jobs the day they go up, without LinkedIn or Indeed reposts and without listings that were filled weeks ago.

Over 1.6 million open jobs, searchable by title keywords, location, country, remote/hybrid, seniority, pay, job type and company.

**No company list needed.** Most job scrapers make you supply the companies. Here they're already indexed: search "data engineer, remote, US" and get matches from all of them at once. You can still pick specific companies.

**$3 per 1,000 jobs**, full descriptions included at no extra cost. Most searches cost a few cents.

### Who it's for

- **Recruiters and sourcers**: see who is hiring for the roles you place, the day the job goes up.
- **Job boards and niche job sites**: fill your board with direct-from-employer jobs, and take filled ones down with the closed-jobs feed.
- **Sales and market research**: hiring is a buying signal. Track which companies are hiring for which teams, and where.
- **AI agents**: clean, predictable fields, the same for every job system. Works from the Apify MCP server and API.

### Why career-site data

Most job scrapers read LinkedIn or Indeed, where the same job appears many times, often reposted by agencies, and stays up long after it's filled. Career sites are the source: when a company posts a job it's there first, and when they close it, it's gone.

### How to use it

The form opens with the five things most people need: **keywords, countries, locations, workplace type and how many jobs**. Everything else is folded away under *More filters*, *Daily feed* and *Descriptions and job systems*.

**All new remote engineering jobs in the US, every morning**

- Job title keywords: `software engineer`, `data engineer`
- Countries: `US`, Workplace type: Remote
- Daily feed: **Only jobs new since my last run** on
- Schedule it daily (Schedules tab) and connect it to Google Sheets, Slack, a webhook or Zapier.

**A job board that stays clean**

- Your filters, plus **Only jobs new since my last run** and **Also list jobs that closed since my last run**.
- Each run gives you the new jobs to add and the closed jobs (`status: closed`) to remove.

**Full-time jobs, no senior roles, no agencies**

- Employment type: Full-time
- Leave out titles containing: `senior`, `principal`
- Leave out companies: any you don't want

**Every open job at a list of companies**

- Companies: `Stripe`, `https://jobs.lever.co/plaid`, `Ramp`. Leave keywords empty.

### Ready-made searches

One click, then change anything you like:

- [Remote software engineer jobs with salary (US)](https://apify.com/trap_check/career-site-jobs/examples/remote-software-engineer-jobs-salary)
- [New US jobs posted today](https://apify.com/trap_check/career-site-jobs/examples/new-jobs-posted-today-us)
- [Daily new jobs feed (new + closed jobs)](https://apify.com/trap_check/career-site-jobs/examples/daily-new-jobs-feed)
- [Nurse jobs posted this week (US)](https://apify.com/trap_check/career-site-jobs/examples/nurse-jobs-posted-this-week)
- [Internships posted in the last 14 days (US)](https://apify.com/trap_check/career-site-jobs/examples/entry-level-internship-jobs-us)
- [Companies hiring sales reps (hiring signals)](https://apify.com/trap_check/career-site-jobs/examples/companies-hiring-sales-reps)
- [Track what your competitors are hiring for](https://apify.com/trap_check/career-site-jobs/examples/competitor-hiring-monitor)

### What you see

Results open in a clean **Jobs** table: title, company, location, workplace type, pay (e.g. `$120k–150k / yr`), posted date and an apply link. Switch to **Job details** for every field, or **New and closed** for daily feeds.

### What you get for each job

| Field | Example |
|---|---|
| `title` | Senior Data Engineer |
| `company` | Ramp |
| `location` | New York, NY; Remote (US) |
| `country` | US |
| `workplaceType` | remote, hybrid or onsite |
| `seniority` | intern, junior, senior, lead, manager, director, executive |
| `department`, `employmentType` | Engineering, Full-time |
| `salary` | $189k–240k / yr (easy to read) |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | 189000, 240000, USD, year |
| `postedAt` | employer's posting date |
| `firstSeenAt` | when our daily check first found it |
| `status`, `closedAt` | open, or closed and when (closed-jobs feed) |
| `url` | the job page on the employer's site (apply here) |
| `sourceAts`, `companyId`, `id` | stable ids for de-duplication |
| `descriptionText`, `descriptionHtml` | full description (optional) |
| `visaSponsorship`, `experienceYears` | read from the description: yes / no / blank, and years asked for |

Pay is filled wherever the employer publishes it, either in the job system or (with descriptions on) in the job text. Country, remote and seniority are worked out from the location and title, so a small share may be blank.

### Pricing

- **$3 per 1,000 jobs** returned. Descriptions cost nothing extra.
- **Closed jobs: $1 per 1,000** (from Nov 21; free until then).
- Set a maximum charge per run in the run options to cap spend. Apify's free monthly credit covers about 1,600 jobs.

### Good to know

- Each company is checked about once every 24 hours, so a job appears within a day of being posted.
- `postedAt` comes from the employer. Workday only says "Posted 3 days ago", so for Workday it's accurate to the day.
- With **Only jobs new since my last run**, the first run returns everything matching your filters; later runs return only jobs first seen since the previous run. Give a feed a **Feed name** if you plan to tweak its filters but keep its place.
- Keywords match job titles by default. Choose "Title, company, location and department" for a broader search.
- Known staffing agencies and job resellers are left out, so results are mostly direct employers.

### FAQ

**How do I get jobs from every company on Workday, Greenhouse or Lever without a list of companies?**
Search here. Nearly 30,000 companies are already indexed and checked daily, so a search like `data engineer` + `US` returns matches from all of them. Most other scrapers need you to supply each company's careers page first.

**Is there an official API for all Greenhouse or Workday jobs?**
No. Greenhouse, Lever and Ashby publish a job feed per company, and Workday has no public jobs API at all. This tool reads each company's own public listings every day and puts them in one search with the same fields for every job system.

**How fresh are the jobs?**
Every company is checked about once every 24 hours. `firstSeenAt` tells you when we first saw a job, `postedAt` when the employer says it was posted.

**Can I get only the new jobs each day, and remove filled ones?**
Yes. Turn on **Only jobs new since my last run** and schedule a daily run. Add **Also list jobs that closed since my last run** to get the jobs employers took down, so a job board or dataset stays clean.

**Can I use it to fill a job board (backfill)?**
Yes, that's a main use. Every job links to the employer's own apply page, and known staffing agencies and job resellers are left out.

**Does it include LinkedIn or Indeed jobs?**
No. Only jobs from companies' own career sites, which is where they appear first and where they disappear when filled.

**Does it have salaries and job descriptions?**
Pay is included wherever the employer publishes it (common on Greenhouse, Lever and Ashby, rare on Workday). Full descriptions are included at no extra cost when you turn them on.

**How much does it cost?**
$3 per 1,000 jobs returned, and $1 per 1,000 closed jobs (from Nov 21). A search for 200 jobs costs about 60 cents. Apify's free monthly credit covers about 1,600 jobs.

**Can I use it from Google Sheets, Zapier, Make, n8n, Python or an AI agent?**
Yes. It's a standard Apify Actor: run it from the API or the Python and JavaScript clients, schedule it, connect it to Apify's integrations (Google Sheets, Zapier, Make, n8n, Slack, webhooks), or let an AI agent call it through the Apify MCP server.

**Is this data OK to use?**
It's the job listings employers publish on their careers pages so they can be found. No logins and no personal data. You're responsible for how you use it, as with any data.

### Feedback

Missing a company or a field you need? Open an issue in the Issues tab. New companies are added regularly.

# Actor input Schema

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

Words from the job title, e.g. "data engineer", "nurse" or "Account Executive". Each entry matches titles containing all its words; with several entries, a job matching any of them is returned. Keep them short: "nurse" finds more than "registered nurse ICU night shift". Leave empty for all jobs.

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

Country names or two-letter codes, e.g. United States, United Kingdom, Germany, India, or US, GB, DE, IN. Any country works. Leave empty for the whole world.

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

A city, state or region that must appear in the job's location, e.g. "Austin", "London", "Bavaria", "CA". A job matching any of them is returned. For a whole country, use Countries; for remote jobs, use Workplace type.

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

Remote, hybrid or on-site, as stated by the employer or found in the location text.

## `maxResults` (type: `integer`):

Stop after this many jobs. Newest first.

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

Worked out from the job title (e.g. "Senior", "Staff", "Intern", "Director").

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

As the employer labels the job (Full-time, Part-time, Contract...). About half of employers don't say, and those jobs are left out when you pick a type.

## `minSalary` (type: `integer`):

Only jobs whose posted pay range reaches this amount (in the job's own currency and period). Jobs without posted pay are left out.

## `onlyWithSalary` (type: `boolean`):

Only jobs where the employer published a pay range.

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

Uses the employer's posting date; when the employer gives none, the day we first saw the job.

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

Only these companies: a name ("Stripe"), a careers page URL (https://jobs.lever.co/acme) or a company id from earlier results. Leave empty for all companies.

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

Jobs whose title contains any of these are left out, e.g. "senior", "intern", "sales".

## `excludeCompanies` (type: `array`):

Jobs from these companies are left out: a name, a careers page URL or a company id.

## `excludeLocations` (type: `array`):

Jobs whose location contains any of these are left out, e.g. "London", "India", "Remote". Jobs with no location are kept.

## `excludeAgencies` (type: `boolean`):

Skip jobs posted by staffing and recruiting agencies (e.g. Robert Half, Aerotek), so you only get jobs from the actual employer.

## `searchIn` (type: `string`):

Title only (precise), or title + company + location + department (broader).

## `onlyNewSinceLastRun` (type: `boolean`):

Schedule this Actor daily and turn this on to get only jobs that appeared since the previous run of the same search. The first run returns everything that matches.

## `includeClosedJobs` (type: `boolean`):

Used with "Only new since my last run". From the second run on, jobs matching your search that the employer took down since the previous run are added too, with status "closed" and closedAt. Handy for keeping a job board or dataset clean.

## `feedName` (type: `string`):

Used with "Only new since my last run". Give a search a name to keep its bookmark when you edit its filters. Leave empty to track each different search separately.

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

Fetch each job's full description (text and HTML) from the employer's own job system. Slower, same price.

## `maxExperienceYears` (type: `integer`):

Leave out jobs asking for more years than this, e.g. 2 for junior roles. Jobs that don't say are kept. Turns on descriptions automatically.

## `descriptionLanguages` (type: `array`):

Keep only jobs written in these languages. Turns on descriptions automatically.

## `sources` (type: `array`):

Limit to companies using these job systems. Leave empty for all eleven.

## `excludeSources` (type: `array`):

Skip companies using these job systems.

## Actor input object example

```json
{
  "keywords": [
    "software engineer"
  ],
  "maxResults": 1000,
  "onlyWithSalary": false,
  "excludeAgencies": false,
  "searchIn": "title",
  "onlyNewSinceLastRun": false,
  "includeClosedJobs": false,
  "includeDescription": false
}
```

# Actor output Schema

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

No description

## `details` (type: `string`):

No description

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

No description

# 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 = {
    "keywords": [
        "software engineer"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("trap_check/career-site-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 = { "keywords": ["software engineer"] }

# Run the Actor and wait for it to finish
run = client.actor("trap_check/career-site-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 '{
  "keywords": [
    "software engineer"
  ]
}' |
apify call trap_check/career-site-jobs --silent --output-dataset

```

## MCP server setup

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