# Greenhouse/Lever/Ashby/Personio/Teamtailor Jobs (`brimfold/ats-jobs-feed`) Actor

Get every open job from company career boards on Greenhouse, Lever, Ashby, Personio and Teamtailor in one clean format: title, department, location, remote/hybrid, salary where published, posted date, apply link and description. Filter by keyword, location, remote and date, or monitor only new jobs.

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

## Pricing

from $1.10 / 1,000 job saveds

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

## Jobs Feed: Greenhouse, Lever, Ashby, Personio & Teamtailor

Pull every open job from company career boards hosted on **Greenhouse**, **Lever**, **Ashby**, **Personio** and **Teamtailor**, in one clean, consistent format. Give it a list of companies (board slugs or careers-page URLs) and get a dataset of jobs with title, department, team, location, remote/hybrid/on-site, employment type, salary range (where the company publishes it), posted date, job URL, apply URL and a plain-text description.

Use it to build a niche job board, track hiring at competitors or target accounts, feed a recruiting CRM, alert on new roles, or study hiring trends.

### Why this Actor

- **Five ATS platforms, one schema.** Greenhouse, Lever (US and EU), Ashby, Personio (.de and .com) and Teamtailor jobs come out with the same fields, so you can mix companies freely. Personio and Teamtailor are popular with European companies.
- **Official public job-board feeds.** Data comes from each platform's public job-board endpoints (JSON APIs for Greenhouse, Lever and Ashby, the Personio XML feed and the Teamtailor RSS feed) that companies publish for their own careers pages. No logins, no browser, no captchas, so runs are fast and cheap.
- **Paste anything.** `greenhouse:discord`, `https://jobs.lever.co/spotify`, `jobs.ashbyhq.com/linear`, `f24.jobs.personio.de`, `tibber.teamtailor.com`, or just `notion`. Bare slugs are auto-detected across Greenhouse, Lever and Ashby; Personio and Teamtailor need a prefix or URL.
- **Filters built in.** Title keywords, excluded words, location, department/team, remote only, and posted within N days.
- **Monitor mode.** Turn on `onlyNew` and schedule the Actor to get only jobs you haven't seen before.
- **Salary when published.** Ashby compensation ranges come through as min/max/currency/interval plus the original text.
- **Extra Personio fields.** Seniority, years of experience and schedule (full-time/part-time) are included when the company sets them.

### Input

| Field | What it does |
|---|---|
| `companies` | Board slugs or URLs, one per line. Prefix with `greenhouse:`, `lever:`, `lever-eu:`, `ashby:`, `personio:` or `teamtailor:`, or paste a careers URL. Without a prefix or URL, Greenhouse, Lever and Ashby are tried. Teamtailor companies on their own domain work as `https://careers.example.com/jobs.rss`. |
| `titleKeywords` / `excludeKeywords` | Keep or drop jobs by words in the title (case-insensitive). |
| `locationKeywords` | Keep jobs whose location matches any word, e.g. `London`, `Remote`, `Germany`. |
| `departmentKeywords` | Keep jobs whose department or team matches. |
| `remoteOnly` | Keep only remote jobs. |
| `postedWithinDays` | Keep jobs first published in the last N days. |
| `maxResults` / `maxPerCompany` | Total and per-company limits (newest first). Defaults: 30 and 10. |
| `descriptionMaxChars` | Length of the plain-text description. 0 leaves descriptions out. |
| `onlyNew` | Skip jobs already delivered in earlier runs. |

Example:

```json
{
  "companies": ["greenhouse:gitlab", "jobs.lever.co/palantir", "ashby:ramp", "personio:f24", "teamtailor:tibber", "notion"],
  "titleKeywords": ["engineer"],
  "excludeKeywords": ["intern"],
  "postedWithinDays": 14,
  "maxResults": 200
}
```

**How to find a company's slug:** open its careers page and click a job. The URL shows the platform and slug, e.g. `job-boards.greenhouse.io/discord/jobs/123` (Greenhouse, `discord`), `jobs.lever.co/spotify/...` (Lever, `spotify`), `jobs.ashbyhq.com/linear/...` (Ashby, `linear`), `f24.jobs.personio.de/job/...` (Personio, `f24`), `tibber.teamtailor.com/jobs/...` (Teamtailor, `tibber`). Paste that URL straight in.

### Output

One row per job:

```json
{
  "source": "ashby",
  "companySlug": "ramp",
  "jobId": "…",
  "title": "Software Engineer, Forward Deployed",
  "department": "Engineering",
  "location": "New York, NY (HQ)",
  "workplaceType": "hybrid",
  "employmentType": "FullTime",
  "postedAt": "2026-10-22T19:20:16Z",
  "url": "https://jobs.ashbyhq.com/ramp/…",
  "applyUrl": "https://jobs.ashbyhq.com/ramp/…/application",
  "salary": { "min": 168000, "max": 285000, "currency": "USD", "interval": "1 YEAR", "text": "$168K – $285K • Offers Equity" },
  "descriptionText": "ABOUT RAMP …",
  "boardUrl": "https://jobs.ashbyhq.com/ramp",
  "scrapedAt": "…"
}
```

A `RUN-SUMMARY` record in the key-value store lists each board's status (ok / not-found), jobs on the board, jobs saved, unrecognised inputs and how many jobs the filters removed.

