Ashby job board API: how to export jobs and salaries from jobs.ashbyhq.com
Last updated: 27 October 2026 · By Quicksloth
Companies that publish their jobs on Ashby have job boards at addresses like jobs.ashbyhq.com/ramp. Ashby documents a public API for these job boards: one request, no key, every published job of the board in JSON, with the salary range when the employer shows it. This guide shows what the API returns, what we got when we tried it on two real boards, a short free script that saves a board as a CSV file, and when a scheduled cloud run is the better choice.
Short version: GET https://api.ashbyhq.com/posting-api/job-board/<board>?includeCompensation=true returns all published jobs of one board. Use workplaceType, not isRemote, to tell remote jobs from hybrid ones, and expect salaries only where the employer publishes them.
What the public API offers
Ashby calls it the Job Postings API (documentation read on 27 October 2026): "This API allows you to get data for all currently published Job Postings for your organization." It is meant for companies that build their own careers page, and it needs no login or API key.
- Endpoint:
https://api.ashbyhq.com/posting-api/job-board/<board>. The board name is the last part of the job board address: forhttps://jobs.ashbyhq.com/rampit isramp. - Salaries: add
?includeCompensation=trueto get acompensationobject for each job. - One request per board: the response holds every published job of the board; there is no paging and no search across companies.
The fields of each job, as listed in the documentation:
| Field | What it holds |
|---|---|
title, department, team | job title, department and immediate team |
location, secondaryLocations, address | main location as text, other locations, and city, region and country when the employer filled them in |
workplaceType | OnSite, Remote or Hybrid |
isRemote | true when the work type is Remote or Hybrid; the documentation says to use workplaceType to tell them apart |
employmentType | FullTime, PartTime, Intern, Contract or Temporary |
publishedAt | when the job was last published (ISO date and time) |
descriptionHtml, descriptionPlain | the job description, as HTML and as plain text |
jobUrl, applyUrl | the job page and the application page on jobs.ashbyhq.com |
isListed | false for jobs meant to be reached only by direct link |
compensation | with includeCompensation=true: a text summary (for example "$81K - $87K") and components with compensationType (Salary, EquityPercentage, Bonus and others), minValue, maxValue, currencyCode and interval |
Limits we know of: the documentation states no rate limit, so keep a gentle pace (one request per board, with a pause). Fields the employer left empty in Ashby are also empty in the response, as the documentation says. The company name is not a field: the board name is what you have. In our test the responses also had an id for each job, which the documentation does not list.
What we got on two real boards
We called the endpoint with curl on 27 October 2026 for two companies:
curl "https://api.ashbyhq.com/posting-api/job-board/ramp?includeCompensation=true"
| Board | Jobs | Response size | With a structured salary | Work type |
|---|---|---|---|---|
ramp | 173 | 3.1 MB | 166 | 139 hybrid, 19 on-site, 15 remote; isRemote true for 154 |
notion | 140 | 2.6 MB | 0 (the employer does not show pay on its postings) | 88 hybrid, 52 with no work type |
Two things to take from it. First, salaries depend on the employer: the same request gives a range for almost every job at one company and none at the other. Second, if you filter on isRemote, Ramp's 139 hybrid jobs come out as remote; filtering on workplaceType keeps the 15 remote ones. A board name that does not exist returns HTTP 404 "Not Found". The responses are large because each job carries its full description twice, as HTML and as plain text.
A free Python script: one board to CSV
The script reads one or more boards and writes ashby_jobs.csv with one row per listed job: title, department, team, location, work type, employment type, publish date, salary range, currency, interval and link. It uses only Python's standard library (Python 3.8 or later).
"""Export the jobs of one or more Ashby 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 ["ramp"]
FIELDS = ["board", "id", "title", "department", "team", "location", "workplaceType",
"employmentType", "publishedAt", "salaryMin", "salaryMax", "currency", "interval", "jobUrl"]
def get_board(board):
url = f"https://api.ashbyhq.com/posting-api/job-board/{board}?includeCompensation=true"
request = urllib.request.Request(url, headers={"User-Agent": "ashby-jobs-script"})
with urllib.request.urlopen(request, timeout=60) as response:
return json.load(response)["jobs"]
def salary(job):
for part in (job.get("compensation") or {}).get("summaryComponents") or []:
if part.get("compensationType") == "Salary":
return part.get("minValue"), part.get("maxValue"), part.get("currencyCode"), part.get("interval")
return None, None, None, None
with open("ashby_jobs.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(FIELDS)
for board in BOARDS:
jobs = [j for j in get_board(board) if j.get("isListed", True)]
for j in jobs:
writer.writerow([board, j.get("id"), j["title"].strip(), j.get("department"), j.get("team"), j.get("location"),
j.get("workplaceType"), j.get("employmentType"), j.get("publishedAt"),
*salary(j), j.get("jobUrl")])
print(f"{board}: {len(jobs)} jobs")
time.sleep(1) # one request per board, with a pause
Run it with the board names after the file name:
$ python3 ashby_jobs.py ramp notion
ramp: 173 jobs
notion: 140 jobs
What we got on 27 October 2026: a CSV with 313 jobs, 166 of them with a salary (161 yearly and 5 monthly; in USD, CAD, GBP and SEK). One row, as it appears in the file:
ramp,34413f8d-26bf-4bbc-8ade-eb309a0e2245,"Security Engineer, Cloud",Engineering,Backend,"New York, NY (HQ)",Hybrid,FullTime,2026-04-07T17:12:35.753+00:00,211400,290600,USD,1 YEAR,https://jobs.ashbyhq.com/ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245
What the script does not do, to stay short: it keeps one salary range per job (Ashby's summary, not each pay zone); it leaves out secondary locations and descriptions; it does not filter by title or location; and it stops at the first board that fails (a wrong name 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 Ashby API in the cloud, and is worth it when you need more than that:
- Several systems in one schema: it reads Greenhouse and Lever boards too, and returns the same fields for all three, so one dataset covers a mixed list of companies.
- Remote and hybrid kept apart: for Ashby jobs with a work type,
isRemotefollows it, so hybrid jobs are not marked remote. - 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,
ashby:boardnames, 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": ["ashby:ramp", "ashby:notion"],
"titleKeywords": ["engineer"],
"onlyNewJobs": true,
"stateKey": "ashby-guide-test"
}
The first run saved 69 jobs with "engineer" in the title (39 at Ramp, all with a salary range; 30 at Notion, none), and only 1 of them was marked remote. 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 an Ashby account or an API key?
- Not for the job board endpoint in this guide. Ashby's other APIs, for the company's own recruiting data, need an API key from the company's own Ashby account (Ashby: Authentication) and are not covered here.
- Is it allowed to read Ashby job boards?
- The Job Postings API is the public, documented way to read an organisation's published job postings (Ashby describes it for companies that build their own careers page), and it needs no login or key. Ashby's documentation does not say anything about other uses: keep a gentle pace, and check that your use of the job texts is allowed where you are.
- Can I list every company that uses Ashby?
- 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
jobs.ashbyhq.comin the address of a job page or of the Apply button on the company's careers page. - Why is the salary empty for some companies?
- Ashby returns compensation only where the employer has set it up and shows it on its postings. In our test Notion's 140 jobs had none. Pay written only inside the description is not a field.
- What about Greenhouse, Lever and Workday?
- Greenhouse and Lever have their own guides: how to export jobs and salaries from Greenhouse job boards and how to export jobs and salaries from Lever job sites. The monitoring guide has a script for Greenhouse, Lever and Ashby together, and Workday has its own guide: how to export job postings from a Workday career site.
API, script and Actor tested by Quicksloth on 27 October 2026 on the public Ashby job boards of Ramp and Notion; job counts change every day. Field descriptions come from Ashby'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 Ashby, Apify or the companies named. Ashby and Apify are trademarks of their respective owners.