Practical guide
How to Export All Jobs from a Greenhouse, Lever or Ashby Job Board (Free Public APIs)
Last reviewed: October 22, 2026
Find the hosted board, read its public jobs endpoint and convert the response to CSV. Public board GET requests differ from authenticated recruiting APIs used to manage candidates. These examples export listings without submitting applications.
Find the board token or slug
Follow a job link from the company careers page. On a hosted board, the path or subdomain identifies the board. For a custom page, inspect linked hosted jobs or the browser Network panel for its JSON request. Confirm branding and destinations; a plausible slug alone is not identity evidence.
| Hosted board | Identifier |
|---|---|
job-boards.greenhouse.io/stripe | Greenhouse token: stripe |
jobs.lever.co/spotify | Lever site: spotify |
jobs.ashbyhq.com/ramp | Ashby board: ramp |
apply.workable.com/blueground/ | Workable account: blueground |
fastned.recruitee.com/ | Recruitee subdomain: fastned |
These examples were checked October 22, 2026. They are not endorsements or permanent fixtures. Companies can migrate between ATS providers.
Exact public job board API endpoints
| Platform | GET endpoint | Response and pagination |
|---|---|---|
| Greenhouse | https://boards-api.greenhouse.io/v1/boards/{token}/jobs?content=true | Object with jobs array; no paging parameter documented for this route. |
| Lever | https://api.lever.co/v0/postings/{company}?mode=json | Array; use limit and skip. EU host: api.eu.lever.co. |
| Ashby | https://api.ashbyhq.com/posting-api/job-board/{name}?includeCompensation=true | Object with jobs array; no pagination documented for this public route. |
| Workable | https://apply.workable.com/api/v1/widget/accounts/{slug} | Object with jobs array. Public widget, not authenticated SPI API. |
| Recruitee | https://{slug}.recruitee.com/api/offers/ | Object with offers array; reference documents department/tag filters, not paging. |
All five example endpoints returned HTTP 200 and valid arrays in live curl checks. Workable documents its widget, but a stable public contract for the exact widget route was not established. Validate its schema each run. Sources: Greenhouse: Job Board API, Lever: official Postings API documentation, Ashby: public Job Postings API, Workable: careers page options, Workable: live widget response checked October 22, 2026 and Recruitee: public careers offers endpoint.
Recruitee notice: official docs announce a Careers Site API token deadline of February 10, 2027, after which unauthenticated calls return 401. Do not promise ongoing keyless access. The page excludes XML feeds and the jobs widget from that scope. Recruitee: February 2027 authentication deadline.
Greenhouse and Ashby: curl plus jq to CSV
Use curl and jq from your normal system tools. Quote URLs so ampersands do not become shell operators. Save and validate JSON before conversion. The examples select practical columns while retaining the original response for secondary locations, descriptions and compensation.
curl --fail --silent --show-error --max-time 30 \
'https://boards-api.greenhouse.io/v1/boards/stripe/jobs?content=true' > greenhouse.json
jq -e '.jobs | type == "array"' greenhouse.json
jq -r '(["id","title","location","department","url"]),
(.jobs[] | [.id,.title,.location.name,
([.departments[]?.name] | join("; ")),.absolute_url]) | @csv' \
greenhouse.json > greenhouse.csv
curl --fail --silent --show-error --max-time 30 \
'https://api.ashbyhq.com/posting-api/job-board/ramp?includeCompensation=true' > ashby.json
jq -e '.jobs | type == "array"' ashby.json
jq -r '(["id","title","location","department","apply_url"]),
(.jobs[] | [.id,.title,.location,.department,.applyUrl]) | @csv' \
ashby.json > ashby.csv
Run each block in a shell that stops on errors, for example a Bash script with set -euo pipefail. Ashby compensation still depends on supplied data. Do not invent missing salary. The jq manual documents CSV quoting.
Lever pagination beyond the first page
Save as export_lever.sh and run bash export_lever.sh spotify. This Bash example uses limit/skip and spaces requests. It continues until an empty page rather than assuming the server honored the requested page size.
#!/usr/bin/env bash
set -euo pipefail
company="$1" # Usage: bash export_lever.sh spotify
api='https://api.lever.co' # EU boards: https://api.eu.lever.co
skip=0
limit=100
printf '%s\n' 'id,title,location,department,apply_url' > lever.csv
while :; do
page=$(curl --fail --silent --show-error --max-time 30 \
"$api/v0/postings/$company?mode=json&limit=$limit&skip=$skip")
count=$(jq -er 'if type=="array" then length else error("Expected array") end' <<<"$page")
[ "$count" -gt 0 ] || break
jq -r '.[] | [.id,.text,.categories.location,.categories.department,.applyUrl] | @csv' \
<<<"$page" >> lever.csv
skip=$((skip + count))
sleep 1
done
Use the EU API host for a board on jobs.eu.lever.co. This one-off script stops on HTTP errors; discard partial CSV output. For recurring collection, add finite retries, backoff, a request cap and repeated-page detection. Never retry authorization failures with credentials you do not have.
Workable and Recruitee exports
curl --fail --silent --show-error --max-time 30 \
'https://apply.workable.com/api/v1/widget/accounts/blueground' > workable.json
jq -e '.jobs | type == "array"' workable.json
jq -r '(["id","title","city","apply_url"]),
(.jobs[] | [.shortcode,.title,.city,.application_url]) | @csv' \
workable.json > workable.csv
curl --fail --silent --show-error --max-time 30 \
'https://fastned.recruitee.com/api/offers/' > recruitee.json
jq -e '.offers | type == "array"' recruitee.json
jq -r '(["id","title","location","apply_url"]),
(.offers[] | [.id,.title,.location,.careers_apply_url]) | @csv' \
recruitee.json > recruitee.csv
The Workable widget can expose summaries without descriptions or salaries. Recruitee may supply multiple locations and translations. Select required fields rather than redistributing entire payloads, which can contain contact and application-related fields.
Completeness, limits and the easy option
Compare counts with the board at collection time, recognizing that postings can change during pagination. Preserve IDs as strings and deduplicate by platform, board and native ID. A changed title is not a new ID. An empty valid array differs from a failed fetch.
Read robots.txt and applicable terms. Use a truthful client identifier, low request volume and backoff for temporary errors. Do not bypass access blocks or disabled endpoints. Import untrusted CSV fields as text in spreadsheets to avoid formula interpretation.
ATS Jobs Scraper accepts platform prefixes or hosted URLs and normalizes titles, locations, departments, apply links and salary when exposed. Missing values remain null. Explicit platforms avoid ambiguous auto-detection.
{
"companies": ["greenhouse:stripe", "lever:spotify", "ashby:ramp"],
"includeDescription": true,
"maxJobsPerCompany": 0,
"maxResults": 2000,
"requestDelayMs": 1000
}
Increase caps for a larger inventory and check RUN_SUMMARY. Filters and caps can omit jobs. “All jobs” requires successful complete fetches and sufficient output limits. For repeat runs, follow the new-posting monitoring guide.
Frequently asked questions
Do these exports need an ATS API key?
The tested public GET routes worked without a key on October 22, 2026. Recruitee announces a Careers Site API token deadline for February 10, 2027. Management APIs are separate.
Why is the board token hard to find?
A company can use a custom page or a different ATS. Inspect a hosted job link or JSON request and verify ownership before trusting a guessed slug.
Does one Lever request guarantee all jobs?
No. Use limit and skip, continue paging and verify a complete export before replacing a monitoring baseline.
Why are salary or description fields empty?
The public source may not expose them or the employer may not supply them. Preserve unknowns rather than inferring missing data.
Sources
Primary documentation and official authorities reviewed for this guide. Live responses are observations on the review date; source policies and laws can change.
- Greenhouse: Job Board API
- Lever: official Postings API documentation
- Ashby: public Job Postings API
- Workable: careers page options
- Workable: live widget response checked October 22, 2026
- Recruitee: public careers offers endpoint
- Recruitee: February 2027 authentication deadline
- jq: official manual
- RFC 9309
Tool inputs, outputs and limitations: ATS Jobs Scraper documentation.