### Pricing

**$1.50 per 1,000 jobs** ($0.0015 per job saved) with pay-per-event pricing. You pay only for jobs that land in your dataset. Boards that don't exist, unrecognised inputs and filtered-out jobs are free. Set a maximum cost per run in Apify and the Actor stops cleanly when it is reached.

### FAQ

**Is this legal?** The Actor reads only the public job-board APIs and feeds that Greenhouse, Lever, Ashby, Personio and Teamtailor provide so that companies can show their openings on their own sites and elsewhere. It does not log in or bypass anything. You are responsible for how you use the data, including each company's and platform's terms.

**Why is `companyName` sometimes empty?** Greenhouse returns the company name and Personio returns the hiring entity when the company sets one; Lever, Ashby and Teamtailor feeds do not, so `companySlug` identifies the company.

**Why is `workplaceType` "unspecified"?** The company didn't set it on the job and the location doesn't say remote.

**Does it support Workday, SmartRecruiters or LinkedIn?** No. Only Greenhouse, Lever, Ashby, Personio and Teamtailor.

**Why does a Teamtailor job have no department?** The Teamtailor RSS feed includes department and locations only when the company fills them in. It has no salary fields.

**A board shows "not-found".** The slug is wrong or the company moved to another ATS. Open its careers page and copy a job URL.

### Sources, terms and rate limits

| Platform | Endpoint read | Notes |
|---|---|---|
| Greenhouse | `boards-api.greenhouse.io/v1/boards/{slug}/jobs` | Public Job Board API, no key needed |
| Lever | `api.lever.co/v0/postings/{slug}` (EU: `api.eu.lever.co`) | Public Postings API |
| Ashby | `api.ashbyhq.com/posting-api/job-board/{slug}` | Public Job Postings API |
| Personio | `{slug}.jobs.personio.de/xml` (or `.com`) | Public XML feed Personio documents for publishing a company's open positions. robots.txt allows all |
| Teamtailor | `{slug}.teamtailor.com/jobs.rss` (or the company's own careers domain) | Public RSS feed of published jobs, read 50 jobs per page, up to 20 pages per board. robots.txt allows `/jobs`; its Content-Signal says `ai-train=no`, so don't use Teamtailor job text to train AI models |

- At most 4 requests at a time across all boards, one request per board page, with retries and back-off on HTTP 429 and 5xx (`Retry-After` honoured, up to 60 s). Big runs of hundreds of boards take longer but stay polite.
- No logins, cookies, browsers or captcha solving. Only published job ads are read; internal jobs and applicant data are never touched.
- Job ads are the companies' content. Check each company's and platform's terms before republishing descriptions.

Made by Brimfold Studio. Job data comes from each company's public Greenhouse, Lever, Ashby, Personio or Teamtailor job board; those names are trademarks of their owners, and this Actor is not affiliated with them.

# Actor input Schema

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

One per line. Use source:slug (greenhouse:discord, lever:spotify, ashby:linear, lever-eu:slug, personio:f24, teamtailor:tibber), a board URL (job-boards.greenhouse.io/discord, jobs.lever.co/spotify, jobs.ashbyhq.com/linear, f24.jobs.personio.de, tibber.teamtailor.com, or a Teamtailor custom-domain feed such as https://jobs.example.com/jobs.rss), or just a slug to try Greenhouse, Lever and Ashby. Personio and Teamtailor need the prefix or URL.

## `titleKeywords` (type: `array`):

Keep jobs whose title contains any of these (case-insensitive). Empty = all.

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

Drop jobs whose title contains any of these, e.g. intern, senior.

## `locationKeywords` (type: `array`):

Keep jobs whose location contains any of these, e.g. London, Remote, Germany.

## `departmentKeywords` (type: `array`):

Keep jobs whose department or team contains any of these.

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

Keep only jobs marked remote by the board (or with 'Remote' in the location).

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

Keep jobs first published in the last N days. Empty = any date.

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

Stop after this many jobs in total.

## `maxPerCompany` (type: `integer`):

Newest first. 0 = no per-company limit.

## `descriptionMaxChars` (type: `integer`):

Plain-text job description, cut to this length. 0 = leave out descriptions.

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

Skip jobs this Actor already delivered to you in earlier runs (kept in your named key-value store 'ats-jobs-feed-state'). Use with a schedule.

## Actor input object example

```json
{
  "companies": [
    "greenhouse:discord",
    "lever:spotify",
    "ashby:linear"
  ],
  "remoteOnly": false,
  "maxResults": 30,
  "maxPerCompany": 10,
  "descriptionMaxChars": 3000,
  "onlyNew": false
}
```

# Actor output Schema

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

No description

## `summary` (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": [
        "greenhouse:discord",
        "lever:spotify",
        "ashby:linear"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("brimfold/ats-jobs-feed").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": [
        "greenhouse:discord",
        "lever:spotify",
        "ashby:linear",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("brimfold/ats-jobs-feed").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": [
    "greenhouse:discord",
    "lever:spotify",
    "ashby:linear"
  ]
}' |
apify call brimfold/ats-jobs-feed --silent --output-dataset

```

## MCP server setup

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

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/Zh1HyJldBlIG5ajC9/builds/I6oHFjY31rC2sSa4a/openapi.json
