Which ATS does a company use? How to find its job board (Greenhouse, Lever, Ashby, Workday)

Last updated: 4 November 2026 · By Quicksloth

Before you can download a company's open jobs, you need two things: the system it posts them on (its ATS, applicant tracking system) and the name of its job board in that system, such as figma on Greenhouse or ramp on Ashby. This guide shows where those two things show up, how to confirm them with one request to the system's public API, and a short free script that does both. We ran it today on 14 well-known companies: it recognised 12.

Short answer: open any job on the company's careers page and read the address. greenhouse.io, lever.co, ashbyhq.com or myworkdayjobs.com tell you the system, and the part right after the domain is the board name. If the careers page stays on the company's own domain, search its page source for those domains, or try the company name on the three public APIs: HTTP 200 means the board exists, 404 means it does not. Workday addresses cannot be guessed; you have to find one.

The fastest check: open a job and read the address

Click any job on the careers page, or its Apply button, and look at the address bar. These are the addresses we saw on 4 November 2026:

SystemJob page address looks likeWhat you need
Greenhouseboards.greenhouse.io/figma/jobs/… or job-boards.greenhouse.io/gitlab/jobs/…board name (Greenhouse calls it the "Job Board URL token"): figma
Leverjobs.lever.co/spotify/… (EU instance: jobs.eu.lever.co/…)board name: spotify
Ashbyjobs.ashbyhq.com/ramp/…board name: ramp
Workdayredhat.wd5.myworkdayjobs.com/jobs/…three parts: company (redhat), the wd5 number and the site (jobs)

Addresses on smartrecruiters.com, workable.com, icims.com, jobvite.com and similar domains mean another system. This guide, its script and our Actors do not cover those.

When the careers page hides it: look in the page source

Many careers pages list the jobs on the company's own domain. The system's address is then often still in the page: right-click and choose View page source (in most browsers), then search for greenhouse, lever.co, ashbyhq or myworkday. What we found in the HTML of real careers pages on 4 November 2026, downloaded once each without running JavaScript:

Careers pageWhat the source containsSystem and board
figma.com/careers/290 links to boards.greenhouse.io/figma/jobs/…Greenhouse, figma
notion.com/careers292 links to jobs.ashbyhq.com/notion/…Ashby, notion
ramp.com/careers336 links to jobs.ashbyhq.com/ramp/…Ashby, ramp
linear.app/careers62 links to jobs.ashbyhq.com/Linear/…Ashby, Linear
careers.duolingo.coma call to Greenhouse's API: boards-api.greenhouse.io/v1/boards/duolingo/departmentsGreenhouse, duolingo
Workday's own careers pagelinks to workday.wd5.myworkdayjobs.com/Workday/Workday, workday / wd5 / Workday
redhat.com/en/jobslinks to redhat.wd5.myworkdayjobs.com/jobs/Workday, redhat / wd5 / jobs

That is 7 of the 14 pages we tried. The other seven had no system address in their HTML: GitLab, Stripe, Cloudflare, Spotify, Salesforce and NVIDIA build or link their job lists in other ways, and OpenAI's careers page answered our request with HTTP 403. Greenhouse boards can also be embedded with an address like boards.greenhouse.io/embed/job_board?for=<board>, where the board name follows for=; none of our 14 pages used it, but the script below looks for it too.

When the job list is built by JavaScript, the board address may appear only in the requests the page makes while it loads. In the browser's developer tools (F12), open the Network tab, reload the page and type greenhouse, lever, ashby or myworkday in the filter box.

Guess the board name and ask the API

Greenhouse, Lever and Ashby all have a public job board API that needs no key, so you can test a guess with one request. Greenhouse's documentation says it plainly: "Job Board data is publicly available, so authentication is not required for any GET endpoints" (Greenhouse Job Board API, read on 4 November 2026). Lever documents its Postings API and Ashby its Job Postings API.

https://boards-api.greenhouse.io/v1/boards/<board>/jobs
https://api.lever.co/v0/postings/<board>?mode=json
https://api.ashbyhq.com/posting-api/job-board/<board>

HTTP 200 means the board exists; 404 means it does not. For the seven companies whose page source showed nothing, we tried the company name in lower case on all three on 4 November 2026:

Name triedGreenhouseLeverAshby
gitlab200, 239 jobs404404
stripe200, 754 jobs404404
cloudflare200, 468 jobs404404
spotify404200, 84 jobs404
openai404404200, 812 jobs
salesforce404404404
nvidia404404404

Three things we learned from the answers:

Workday is different: company, wdN and site

