Ashby Jobs API: how to get every open role from any Ashby job board (jobs.ashbyhq.com) as JSON
Ashby exposes a public Posting API for every company
that hosts its job board on jobs.ashbyhq.com. No key, no
login. This repository documents the endpoint, the fields, and ships a
dependency-free Python example.
The endpoint
GET https://api.ashbyhq.com/posting-api/job-board/{job_board_name}
GET https://api.ashbyhq.com/posting-api/job-board/{job_board_name}?includeCompensation=true
job_board_name is the slug in the board URL:
https://jobs.ashbyhq.com/notion → notion.
Companies embedding the board on their own domain still use the same
name; look for jobs.ashbyhq.com/<name> in the page
source.
What you get back
{"apiVersion": "1", "jobs": [...]}. Each job:
| Field | Example | Notes |
|---|---|---|
id |
8f6c... |
UUID, stable; diff between runs |
title |
Product Engineer |
|
department |
Engineering |
|
team |
Core |
|
location |
San Francisco |
primary location |
secondaryLocations[] |
[{"location":"New York"}] |
|
isRemote |
true |
explicit remote flag |
employmentType |
FullTime / PartTime /
Contract / Intern |
|
publishedAt |
2026-10-20T15:04:05.000Z |
ISO 8601 UTC |
jobUrl, applyUrl |
https://jobs.ashbyhq.com/notion/<id> |
|
descriptionHtml, descriptionPlain |
full description | |
compensation |
{"compensationTierSummary": "$180K – $220K"...} |
only with includeCompensation=true and only where
published |
Pagination and limits
No pagination: the whole board comes back in one response. No published rate limit; cache and keep request rates low.
Python example (stdlib only)
import json, urllib.request
def ashby_jobs(board):
url = f"https://api.ashbyhq.com/posting-api/job-board/{board}?includeCompensation=true"
req = urllib.request.Request(url, headers={"User-Agent": "your-app/1.0 (contact@example.com)"})
with urllib.request.urlopen(req, timeout=30) as r:
data = json.load(r)
for j in data["jobs"]:
yield {"id": j["id"], "title": j["title"], "department": j.get("department"), "team": j.get("team"),
"location": j.get("location"), "remote": j.get("isRemote"), "type": j.get("employmentType"),
"url": j["jobUrl"], "posted_at": j.get("publishedAt"),
"comp": (j.get("compensation") or {}).get("compensationTierSummary")}
if __name__ == "__main__":
rows = list(ashby_jobs("notion")); print(len(rows), "jobs"); print(rows[0])Finding Ashby boards
Search site:jobs.ashbyhq.com. Ashby is common among
2020s startups (Notion, Linear, Supabase, Cursor, Ramp and others).
Common questions
Is there a GraphQL endpoint too? The board UI uses an internal GraphQL API; the Posting API above is the public, documented one and is what you should use.
Why is compensation missing? The
company has not enabled public compensation on the posting, or you
omitted includeCompensation=true.
Hosted version, pay per result
If you would rather not run and maintain this yourself, the same logic runs as a pay-per-result Apify Actor by CleanFeeds: https://apify.com/cleanfeedsapi/ashby-jobs-api ($1.50 per 1,000 rows, no subscription, JSON/CSV/Excel export, API, scheduling, n8n/Make/Zapier and MCP integrations). A multi-ATS variant that mixes Greenhouse, Lever, Ashby, Workday, SmartRecruiters and Recruitee boards in one run: https://apify.com/cleanfeedsapi/ats-jobs-feed
Free sample data: a daily snapshot of about 10,000 open roles at 26 tech companies from these endpoints, CC BY 4.0: https://huggingface.co/datasets/cleanfeeds/tech-jobs-daily
More feeds: https://cleanfeeds.dev
Legal note
These are public, unauthenticated endpoints that the career pages themselves load. Job postings are employer announcements and belong to the employers. Be polite: identify your client with a User-Agent, cache results, and do not hammer the endpoints. Nothing here is affiliated with or endorsed by Ashby.