# Company Job Postings: Greenhouse, Lever, Ashby & Workable (`tabulary/multi-ats-job-postings`) Actor

Open job postings from any company's Greenhouse, Lever, Ashby or Workable careers page, in one schema. Filter by job title, location and remote. Optional hiring monitor: only new or changed jobs since the last run, for sales signals and job alerts. No login or API key.

- **URL**: https://apify.com/tabulary/multi-ats-job-postings.md
- **Developed by:** [Tabulary](https://apify.com/tabulary) (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 $1.61 / 1,000 job postings

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

### What does Company Job Postings do?

It returns **every open job posting** from the careers pages of the companies you choose, straight
from their applicant tracking system (ATS): **Greenhouse**, **Lever**, **Ashby** and **Workable**.
Give it board slugs or careers-page URLs, and it detects the ATS, reads the employer's public job
board API and returns one clean record per job in a single schema. Filter by job title, location
and remote, and turn on **only new since the last run** to get a daily feed of new roles. Sales
teams use it for hiring signals, recruiters and job sites for fresh listings, and analysts and AI
agents for hiring trends. No login or API key needed.

### What you get

- Company, ATS, job ID, title, department and location.
- Remote flag, employment type (full time, part time, contract, internship and more), and posted
  and updated dates where the ATS publishes them.
- Links to the job page and the application page.
- The full job description as plain text, with email addresses masked.
- The same fields whichever ATS a company uses, so four systems become one table.
- Hiring monitor for scheduled runs: only jobs that are new or changed since the last run.
- Export as JSON, CSV or Excel, send to Google Sheets, Slack, a CRM or a webhook, or call it as a
  tool from AI agents through the Apify MCP server.

### How much does it cost?

You pay per job posting saved, with no monthly fee: **$2.30 per 1,000 job postings** on Apify's
free plan, and 10–40% less on paid Apify plans. Each run also costs $0.001 to start. Apify's free plan includes $5 of credit every
month, enough for about 2,100 job postings. Prices as of October 2026; the price shown on this
page is the one that applies.

| Use | Job postings | Cost on the free plan |
|---|---|---|
| All open jobs at 5 mid-size companies | about 500 | about $1.15 |
| Engineering jobs only at 20 companies | about 400 | about $0.92 |
| Daily hiring monitor for 50 companies, about 30 new jobs a day | about 900 a month | about $2.07 a month |

Use the title, location and remote filters to pay only for the roles you need. Set **Maximum cost
per run** to cap any run; the Actor stops cleanly at the cap and keeps everything it saved.

### Ready-made inputs

Paste one of these into the JSON input tab, or set the same fields in the form.

**All open jobs at a few companies** (slugs or careers-page URLs, any mix of ATSs) · [open this example](https://apify.com/tabulary/multi-ats-job-postings/examples/jobs-greenhouse-lever-ashby-mix)

```json
{ "companies": ["gitlab", "https://jobs.lever.co/dnb", "https://jobs.ashbyhq.com/notion"] }
```

**Remote engineering roles only** · [open this example](https://apify.com/tabulary/multi-ats-job-postings/examples/remote-engineering-jobs)

```json
{ "companies": ["gitlab", "stripe", "figma"], "titleKeywords": "engineer, developer", "remoteOnly": true }
```

**Sales hiring signals: new sales and marketing roles, daily** (schedule it every morning) · [open this example](https://apify.com/tabulary/multi-ats-job-postings/examples/sales-hiring-signals-monitor)

```json
{ "companies": ["gitlab", "stripe", "figma", "notion"], "titleKeywords": "sales, account executive, marketing", "onlyNewSinceLastRun": true }
```

**Jobs in one city** · [open this example](https://apify.com/tabulary/multi-ats-job-postings/examples/jobs-in-london)

```json
{ "companies": ["stripe", "figma"], "locationKeywords": "London" }
```

### Hiring monitor: only new since the last run

1. List the companies, set any filters and turn on **Only new since last run**.
2. Save it as a task and add an Apify **Schedule** (for example every morning).
3. Connect the output: Apify's built-in Slack and email notifications, a webhook, or Make, Zapier
   and n8n to push new roles into Google Sheets, HubSpot, Clay or a Teams channel.

Each run returns only jobs that are new, or whose posting was updated, since earlier runs with the
same companies and filters. Jobs cut off by your spending limit are delivered next time. With
filters, the memory is kept per set of filters, so separate tasks never interfere.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `companies` | array | required | Board slugs (e.g. `gitlab`) or careers-page URLs (e.g. `https://jobs.lever.co/dnb`). A bare slug is checked against the four ATSs in a fixed order. |
| `titleKeywords` | string | `""` (all) | Comma-separated words; keeps jobs whose title contains any of them. |
| `locationKeywords` | string | `""` (all) | Comma-separated words; keeps jobs whose location contains any of them. |
| `remoteOnly` | boolean | `false` | Keep only jobs the ATS marks as remote. |
| `onlyNewSinceLastRun` | boolean | `false` | Return only jobs that are new or changed since earlier runs (see Hiring monitor). |

**Finding a company's slug:** open its careers page. The slug is the part after the ATS domain:
`boards.greenhouse.io/gitlab` → `gitlab`, `jobs.lever.co/dnb` → `dnb`, `jobs.ashbyhq.com/notion` →
`notion`, `apply.workable.com/acme` → `acme`. If a company's careers page is on its own domain,
look for one of these links behind the "Apply" button.

### Output

One dataset item per job. A real item from a run on 21 October 2026 (description shortened):

```json
{
  "company": "dnb",
  "ats": "lever",
  "job_id": "d0e51a7a-5f0f-483a-9b65-78a9024f1681",
  "title": "2027 Enterprise Sales Development Program",
  "department": "Sales",
  "location": "Florham Park - New Jersey - United States",
  "remote": false,
  "employment_type": "full_time",
  "posted_at": "2026-10-15T18:18:27.254Z",
  "updated_at": null,
  "url": "https://jobs.lever.co/dnb/d0e51a7a-5f0f-483a-9b65-78a9024f1681",
  "apply_url": "https://jobs.lever.co/dnb/d0e51a7a-5f0f-483a-9b65-78a9024f1681/apply",
  "description": "Shape the Future with Dun & Bradstreet. At Dun & Bradstreet, we believe data has the power to create a better tomorrow…"
}
```

`employment_type` is `full_time`, `part_time`, `contract`, `internship`, `temporary`, `other` or
`null` (Greenhouse boards don't publish it). `updated_at` is `null` where the ATS doesn't publish
an update time (Lever, Ashby, Workable). Dates are ISO 8601.

### Use it from AI agents

Add the Actor to Claude, ChatGPT, Cursor or any MCP client through the Apify MCP server
(`https://mcp.apify.com?tools=tabulary/multi-ats-job-postings`). Ask in plain language, for
example: "Which data engineering roles are GitLab and Stripe hiring for right now?" The agent fills
in the input and gets structured job records back.

### Use it from code

```bash
curl -X POST "https://api.apify.com/v2/acts/tabulary~multi-ats-job-postings/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["gitlab", "stripe"], "titleKeywords": "engineer"}'
```

The same works with the Apify Python and JavaScript clients. See the API tab for details.

### Data source and limits

- **Greenhouse Job Board API** ([docs](https://docs.greenhouse.io/job-board.html)): "Job Board
  data is publicly available, so authentication is not required for any GET endpoints."
- **Lever Postings API** ([docs](https://github.com/lever/postings-api)): published postings are
  public.
- **Ashby public job posting API**
  ([docs](https://developers.ashbyhq.com/docs/public-job-posting-api)).
- **Workable public careers widget API** (`apply.workable.com`), the same data its careers pages
  show.
- The Actor makes at most about one request per second to each host and backs off when a host
  asks it to slow down. A bare slug can need up to four requests to find its ATS, and two
  companies can own the same slug on different systems, so pass the full careers-page URL when you
  can.
- It reads the companies you list; it does not search every company on an ATS.
- Jobs are returned as the employer publishes them; check the employer's page before acting on a
  posting. Email addresses in descriptions are masked.
- Not affiliated with or endorsed by Greenhouse, Lever, Ashby or Workable.

### Other Tabulary tools

Clean data from official and public sources, priced per result:

- [UK Tenders API: Contracts Finder & Find a Tender](https://apify.com/tabulary/uk-public-tenders)
- [EU Tenders API: TED Public Procurement Notices](https://apify.com/tabulary/eu-ted-tenders)
- [SAM.gov Federal Contract Opportunities](https://apify.com/tabulary/sam-gov-contract-notices)
- [Airport METAR & TAF Weather](https://apify.com/tabulary/airport-weather-metar-taf)
- [Remote Jobs API: RemoteOK & Jobicy Postings](https://apify.com/tabulary/remote-jobs-feed)

### FAQ

**Which companies can I track?** Any company whose careers page runs on Greenhouse, Lever, Ashby
or Workable. See "Finding a company's slug" above.

**Do I need API keys or accounts?** No. All four job boards are public and keyless.

**Why did a company return 0 jobs?** Either it has no open roles right now, or its slug belongs to
a different company on another ATS. The run log says which board matched; pass the full
careers-page URL to be exact.

**Does it include salaries?** Only where the employer writes them into the job description.

**How do I get only new jobs every day?** Turn on the hiring monitor, save the input as a task and
schedule it (see Hiring monitor).

**Something broke?** Open an issue on the Issues tab. The Actor is tested daily.

### Changelog

- **2026-10-21:** job title, location and remote filters; ready-made inputs; slug guide.
- **2026-10-21:** first version: Greenhouse, Lever, Ashby and Workable, ATS auto-detection, hiring
  monitor, masked emails.

### About Tabulary

This tool is part of [Tabulary](https://apify.com/tabulary): clean tables from official public
sources. Every Tabulary tool uses the source's official API or open data where one exists,
collects no personal data, and is tested on Apify every day. Questions or ideas? Open an issue on
the Issues tab.

# Actor input Schema

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

Board slugs (e.g. "gitlab") or full careers-page URLs from Greenhouse, Lever, Ashby or Workable. A bare slug is checked against all four ATSs; a URL's domain picks the ATS directly.

## `titleKeywords` (type: `string`):

Optional. Comma-separated words, for example "engineer, data, sales". Keeps jobs whose title contains any of them (not case-sensitive). Leave empty for all jobs.

## `locationKeywords` (type: `string`):

Optional. Comma-separated words, for example "London, Berlin, United States". Keeps jobs whose location contains any of them. Leave empty for all locations.

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

Keep only jobs the hiring system marks as remote. Jobs with no remote flag are dropped when this is on.

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

For scheduled runs. Remembers which jobs earlier runs returned for each company (and for the same title, location and remote filters), and returns only jobs that are new or whose posting was updated since then. Jobs cut off by your spending limit come in the next run.

## Actor input object example

```json
{
  "companies": [
    "gitlab"
  ],
  "titleKeywords": "",
  "locationKeywords": "",
  "remoteOnly": false,
  "onlyNewSinceLastRun": false
}
```

# Actor output Schema

## `overview` (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 = {
    "companies": [
        "gitlab"
    ],
    "titleKeywords": "",
    "locationKeywords": "",
    "remoteOnly": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("tabulary/multi-ats-job-postings").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": ["gitlab"],
    "titleKeywords": "",
    "locationKeywords": "",
    "remoteOnly": False,
}

# Run the Actor and wait for it to finish
run = client.actor("tabulary/multi-ats-job-postings").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": [
    "gitlab"
  ],
  "titleKeywords": "",
  "locationKeywords": "",
  "remoteOnly": false
}' |
apify call tabulary/multi-ats-job-postings --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,tabulary/multi-ats-job-postings"
        }
    }
}
```

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/nIv7bbwbCevNymXOm/builds/hXccYXChh82pHd8iT/openapi.json