A Workday career site has an address like https://<company>.wd<N>.myworkdayjobs.com/<site>. The number after wd differs from company to company, and the site name is chosen by the company, so there is no single request that answers "does this company use Workday?". You have to find one address, by clicking a job or from the page source. The four Workday sites of our test, checked on 4 November 2026 with the JSON request the career page itself makes (explained in our Workday guide):

CompanyCareer siteWhere we found itJobs
Workdayworkday.wd5.myworkdayjobs.com/Workdaysource of its careers page362
Red Hatredhat.wd5.myworkdayjobs.com/jobssource of its careers page138
NVIDIAnvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSitenot on its careers page, which links to a job search at jobs.nvidia.com; that page's Sign In link points to the Workday site2,000 (Workday's count stops there)
Salesforcesalesforce.wd12.myworkdayjobs.com/External_Career_Sitenot in the HTML of its jobs page, which has no job links until JavaScript runs; we used the address from our Workday guide1,554

Once you have the host (for example workday.wd5.myworkdayjobs.com), its robots.txt is worth a look: on all four hosts above it listed the company's career sites, one Sitemap: line each (four sites for Workday, nine for Salesforce, including Slack and Tableau). It also says which sites may be read: the script below checks it before each Workday request.

A free Python script: careers page in, system and board out

