Greenhouse Job Board API: how to export jobs and salaries from Greenhouse job boards
Last updated: 27 October 2026 · By Quicksloth
Companies that publish their jobs on Greenhouse have job boards at addresses like job-boards.greenhouse.io/figma. Greenhouse documents a public API for these job boards. It needs no key, and one request returns every published job of a board in JSON. This guide shows what the API returns and what we got when we tried it on two real job boards. It also has a short free script that saves a board as a CSV file, and explains when a scheduled cloud run is the better choice.
Short version: GET https://boards-api.greenhouse.io/v1/boards/<token>/jobs?content=true returns all published jobs of one board, with descriptions and departments. Salaries come only with pay_transparency=true, and only where the employer publishes them.
What the public API offers
Greenhouse calls it the Job Board API (documentation read on 27 October 2026). In Greenhouse's words, it gives "a simple JSON representation of your company's offices, departments, and published jobs", so that companies "can build careers pages with a unique look and feel". The documentation also says: "Job Board data is publicly available, so authentication is not required for any GET endpoints."
- Endpoint:
https://boards-api.greenhouse.io/v1/boards/<token>/jobs. The board token is the first part of the path of the job board: forhttps://job-boards.greenhouse.io/figma(orboards.greenhouse.io/figma) it isfigma. Some companies, like Figma, send the board's front page to their own careers site; the API and the job pages still answer. - Descriptions: add
?content=trueto get the job description, the departments and the offices of each job. - Salaries: the documentation lists
pay_transparency=trueonly for the single-job endpoint. In our test it also worked on the list, and returnedpay_input_ranges. - One request per board: the response holds every published job of the board, with a
meta.totalcount. There is no paging and no search across companies. - One job:
/v1/boards/<token>/jobs/<id>returns a single job post.
The main fields of each job, from the documentation (the full list is on Greenhouse's page):
| Field | What it holds |
|---|---|
id, internal_job_id | the ID of the job post and the ID of the job itself |
title, location.name | the job title and the location as one text |
updated_at | when the job was last updated |
absolute_url | the job page, on Greenhouse or on the company's own site |
metadata | the custom fields the company chose to show, for example a work type |
content, departments, offices | with content=true: the description (HTML encoded as text, for example <p>), departments and offices |
pay_input_ranges | with pay_transparency=true: min_cents, max_cents, currency_type and a title such as "Pay Range" |
Limits we know of: the documentation states no rate limit, so keep a gentle pace (one request per board, with a pause). Amounts are in cents, and the pay range has no interval field: the period is only in its title, when the employer writes it. Work type is not a standard field: some companies add it in metadata, others write "Remote" in the location. In our test the list also returned company_name and first_published, which the documentation shows only in its single-job example. Boards on job-boards.eu.greenhouse.io are not covered by this guide.
What we got on two real job boards
We called the endpoint with curl on 27 October 2026 for two companies:
curl "https://boards-api.greenhouse.io/v1/boards/figma/jobs?content=true&pay_transparency=true"
| Board | Jobs | Response size (plain / with content and pay ranges) | With a pay range | Work type |
|---|---|---|---|---|
figma | 141 | 89 KB / 1.8 MB | 90 (all USD) | no work type field |
airbnb | 188 | 145 KB / 2.8 MB | 152 (USD, EUR, CAD, GBP, MXN, BRL, INR) | a Workplace Type custom field: 142 remote, 39 hybrid, 7 on-site |
Each request took about a second. Without pay_transparency=true the same Figma request returned no pay ranges. Airbnb's job links point to its own careers site, not to Greenhouse. A board token that does not exist returns HTTP 404 with {"status":404,"error":"Job not found"}.
A free Python script: one board to CSV
The script reads one or more boards and writes greenhouse_jobs.csv with one row per job: company, title, department, location, first published and updated dates, pay range, currency, the title of the pay range and link. It uses only Python's standard library (Python 3.8 or later).
"""Export the jobs of one or more Greenhouse job boards to a CSV file, with salary where the employer publishes it."""
import csv
import json
import sys
import time
import urllib.request
BOARDS = sys.argv[1:] or ["figma"]
FIELDS = ["board", "id", "company", "title", "department", "location", "firstPublished", "updatedAt",
"salaryMin", "salaryMax", "currency", "salaryTitle", "url"]
def get_board(board):
url = f"https://boards-api.greenhouse.io/v1/boards/{board}/jobs?content=true&pay_transparency=true"
request = urllib.request.Request(url, headers={"User-Agent": "greenhouse-jobs-script"})
with urllib.request.urlopen(request, timeout=60) as response:
return json.load(response)["jobs"]
def amount(cents): # Greenhouse sends amounts in cents
if cents is None:
return None
return cents / 100 if cents % 100 else cents // 100
def salary(job):
for pay in job.get("pay_input_ranges") or []:
return amount(pay.get("min_cents")), amount(pay.get("max_cents")), pay.get("currency_type"), pay.get("title")
return None, None, None, None
with open("greenhouse_jobs.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(FIELDS)
for board in BOARDS:
jobs = get_board(board)
for j in jobs:
department = (j.get("departments") or [{}])[0].get("name")
writer.writerow([board, j["id"], j.get("company_name"), j["title"].strip(), department,
((j.get("location") or {}).get("name") or "").strip(), j.get("first_published"),
j.get("updated_at"), *salary(j), j.get("absolute_url")])
print(f"{board}: {len(jobs)} jobs")
time.sleep(1) # one request per board, with a pause
Run it with the board tokens after the file name:
$ python3 greenhouse_jobs.py figma airbnb
figma: 141 jobs
airbnb: 188 jobs
What we got on 27 October 2026: a CSV with 329 jobs in 3 seconds, 242 of them with a pay range. One row, as it appears in the file:
figma,5426468004,Figma,"Account Executive, Enterprise",Sales,"San Francisco, CA • New York, NY • United States",2025-01-28T18:57:29-05:00,2026-07-22T05:37:08-04:00,165000,190000,USD,Annual Base Salary Range:,https://boards.greenhouse.io/figma/jobs/5426468004?gh_jid=5426468004
What the script does not do, to stay short: it keeps the first pay range only (a job can have several); it leaves out descriptions and custom fields; it does not filter by title or location; and it stops at the first board that fails (a wrong token gives HTTP Error 404). It also exports everything each time. To get only the jobs that are new since the last run, see our guide how to monitor new jobs at a list of companies.
When the Apify Actor is worth it
The script is enough for a one-off export of a few boards. Our ATS Jobs Scraper on the Apify Store reads the same Greenhouse API in the cloud. It is worth it when you need more than that:
- Several systems in one schema: it reads Lever and Ashby boards too, and returns the same fields for all three. One dataset covers a mixed list of companies.
- Work type and every location: it reads a work-type custom field (and an employment-type one) when the company has one, or looks for "remote" or "hybrid" in the location. It splits locations written with semicolons. Other custom fields are left out.
- Filters and only-new runs: title, location and remote filters, and an Only new or changed jobs mode for scheduled runs that keeps the list of jobs already returned for you.
- Many companies: board URLs,
greenhouse:tokennames, careers-page URLs or plain company names, up to 1,000 per run. A company that fails is reported and the others continue.
What we got on 27 October 2026, running the Actor's code (version 0.3, the one on the Apify Store) on our machine with this input:
{
"companies": ["greenhouse:figma", "greenhouse:airbnb"],
"titleKeywords": ["engineer"],
"onlyNewJobs": true,
"stateKey": "greenhouse-guide-test"
}
The first run saved 82 jobs with "engineer" in the title (28 at Figma and 54 at Airbnb; 66 with a pay range) in 3 seconds. The second run, right after, saved 0. The first run of a new history returns the matching jobs up to Max jobs in total, which the form prefills at 500, and up to 100 jobs on Apify's free plan. With Only new or changed jobs on, the jobs left out by a limit come in the next runs, as long as they are still posted. How to schedule it is explained in the monitoring guide.
The Actor charges per job a run saves, plus Apify's small start charge for each run. The current prices are in the Pricing tab of the Actor's page.
Questions and answers
- Do I need a Greenhouse account or an API key?
- Not to read published jobs. The documentation asks for a Job Board API key only to submit applications through the API, which this guide does not cover.
- Is it allowed to read Greenhouse job boards?
- Greenhouse describes the API for companies that build their own careers pages, and it needs no login or key. Its documentation says that "Job Board data is publicly available" — a statement about access, not a permission for every use. Keep a gentle pace (one request per board, with a pause), and check that your use of the job texts is allowed where you are.
- Can I list every company that uses Greenhouse?
- No. The API works one board at a time, and neither the script nor the Actor has a directory of companies. You start from your own list: look for
greenhouse.ioin the address of a job page or of the Apply button, or forgh_jidin the address of a job on the company's own site, then find the token in the page source. - Why are some pay ranges missing or without a period?
- Greenhouse returns pay ranges only where the employer has set them up for the job post. The range has no interval field, so "per year" or "per hour" is known only when the employer writes it in the range title.
- What about Lever, Ashby and Workday?
- Lever and Ashby have their own guides: how to export jobs and salaries from Lever job sites and how to export jobs and salaries from Ashby job boards. The monitoring guide has a script for Greenhouse, Lever and Ashby together. Workday is covered in how to export job postings from a Workday career site.
API, script and Actor tested by Quicksloth on 27 October 2026 on the public Greenhouse job boards of Figma and Airbnb; job counts change every day. Field descriptions come from Greenhouse's documentation read on 27 October 2026. Written with AI tools and checked by Quicksloth. Quicksloth is an independent developer and is not affiliated with Greenhouse, Apify or the companies named. Greenhouse and Apify are trademarks of their respective owners.