# Career Site Jobs API: Search Company Job Boards, New Jobs Feed (`zaiq/career-site-jobs-api`) Actor

Search jobs straight from company career sites by title, place, company, words and time, from an index refreshed about every six hours. Full text and direct apply links. A named feed returns only what is new. For job boards, recruiters and sales teams watching who is hiring. $3 per 1,000 jobs.

- **URL**: https://apify.com/zaiq/career-site-jobs-api.md
- **Developed by:** [Zaiq](https://apify.com/zaiq) (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.40 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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: search jobs straight from company job boards

![Career Site Jobs API: Search Company Job Boards, New Jobs Feed](https://api.apify.com/v2/key-value-stores/4VJNANhwKgqPpXtAi/records/hero-career-site-jobs-api.jpg)

Search **jobs straight from company career sites** by **title, place, company, words in the text and time**. Every job comes from a company's own board on **Greenhouse, Lever or Ashby**, with the **full description and a direct apply link**: about **330,000 open jobs from 11,700 companies**.

Name a **feed** and schedule it, and every run returns **only the jobs new since the last one**. Built for **job boards**, **recruiters**, **sales teams following who is hiring** and **labour-market research**, at **$3 per 1,000 jobs**.

### What you get

| Field | What it holds |
|---|---|
| The job | `jobId`, `title`, `description` or `descriptionHtml`, `department`, `employmentType`, `salary`, `isRemote` |
| The place | `location`, `country` |
| The employer | `company`, `ats`, `board` |
| The dates | `postedAt`, `updatedAt`, `firstSeenAt`, `lastSeenAt`, `closedAt` |
| The links | `url`, `applyUrl` |

### What people use it for

- **Fill a job board:** add fresh employer jobs with apply links, automatically, every day
- **Hiring signals for sales:** see which companies just started hiring for what your product helps with
- **Recruitment research:** find every company hiring for a role in a place
- **Competitor watch:** follow what a rival is hiring for, by company name
- **Labour-market data:** track roles, skills and pay across thousands of employers
- **AI agents:** a searchable jobs source inside any workflow

### How to use it

1. Enter **job titles** and, if you want, **places**, **countries** or **companies**.
2. Choose **Posted within**.
3. For a daily feed, give it a **feed name** and schedule the run.
4. Press **Start** and download the rows.

### Input

| Field | Example | Notes |
|---|---|---|
| Job titles | software engineer | Any line can match. Words in one line must appear together. |
| Leave out titles with | intern | Removes unwanted roles. |
| Places | London | Words in the job's location, or Remote. |
| Countries | US, GB, DE | Two-letter codes. |
| Remote jobs only | off | Only jobs marked remote. |
| Posted within | Last 7 days | From the last hour to any time. |
| Feed name | my-job-board | Later runs return only what is new. |
| Most jobs a run | 1000 | Up to 20,000. |
| Words in the description | Kubernetes | Searches the full text. |
| Companies | Example Inc | Only these employers. |
| Career systems | Greenhouse | Empty means all three. |
| Description | Plain text | Or HTML, both, or none. Same price. |
| Closed jobs instead | off | Jobs that left their board, kept 90 days. |

### Output

Each result is one row in the run's dataset (download it as JSON, CSV, Excel, XML or HTML, or read it through the API). An example row (values shortened):

```json
{
  "kind": "job",
  "jobId": "greenhouse:examplecorp:4749457",
  "title": "Software Engineer, Platform",
  "company": "Example Corp",
  "location": "Remote, US",
  "country": "US",
  "isRemote": true,
  "department": "Engineering",
  "employmentType": "Full-time",
  "salary": "$100,700 - $167,800",
  "postedAt": "2026-10-30T16:08:45Z",
  "updatedAt": "2026-10-30T16:08:45Z",
  "firstSeenAt": "2026-11-01T19:46:12Z",
  "lastSeenAt": "2026-11-02T01:48:03Z",
  "closedAt": null,
  "url": "https://job-boards.greenhouse.io/examplecorp/jobs/4749457",
  "applyUrl": "https://job-boards.greenhouse.io/examplecorp/jobs/4749457",
  "ats": "greenhouse",
  "board": "examplecorp",
  "description": "About the role..."
}
```

A record named `SUMMARY` in the run's key-value store says what each input returned, with any notes (for example an account that does not exist), what was charged and how much traffic the run used.

### Pricing

- **$3 per 1,000 jobs** on Free and Bronze, $2.70 on Silver, $2.40 on Gold, less above, with the description included.
- **$0.01 a run** to start.
- A search with no jobs, or a feed with nothing new, costs only the start fee. The Free plan returns 20 jobs a run.

What typical jobs cost at the list price:

| Job | Cost |
|---|---|
| 100 jobs | $0.31 |
| 5,000 jobs | $15.01 |
| A daily feed of 300 new jobs | $0.91 a day |

On Apify's Scale and Business plans the per-event prices are lower (Store discounts). Set **Maximum cost per run** and the Actor stops cleanly when it is reached: you never pay more than that.

### Tips

- Use a **feed name** and a schedule: you pay only for jobs you haven't had.
- Search by **company** to follow one employer's hiring.
- **Closed jobs** with a **feed name** tell a job board which ads to take down: each run returns only the jobs closed since the last one.
- `salary` is what the employer states, read from the system or the text, so it is often empty.

### Use it through the API

**Python**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("zaiq/career-site-jobs-api").call(run_input={"titles": ["software engineer"], "postedWithin": "7d", "maxJobs": 10})
for row in client.dataset(run.default_dataset_id).iterate_items():
    print(row)
```

**JavaScript**

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('zaiq/career-site-jobs-api').call({"titles": ["software engineer"], "postedWithin": "7d", "maxJobs": 10});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

**HTTP (one call, results back)**

```bash
curl -X POST 'https://api.apify.com/v2/acts/zaiq~career-site-jobs-api/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>' \
  -H 'Content-Type: application/json' \
  -d '{"titles": ["software engineer"], "postedWithin": "7d", "maxJobs": 10}'
```

### Integrations and schedules

- **Schedules:** run it every hour, day or week from the Apify Console (Schedules) and keep a history of results.
- **Make, Zapier, n8n, Google Sheets, Slack, Airtable:** connect it through Apify's integrations, or send each finished run to a **webhook**.
- **Datasets:** results stay in the run's dataset; export them or read them by API whenever you need them.

### Use it with AI agents (MCP)

Add Apify's MCP server with this Actor already pinned (`https://mcp.apify.com?tools=zaiq/career-site-jobs-api`) to Claude, ChatGPT, Cursor, VS Code or any MCP client. The agent can find this Actor and run it for you: ask it for Find remote data engineer jobs posted this week at companies on Ashby and list who is hiring most. AI agents can also pay for runs directly through Apify's agentic payments.

### Limits

- **Coverage:** about 11,700 company boards and 330,000 open jobs on Greenhouse, Lever and Ashby at launch. A company on another system won't appear, so this is not every job on the internet.
- **Some boards belong to recruiters, staffing firms or franchises** rather than one employer, and a few post the same job for many towns. Put words like **staffing, recruiting, talent, personnel** in **Leave out companies** to drop most of them.
- **Freshness:** boards are re-read about every six hours, so a job can take that long to appear.
- `country` is read from the location words where the employer doesn't state it, so a vague location such as Remote stays blank, about 7% of jobs. A job in several countries carries the first one.
- `postedAt` is the date the employer's system gives. A company can repost an old job as new.
- Job descriptions belong to the employers. It's for you to check your use of them fits, especially if you publish them.
- Companies and jobs only: no people are looked up or collected, though an employer's own job text sometimes names a contact.

### FAQ

**Where do the jobs come from?**

The public job board feeds of Greenhouse, Lever and Ashby, which those systems publish for outside use. Our server re-reads them about every six hours. The starting list of boards is LastRound AI's ATS Company Directory (CC BY 4.0, github.com/fyrosofttech/lastroundai-hiring-data).

**How is a feed different from Posted within?**

A feed remembers where its last run stopped and carries on from there, so nothing is repeated or missed, even if a run hits its limit. Posted within still applies, so an old job on a newly added board stays out.

**Is this every job at a company?**

It is every job on that company's public board on these systems. Jobs a company lists elsewhere won't appear.

**Can I get closed jobs?**

Yes. Switch on Closed jobs, newest closures first. They are kept for 90 days after leaving the board, and Posted within then counts from when the job closed. Add a feed name to get only the jobs closed since the last run.

**Do I need any keys?**

No.

### Related Actors from Zaiq

- [indeed-jobs-scraper](https://apify.com/zaiq/indeed-jobs-scraper): job ads from Indeed in 62 countries
- [ats-jobs-scraper](https://apify.com/zaiq/ats-jobs-scraper): jobs from career systems you name by board
- [google-jobs-scraper](https://apify.com/zaiq/google-jobs-scraper): Google's job listings

### Support

Questions, a site that changed, or a field you need? Open an issue on this Actor's **Issues** tab: we answer there, usually within a day.

***

Also found as: career site jobs API, ATS jobs API, Greenhouse jobs scraper, Lever jobs API, Ashby jobs API, job posting API, jobs data feed, hiring signals, job board feed.

# Actor input Schema

## `titles` (type: `array`):

Words that must be in the job title. Any line can match; words in one line must appear together, such as software engineer.

## `titlesExclude` (type: `array`):

Jobs with these whole words in the title are left out, such as internship or senior.

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

Words in the job's location, such as London, Germany, or Remote. Empty means anywhere.

## `locationsExclude` (type: `array`):

Jobs with these words in the location are left out.

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

Such as US, GB or DE. Read from the location where the job doesn't state it, so a vague location may be missed.

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

Only jobs the employer marks as remote, or that say so in the location.

## `postedWithin` (type: `string`):

How new the job is, by the date the employer's system gives. With Closed jobs on, it counts from when the job closed.

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

Give the run a name and schedule it. Each run carries on from where the last one stopped, so nothing is repeated or missed, even when a run hits its limit.

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

The run stops here.

## `descriptionWords` (type: `array`):

Only jobs whose text holds one of these, such as Kubernetes or visa sponsorship.

## `descriptionWordsExclude` (type: `array`):

Jobs whose text holds these are left out.

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

Only jobs at these companies. Words in the name are enough.

## `companiesExclude` (type: `array`):

Jobs at companies with these words in the name are left out, such as recruiters you don't want.

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

Only these systems. Empty means all.

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

Same price whichever you choose.

## `closedJobs` (type: `boolean`):

Jobs that left their board, newest closures first, kept for 90 days. With a feed name, only those closed since the last run. For job boards taking down dead ads.

## Actor input object example

```json
{
  "titles": [
    "software engineer",
    "data engineer"
  ],
  "titlesExclude": [
    "intern",
    "internship"
  ],
  "locations": [],
  "remoteOnly": false,
  "postedWithin": "7d",
  "maxJobs": 100,
  "companiesExclude": [
    "staffing",
    "recruiting",
    "recruitment",
    "talent",
    "personnel"
  ],
  "descriptionFormat": "text",
  "closedJobs": false
}
```

# Actor output Schema

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

Dataset: the results.

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

What each input returned, and notes.

# 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 = {
    "titles": [
        "software engineer",
        "data engineer"
    ],
    "titlesExclude": [
        "intern",
        "internship"
    ],
    "locations": [],
    "companiesExclude": [
        "staffing",
        "recruiting",
        "recruitment",
        "talent",
        "personnel"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("zaiq/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 = {
    "titles": [
        "software engineer",
        "data engineer",
    ],
    "titlesExclude": [
        "intern",
        "internship",
    ],
    "locations": [],
    "companiesExclude": [
        "staffing",
        "recruiting",
        "recruitment",
        "talent",
        "personnel",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("zaiq/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 '{
  "titles": [
    "software engineer",
    "data engineer"
  ],
  "titlesExclude": [
    "intern",
    "internship"
  ],
  "locations": [],
  "companiesExclude": [
    "staffing",
    "recruiting",
    "recruitment",
    "talent",
    "personnel"
  ]
}' |
apify call zaiq/career-site-jobs-api --silent --output-dataset

```

## MCP server setup

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