The script does the two steps above for a list of companies. It reads each careers page once (if the site's robots.txt allows it), looks for Greenhouse, Lever, Ashby and Workday addresses in the source, and checks what it found on the system's API. If the page shows nothing, it tries the company name on the Greenhouse, Lever and Ashby APIs. It pauses one second between requests and uses only Python's standard library (Python 3.8 or later).

"""Find which ATS a company uses (Greenhouse, Lever, Ashby, Workday) and the name of its job board.

Step 1: read the careers page once (if its robots.txt allows it) and look for job-board addresses in the source.
Step 2: check what step 1 found on the system's public API, or, if it found nothing, try the company name
        on the Greenhouse, Lever and Ashby APIs (HTTP 200 = the board exists, 404 = it does not).
"""
import json
import re
import sys
import time
import urllib.error
import urllib.request
import urllib.robotparser
from collections import Counter
from urllib.parse import urlsplit

UA = "which-ats-script"
COMPANIES = [arg.split("=", 1) for arg in sys.argv[1:]] or [["Figma", "https://www.figma.com/careers/"]]
PATTERNS = {
    "greenhouse": r"(?:job-)?boards(?:-api)?\.greenhouse\.io/(?:embed/job_(?:board|app)(?:/js)?\?(?:[^\"'\s<>]*?&(?:amp;)?)?for=|v1/boards/)?([A-Za-z0-9_-]+)",
    "lever": r"(?:jobs|api)\.lever\.co/(?:v0/postings/)?([A-Za-z0-9_.-]+)",
    "ashby": r"(?:jobs\.ashbyhq\.com|api\.ashbyhq\.com/posting-api/job-board)/([A-Za-z0-9_.%-]+)",
    "workday": r"([a-z0-9-]+\.wd\d+\.myworkdayjobs\.com/(?:[a-z]{2}-[A-Z]{2}/)?[A-Za-z0-9_-]+)",
}
OTHERS = r"smartrecruiters\.com|workable\.com|icims\.com|jobvite\.com|recruitee\.com|bamboohr\.com|teamtailor\.com|personio\.(?:de|com)"
NOT_BOARDS = {"embed", "api", "js", "css", "static", "assets", "v0", "v1", "favicon.ico"}


def request(url, body=None):
    """Return (HTTP status, text). Errors such as 404 or 403 come back as a status, not an exception."""
    data = json.dumps(body).encode() if body else None
    headers = {"User-Agent": UA, "Content-Type": "application/json"} if body else {"User-Agent": UA}
    try:
        with urllib.request.urlopen(urllib.request.Request(url, data, headers), timeout=30) as response:
            return response.status, response.read().decode("utf-8", "replace")
    except urllib.error.HTTPError as error:
        return error.code, ""
    except (urllib.error.URLError, TimeoutError):
        return 0, ""  # no answer at all


def allowed(url):
    """Read robots.txt with our own User-Agent (some sites refuse Python's default one)."""
    parts = urlsplit(url)
    status, text = request(f"{parts.scheme}://{parts.netloc}/robots.txt")
    if status in (401, 403):
        return False
    robots = urllib.robotparser.RobotFileParser()
    robots.parse(text.splitlines() if status == 200 else [])
    return robots.can_fetch(UA, url)


def from_page(url):
    if not allowed(url):
        return {}, "robots.txt does not allow it"
    status, html = request(url)
    if status != 200:
        return {}, f"HTTP {status}"
    found = {}
    for ats, pattern in PATTERNS.items():
        names = Counter(m.rstrip(".%") for m in re.findall(pattern, html) if m.lower() not in NOT_BOARDS)
        if names:
            found[ats] = names.most_common(1)[0][0]  # the board the page links to most often
    others = sorted(set(re.findall(OTHERS, html)))
    return found, "other systems: " + ", ".join(others) if others else ""


def check(ats, board):
    """Ask the system's API for the board: returns (HTTP status, number of jobs as text)."""
    if ats == "greenhouse":
        status, text = request(f"https://boards-api.greenhouse.io/v1/boards/{board}/jobs")
        jobs = json.loads(text)["jobs"] if status == 200 else []
        company = f", company_name {jobs[0].get('company_name')!r}" if jobs else ""  # check it is the right company
        return status, f"{len(jobs)} jobs{company}" if status == 200 else ""
    if ats == "lever":
        status, text = request(f"https://api.lever.co/v0/postings/{board}?mode=json")
        return status, f"{len(json.loads(text))} jobs" if status == 200 else ""
    if ats == "ashby":
        status, text = request(f"https://api.ashbyhq.com/posting-api/job-board/{board}")
        return status, f"{sum(j.get('isListed', True) for j in json.loads(text)['jobs'])} jobs" if status == 200 else ""
    host, path = board.split("/", 1)  # workday: tenant.wdN.myworkdayjobs.com/[en-US/]site
    tenant, site = host.split(".")[0], path.split("/")[-1]
    api = f"https://{host}/wday/cxs/{tenant}/{site}/jobs"
    if not allowed(api):
        return "robots.txt does not allow it", ""
    status, text = request(api, {"appliedFacets": {}, "limit": 1, "offset": 0, "searchText": ""})
    return status, f"{json.loads(text).get('total')} jobs" if status == 200 else ""


def guesses(name):
    base = re.sub(r"[^a-z0-9 ]", "", name.lower()).split()
    return list(dict.fromkeys(["".join(base), "-".join(base)]))


hits = 0
for name, url in COMPANIES:
    found, note = from_page(url)
    how, results = "page source", {}
    for ats, board in found.items():
        results[ats] = check(ats, board)
        time.sleep(1)
    if not found:  # nothing in the page: try the company name on the three public APIs
        how = "name guess"
        for guess in guesses(name):
            for ats in ("greenhouse", "lever", "ashby"):
                if ats not in found:
                    status, jobs = check(ats, guess)
                    if status == 200:
                        found[ats], results[ats] = guess, (status, jobs)
                    time.sleep(1)
    hits += any(status == 200 for status, _ in results.values())
    answer = "; ".join(f"{ats}:{found[ats]} -> HTTP {s}, {n}" for ats, (s, n) in results.items()) or "not found"
    print(f"{name:<11} [{how}] {answer}" + (f"  ({note})" if note else ""))
    time.sleep(1)
print(f"Recognised {hits} of {len(COMPANIES)} companies")

Give each company as Name=careers page URL. The run on 4 November 2026:

$ python3 which_ats.py "Notion=https://www.notion.com/careers" "Ramp=https://ramp.com/careers" \
    "Linear=https://linear.app/careers" "Figma=https://www.figma.com/careers/" \
    "Duolingo=https://careers.duolingo.com/" "Workday=https://www.workday.com/en-us/company/careers/overview.html" \
    "Red Hat=https://www.redhat.com/en/jobs" "GitLab=https://about.gitlab.com/jobs/" "Stripe=https://stripe.com/jobs" \
    "Cloudflare=https://www.cloudflare.com/careers/jobs/" "Spotify=https://www.lifeatspotify.com/jobs" \
    "OpenAI=https://openai.com/careers/" "Salesforce=https://careers.salesforce.com/en/jobs/" \
    "NVIDIA=https://www.nvidia.com/en-us/about-nvidia/careers/"
Notion      [page source] ashby:notion -> HTTP 200, 146 jobs
Ramp        [page source] ashby:ramp -> HTTP 200, 168 jobs
Linear      [page source] ashby:Linear -> HTTP 200, 31 jobs
Figma       [page source] greenhouse:figma -> HTTP 200, 145 jobs, company_name 'Figma'
Duolingo    [page source] greenhouse:duolingo -> HTTP 200, 54 jobs, company_name 'Duolingo'
Workday     [page source] workday:workday.wd5.myworkdayjobs.com/Workday -> HTTP 200, 362 jobs
Red Hat     [page source] workday:redhat.wd5.myworkdayjobs.com/jobs -> HTTP 200, 138 jobs
GitLab      [name guess] greenhouse:gitlab -> HTTP 200, 239 jobs, company_name 'GitLab'
Stripe      [name guess] greenhouse:stripe -> HTTP 200, 754 jobs, company_name 'Stripe'
Cloudflare  [name guess] greenhouse:cloudflare -> HTTP 200, 468 jobs, company_name 'Cloudflare'
Spotify     [name guess] lever:spotify -> HTTP 200, 84 jobs
OpenAI      [name guess] ashby:openai -> HTTP 200, 812 jobs  (HTTP 403)
Salesforce  [name guess] not found
NVIDIA      [name guess] not found
Recognised 12 of 14 companies

What we got: 7 of 14 companies recognised from the page source and 5 more from the name guess, so 12 of 14. The two misses are the Workday companies whose careers pages do not show their Workday address. Given NVIDIA's job search page instead, python3 which_ats.py "NVIDIA=https://jobs.nvidia.com/careers" printed workday:nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite -> HTTP 200, 2000 jobs. The whole run took 87 seconds, mostly the one-second pauses.

What the script does not do, to stay short: it does not run JavaScript; it tries name guesses only when the page shows nothing, and only in two forms (red hat becomes redhat and red-hat); it does not check Lever's EU instance or Greenhouse's EU boards; it does not look for myworkdaysite.com addresses; and it only names other systems (SmartRecruiters, Workable, iCIMS, Jobvite and a few more) if it sees them in the page, without checking them.

Limits and common mistakes

The careers page is built with JavaScript.
Then the HTML has no job links, as on 7 of our 14 pages. Click a job in a browser, use the developer tools' Network tab, or try the name guess.
The site blocks scripts.
OpenAI's careers page answered our script with HTTP 403; its Ashby board answered normally. Do not try to get around a block: use the name guess or the address of a job you opened in your browser.
The careers page runs on one system and the applications on another.
NVIDIA's job search page is on its own domain, but its Sign In link goes to Workday. The system that holds the jobs is the one in the job and Apply addresses; when two systems show up, open a job to see which one it is.
The name guess finds a board, but it is another company.
Two companies can have similar names. Check Greenhouse's company_name, or open a job link from the response.
A board answers 200 with no jobs.
The board exists but has nothing posted right now, or the company has moved to another system. Look at the careers page again.
The company is on SmartRecruiters, Workable, iCIMS or another system.
This guide, the script and our Actors cover Greenhouse, Lever, Ashby and Workday only.

Next: export the jobs

With the system and the board name, you can read the jobs:

If you would rather not run scripts, we make two Actors on the Apify Store that read these boards in the cloud:

Both charge per job a run saves, plus Apify's small start charge for each run; the current prices are in the Pricing tab of each Actor's page.

Questions and answers

Is it allowed to look up a company's job board this way?
The script reads one public careers page per company, after checking its robots.txt, and then the public job board APIs that Greenhouse, Lever and Ashby document for publishing job postings, which need no login or key. Their documentation describes these APIs for companies that build their own careers pages and does not say anything about other uses. Workday does not offer the JSON address as a public API, and its robots.txt differs from company to company (the script checks it). Keep a gentle pace, and check that your use of the job texts is allowed where you are.
Is a Greenhouse board token secret?
No. It is the board name in the public job board address (figma in boards.greenhouse.io/figma). Greenhouse's documentation calls it the "Job Board URL token" and says that only the endpoint for submitting applications needs authentication, with the company's Job Board API key.
Can I list every company that uses Greenhouse, Lever, Ashby or Workday?
Not with these APIs: they work one board at a time, and neither the script nor our Actors has a directory of companies. You start from your own list of companies.
Does it tell me which ATS a company uses to screen my resume?
It tells you where the company publishes its open jobs. That is usually where applications go too, but this guide is about reading job postings, not about resumes.
Why did the script find nothing for a company I know is hiring?
Most often the careers page loads its jobs with JavaScript, or the company uses Workday or a system this guide does not cover. Open a job in your browser and read the address: that settles it.

Script, page sources and APIs checked by Quicksloth on 4 November 2026 on the public careers pages and job boards of the 14 companies named; job counts change every day. Written with AI tools and checked by Quicksloth. Quicksloth is an independent developer and is not affiliated with Greenhouse, Lever, Ashby, Workday, Apify or the companies named. Greenhouse, Lever, Ashby, Workday and Apify are trademarks of their respective owners.