# Greenhouse Job Board API | Jobs, Companies & New Postings (`johnvc/greenhouse-job-board-api`) Actor

Live jobs from any Greenhouse job board, no API key needed. Scrape full postings with salaries and timestamps, discover 4,400+ companies hiring on Greenhouse, and track new or changed roles. Pay per row delivered: no start fee, no minimum, filters run before billing.

- **URL**: https://apify.com/johnvc/greenhouse-job-board-api.md
- **Developed by:** [John](https://apify.com/johnvc) (community)
- **Categories:** Jobs, Lead generation, AI
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 job records

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Greenhouse Job Board API

Pull live jobs from any Greenhouse-hosted career site through the public Greenhouse job board API, with no Harvest key and no login. Give it company names or board URLs and get back structured job records with titles, locations, departments, timestamps, salaries, and full descriptions. Or give it nothing and let it discover companies from its bundled directory of 4,400+ verified Greenhouse boards.

Greenhouse is the applicant tracking system behind the career pages of thousands of companies, including Stripe, Airbnb, GitLab, and Anthropic. This actor reads their public job board API live at run time, so every row reflects what the employer's board says right now, not what an index remembered from last week.

### What you get per job

| Field group | Fields |
|---|---|
| Identity | id, internalJobId, requisitionId, title, companyName, boardToken, url |
| Structure | departments, offices, location, locationsDerived, isRemote |
| Timestamps | datePublished, dateUpdated (the employer's own last-modified stamp) |
| Compensation | salaryRaw (published pay ranges, verbatim) and salaryDerived (parsed from the posting text) |
| Content | descriptionMarkdown, descriptionHtml, descriptionText, application questions |
| Provenance | language, metadata, dataCompliance, source, scrapedAt |

### Three modes in one actor

1. **Full job records** (default): every open job on the boards you name, with descriptions in the formats you pick.
2. **Job URLs only**: the cheapest way to index everything: id, title, company, link, and both timestamps, without descriptions.
3. **Company discovery**: one row per company that hires through Greenhouse, live-verified with a current open-jobs count. The bundled directory covers 4,400+ boards found in public web archives and re-verified at run time.

Leave the company list empty and the actor sweeps the directory for you, capped by maxCompanies and maxJobs so an exploratory run stays small.

### Track new and changed postings without state

Every Greenhouse job carries the employer's own updated and first-published timestamps. Set updatedAfter to 25h on a daily schedule and each run returns only what changed since yesterday. There is no seen-list or delta store to maintain between runs, because the timestamps come from the source. Use publishedAfter for a genuinely-new-roles feed.

### Pay for exactly what you receive

Billing is per delivered row, with no start fee and no minimum spend. Filters (title, department, location, dates) run before billing, so filtered jobs cost nothing. The base job record is one event; Markdown, HTML, or plain-text descriptions, application questions, and the whole-run report are optional add-ons, each billed only on the rows that actually carry them. Turn everything off and a job row costs a fraction of a cent.

### Input parameters

| Parameter | Type | Default | What it does |
|---|---|---|---|
| companies | array | \["stripe"] | Board tokens or any board, embed, or single-job URL, mixed freely |
| startUrls | array | \[] | Same values in URL-list form; merged with companies |
| outputMode | select | jobs | jobs, urlsOnly, or companiesOnly |
| discoveryQuery | string | "" | Text match over the company directory for discovery and sweeps |
| verifyCompanies | boolean | true | Live-probe each discovered company before returning it |
| titleKeywords | array | \[] | Keep jobs whose title contains any of these |
| departments | array | \[] | Keep jobs in matching departments |
| locationKeywords | array | \[] | Keep jobs in matching locations or offices |
| updatedAfter | string | "" | Change detection: 24h, 7d, 2w, or an ISO date |
| publishedAfter | string | "" | Same grammar, against the first-published date |
| includeDescriptionMarkdown | boolean | true | Add the description as Markdown (paid add-on) |
| includeDescriptionHtml | boolean | false | Add the original HTML (paid add-on) |
| includeDescriptionText | boolean | false | Add plain text (paid add-on) |
| includeQuestions | boolean | false | Add application form questions (paid add-on) |
| report | select | none | Write a Markdown or HTML run report (paid add-on) |
| maxCompanies | integer | 25 | Cap on companies in sweeps and discovery |
| maxJobsPerCompany | integer | 0 | Per-board cap, 0 = all |
| maxJobs | integer | 100 | Whole-run cap, the main cost control |
| maxConcurrency | integer | 5 | Parallel per-job requests |

### Example output

```json
{
  "resultType": "job",
  "id": "8503792002",
  "title": "Account Executive - Italy",
  "companyName": "GitLab",
  "boardToken": "gitlab",
  "url": "https://job-boards.greenhouse.io/gitlab/jobs/8503792002",
  "departments": [{ "id": 4011044002, "name": "Sales" }],
  "location": "Remote, Italy",
  "isRemote": true,
  "language": "en",
  "datePublished": "2026-04-17T05:58:03-04:00",
  "dateUpdated": "2026-08-03T16:43:10-04:00",
  "salaryDerived": { "min": 71400, "max": 126000, "currency": "EUR", "period": "year", "source": "description-regex" },
  "descriptionMarkdown": "## About the role\n\nGitLab is looking for...",
  "source": "greenhouse",
  "scrapedAt": "2026-08-25T16:00:00Z"
}
```

### Use cases

- Job boards and aggregators: backfill and refresh listings straight from the source, not from a third-party index.
- Recruiters and sourcers: pull every open role at target companies, filtered by title, department, or location.
- Sales and GTM teams: hiring is a buying signal. Discover companies on Greenhouse in your niche and watch where headcount is going.
- Talent analytics: track posting velocity, remote share, and salary transparency across thousands of employers.
- AI agents: structured JSON, Markdown descriptions, stable field names, and MCP support make this a clean tool for agent pipelines.

### Getting started

1. Add company tokens or paste board URLs into the companies field.
2. Pick the description formats you want (Markdown is on by default).
3. Run it. Rows land in the dataset; a per-board summary lands in the key-value store.

[View on Apify Store](https://apify.com/johnvc/greenhouse-job-board-api?fpr=9n7kx3)

Worked examples in Python plus MCP setup walkthroughs live in the example repo: https://github.com/johnisanerd/Apify-Greenhouse-Job-Board-API

For scheduled monitoring, create a daily schedule with updatedAfter set to 25h and the actor becomes a change feed for the boards you care about.

### 💡 Example tasks

Ready-made configurations with their own landing pages:

- [Use the Greenhouse Job Board API Without a Key](https://apify.com/johnvc/greenhouse-job-board-api/examples/greenhouse-job-board-api-no-key?fpr=9n7kx3)
- [Find Companies Using Greenhouse ATS](https://apify.com/johnvc/greenhouse-job-board-api/examples/find-companies-using-greenhouse?fpr=9n7kx3)
- [Track New Greenhouse Job Postings Daily](https://apify.com/johnvc/greenhouse-job-board-api/examples/track-new-greenhouse-jobs-daily?fpr=9n7kx3)
- [Greenhouse Jobs as Markdown for AI Agents](https://apify.com/johnvc/greenhouse-job-board-api/examples/greenhouse-jobs-markdown-ai-agents?fpr=9n7kx3)
- [Job Board Scraper for Greenhouse Career Sites](https://apify.com/johnvc/greenhouse-job-board-api/examples/job-board-scraper-greenhouse-sites?fpr=9n7kx3)
- [Greenhouse Job Postings With Salary Data](https://apify.com/johnvc/greenhouse-job-board-api/examples/greenhouse-job-postings-salary-data?fpr=9n7kx3)

### Integrations

- Apify API and clients: run the actor and read the dataset from Python or JavaScript with the [Apify API](https://docs.apify.com/api/v2), or export results as JSON, CSV, or Excel straight from the console.
- Schedules and monitoring: pair a daily schedule with updatedAfter for a hands-off change feed.
- MCP: add the actor to any MCP client through the hosted server (section below).
- Automation platforms: connect through Apify's [integrations](https://docs.apify.com/platform/integrations) for n8n, Make, Zapier, webhooks, and Google Sheets.
- Crypto-native agents: pay per run over the x402 protocol (section below).

### Related tools

Part of a family of job-data APIs on this account:

- [Ashby Job Board API](https://apify.com/johnvc/ashby-job-board-scraper?fpr=9n7kx3) for Ashby-hosted job boards with salary data
- [Workday Careers API](https://apify.com/johnvc/workday-careers-api?fpr=9n7kx3) for Workday-hosted career sites
- [iCIMS Careers API](https://apify.com/johnvc/icims-careers-api?fpr=9n7kx3) for iCIMS career portals
- [JazzHR Jobs API](https://apify.com/johnvc/jazzhr-jobs-api?fpr=9n7kx3) for the JazzHR platform
- [Wellfound Jobs API](https://apify.com/johnvc/wellfound-jobs-api?fpr=9n7kx3) for startup jobs on Wellfound
- [LinkedIn Jobs API](https://apify.com/johnvc/linkedin-jobs-api?fpr=9n7kx3) for LinkedIn job search results
- [Google Jobs Scraper](https://apify.com/johnvc/Google-Jobs-Scraper?fpr=9n7kx3) for Google Jobs listings

### 🔌 Use this API from Claude (MCP)

Add this actor as a tool in [Claude Code](https://claude.ai/referral/uIlpa7nPLg) (free trial), [Claude Cowork](https://claude.ai/referral/uIlpa7nPLg) (free trial), or any MCP client, through the hosted Apify MCP server:

```
https://mcp.apify.com/?tools=actors,docs,johnvc/greenhouse-job-board-api
```

https://www.youtube.com/watch?v=jREWahDGhJM

Apify MCP integration docs: https://docs.apify.com/platform/integrations/mcp

### 💸 Pay per run with crypto (x402)

The Greenhouse Job Board API supports agentic payments via the [x402 protocol](https://docs.apify.com/platform/integrations/x402).
AI agents and MCP clients can pay for runs in USDC (on Base) with no Apify account or API token needed:
point your agent at the [Apify MCP server](https://mcp.apify.com/?tools=actors,docs,johnvc/greenhouse-job-board-api) and it can
discover, pay for, and run this actor autonomously. Read the
[Apify x402 announcement](https://apify.com/change-log/pay-for-apify-actors-with-x402?fpr=9n7kx3) for details.

### Greenhouse job board API pricing

Pay per event, per delivered row. The base job record covers every structured field. Add-ons bill only on rows that carry them: description formats, application questions, and the whole-run report. URL index rows and discovered companies have their own low per-row events. No start fee, no monthly rental, no minimum results per run, and filtered rows are never charged. Current prices are on the store page's pricing card.

### FAQ

#### Is this an API or a web scraper?

Both, honestly. Under the hood it reads the same public endpoints a scraper would. What you get is an API: structured JSON on demand, filters, stable field names, and no HTML unless you ask for it. If you have been maintaining your own Greenhouse scraper, this is the version where someone else maintains the parser.

#### Can I use this from Claude or another MCP client?

Yes. Add the hosted MCP server URL from the section above and the actor shows up as a callable tool in [Claude Code](https://claude.ai/referral/uIlpa7nPLg) (free trial), [Claude Cowork](https://claude.ai/referral/uIlpa7nPLg) (free trial), or any MCP client. Agents can discover it, run it, and read the dataset without any glue code.

#### Is there a page that lists all Greenhouse open jobs?

Not from Greenhouse itself, which is exactly why this actor exists. Leave the companies field empty and it sweeps its bundled directory of 4,400+ verified boards, capped by maxCompanies and maxJobs. Raise the caps to go wider.

#### What is boards-api.greenhouse.io?

It is the public, read-only job board API that powers every hosted Greenhouse career page. This actor reads it directly, which is why results are live rather than indexed.

#### Do I need a Greenhouse Harvest API key?

No. The Harvest API is Greenhouse's private, authenticated API for employers. This actor uses only the public job board layer, so there is nothing to sign up for and no key to manage.

#### How do I use the Greenhouse API without writing code?

Run this actor from the Apify console, on a schedule, from n8n, or from an AI agent over MCP. Input is a form; output is a dataset you can export as JSON, CSV, or Excel.

#### How do I find companies that use Greenhouse?

Set outputMode to companiesOnly. You get one row per company with its board token, a live open-jobs count, and the board URL. Add a discoveryQuery to narrow by name.

#### How do I get only new job postings?

Set updatedAfter (for any change) or publishedAfter (for new roles only) to a window like 24h, or an ISO date. The actor uses the employer's own timestamps, so there is no state to manage between runs.

#### Does job board scraping require an API?

Greenhouse boards expose a public API, and reading it is far more reliable than parsing career-page HTML. This actor speaks that API for you and returns normalized rows.

#### Is the job description included by default?

Yes, as Markdown, which reads well in AI pipelines and converts cleanly to anything else. HTML and plain text are separate toggles. Each format is a per-row add-on charge, so you only pay for what you ship.

#### What about boards hosted in the EU?

A small number of Greenhouse customers use the EU data silo (job-boards.eu.greenhouse.io). Those boards are detected and reported clearly, but not yet scraped; EU support is planned.

#### Why did a board return an error row?

Error rows carry a stable errorCode: board\_not\_found means the token does not exist on the public API (check the spelling against the company's careers URL), http\_error means the source answered abnormally. Errors are in-band rows, so your pipeline sees them without reading logs.

### 🌐 About Alpha OSINT

This Actor is part of [Alpha OSINT](https://www.alphaosint.com), toolset of financial and operations data sources and APIs.
For support or requests for this actor, please start a ticket [directly on our support page](https://apify.com/johnvc/greenhouse-job-board-api/issues/open?fpr=9n7kx3).

Last Updated: 2026.08.27

# Actor input Schema

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

Greenhouse board tokens or URLs, mixed freely: a bare token (stripe), a board URL (https://boards.greenhouse.io/stripe or https://job-boards.greenhouse.io/stripe), an embed URL (...?for=stripe), or a single job URL (.../stripe/jobs/1234567). Leave empty together with startUrls to sweep companies from the bundled directory instead.

## `startUrls` (type: `array`):

Alternative to the companies field for URL-shaped input; both lists are merged. Accepts the same board, embed, and single-job URL forms.

## `outputMode` (type: `string`):

jobs returns full job records. urlsOnly returns the job index without descriptions, the cheapest way to list everything. companiesOnly returns one row per company from the discovery directory with a live job count.

## `discoveryQuery` (type: `string`):

Case-insensitive text matched against company names and board tokens in the bundled directory. Scopes companiesOnly runs and empty-input sweeps. Leave empty to take the largest boards first.

## `verifyCompanies` (type: `boolean`):

companiesOnly mode: probe each candidate board against the live API before returning it, adding a current job count. Dead boards are skipped and never billed. Turn off to list the directory snapshot without network checks.

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

Keep only jobs whose title contains any of these words, for example engineer, sales, designer. Filters run before billing, so filtered jobs cost nothing.

## `departments` (type: `array`):

Keep only jobs whose department name contains any of these values, for example Engineering, Marketing.

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

Keep only jobs whose location or office name contains any of these values, for example Remote, London, New York.

## `updatedAfter` (type: `string`):

Keep only jobs the employer updated on or after this cutoff. Accepts a relative window (24h, 7d, 2w) or an ISO date or datetime (2026-08-01 or 2026-08-01T12:00:00Z). Uses the board's own updated\_at timestamp, so a daily schedule with 25h returns only what changed. No state to manage.

## `publishedAfter` (type: `string`):

Keep only jobs first published on or after this cutoff. Same formats as updatedAfter. Use this for genuinely-new-roles feeds.

## `includeDescriptionMarkdown` (type: `boolean`):

Add descriptionMarkdown to each job row: the posting converted to clean Markdown, compact and ready for AI agents and LLM pipelines. Billed per job row that carries it. Uncheck for cheaper metadata-only rows.

## `includeDescriptionHtml` (type: `boolean`):

Add descriptionHtml to each job row: the original posting markup, entity-decoded. Billed per job row that carries it.

## `includeDescriptionText` (type: `boolean`):

Add descriptionText to each job row: the posting flattened to plain prose. Billed per job row that carries it.

## `includeQuestions` (type: `boolean`):

Fetch each job's application form questions, plus compliance, demographic, and location question sets, via one extra request per job. Slower on large runs. Billed per job row that carries question data.

## `report` (type: `string`):

Also write a human-readable digest of every scraped job, grouped by company, to the key-value store under the REPORT key. One flat charge per report. Capped at 5000 rows.

## `maxCompanies` (type: `integer`):

Cap on companies processed in a discovery sweep or companiesOnly run. Keeps empty-input runs small and predictable.

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

Cap on job rows per board after filtering. 0 means no per-company cap.

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

Hard ceiling on rows across the entire run, all companies combined. The main cost control. 0 means unlimited.

## `maxConcurrency` (type: `integer`):

Parallel per-job requests, used when fetching application questions or hydrating oversized boards.

## `proxyConfiguration` (type: `object`):

Optional. The public board API answers direct connections, so leave this off unless your network requires a proxy.

## Actor input object example

```json
{
  "companies": [
    "stripe"
  ],
  "startUrls": [],
  "outputMode": "jobs",
  "discoveryQuery": "",
  "verifyCompanies": true,
  "titleKeywords": [],
  "departments": [],
  "locationKeywords": [],
  "updatedAfter": "",
  "publishedAfter": "",
  "includeDescriptionMarkdown": true,
  "includeDescriptionHtml": false,
  "includeDescriptionText": false,
  "includeQuestions": false,
  "report": "none",
  "maxCompanies": 25,
  "maxJobsPerCompany": 0,
  "maxJobs": 100,
  "maxConcurrency": 5,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `allResults` (type: `string`):

Every row this run produced.

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

Job rows with the headline fields: title, company, location, dates, and the apply link.

## `changes` (type: `string`):

Job rows ordered for monitoring, with the last-updated date first.

## `companies` (type: `string`):

One row per discovered company with a live open-jobs count and a link to their board.

## `report` (type: `string`):

The whole-run Markdown or HTML report, when the report add-on was enabled.

# 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": [
        "stripe"
    ],
    "startUrls": [],
    "titleKeywords": [],
    "departments": [],
    "locationKeywords": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("johnvc/greenhouse-job-board-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": ["stripe"],
    "startUrls": [],
    "titleKeywords": [],
    "departments": [],
    "locationKeywords": [],
}

# Run the Actor and wait for it to finish
run = client.actor("johnvc/greenhouse-job-board-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": [
    "stripe"
  ],
  "startUrls": [],
  "titleKeywords": [],
  "departments": [],
  "locationKeywords": []
}' |
apify call johnvc/greenhouse-job-board-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,johnvc/greenhouse-job-board-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/X3nud8oqPjzaV92oQ/builds/Ywl8dvtizjEqNlpEg/openapi.json
