Use cases / Greenhouse Jobs API
Hiring signals for sales
Last updated September 28, 2026. Response excerpts are recorded from the live API.
Who
Who runs this, and what for
| Team | What they decide with it |
|---|---|
| Sales development teams | Which accounts to contact this week, with a reason that is specific to them. |
| Investors | Which portfolio or target companies are growing a function, from the roles they open. |
| Recruiting agencies | Which companies are opening roles they could fill. |
Pipeline
The calls, step by step
01Filter each board to the signals
Greenhouse search takes the company's board token and filters by title, department, office, and location on the request. q matches the job title, so one call per signal term keeps only the roles that matter.
GET /v1/search?engine=greenhouse&board=stripe&page=1 · results.0
{ "position": 1, "id": "8172487", "title": "Abuse Investigator", "company": "Stripe", "location": "Dublin", "remote": false, "departments": [ "8611 Security Analytics" ], "offices": [ "Ireland Locations" ], "url": "https://stripe.com/jobs/search?gh_jid=8172487", "first_published": "2026-09-03T17:30:34.000Z", "updated_at": "2026-09-12T17:25:25.000Z" }Recorded response. Live values differ. 02Diff against yesterday
Store the job ids you saw. A new id is a new opening; an id that disappears was filled or closed, which is a signal too. first_published tells you when Greenhouse first listed it.
GET /v1/search?engine=greenhouse&board=stripe&page=1 · results.0.first_published
"2026-09-03T17:30:34.000Z"Recorded response. Live values differ. 03Read the role before reaching out
The job endpoint returns the description and, where the company publishes them, pay ranges. The description names the tools the team uses today, which is what your first message should mention.
GET /v1/job?engine=greenhouse&board=stripe&id=8172487 · job
{ "id": "8172487", "title": "Abuse Investigator", "company": "Stripe", "location": "Dublin", "departments": [ "8611 Security Analytics" ], "offices": [ "Ireland Locations" ], "pay_ranges": [ { "title": "Salary", "min": 102000, "max": 153000, "currency": "USD" } ], "url": "https://stripe.com/jobs/search?gh_jid=8172487", "paragraphs": [ "Who we are", "About Stripe" ] }Recorded response. Live values differ.
Code
A script to start from
hiring_signals.py
# Daily diff of open roles on Greenhouse boards: which companies opened
# roles that signal a buying need. Keeps yesterday's job ids in seen.json.
import json, os, pathlib, requests
API = "https://api.clair.im"
HEADERS = {"Authorization": f"Bearer {os.environ['CLAIR_API_KEY']}"}
BOARDS = ["stripe", "airbnb", "figma"]
SIGNALS = ["data engineer", "revenue operations", "security engineer"]
STATE = pathlib.Path("seen.json")
seen = json.loads(STATE.read_text()) if STATE.exists() else {}
def jobs(board, q):
r = requests.get(f"{API}/v1/search", headers=HEADERS, timeout=60,
params={"engine": "greenhouse", "board": board, "q": q})
r.raise_for_status()
return r.json()["results"]
for board in BOARDS:
before = set(seen.get(board, []))
now = {}
for q in SIGNALS: # q matches the job title
for job in jobs(board, q):
now[job["id"]] = job
for job_id in now.keys() - before:
job = now[job_id]
print(f"{job['company']}: {job['title']} ({job['location']}) {job['url']}")
seen[board] = sorted(now)
STATE.write_text(json.dumps(seen, indent=2))
Set CLAIR_API_KEY to a key subscribed to the Greenhouse Jobs API. Each call is one request against that API's monthly quota.
Cost
What it costs per month
| Schedule | Requests | Plan | Per month | Per 1,000 |
|---|---|---|---|---|
| 100 accounts, 3 signals, daily100 boards × 3 searches × 30 days = 9,000 requests. | 9,000 | Pro | $121.36 | $13.48 |
| 100 accounts, 1 search, dailyOne unfiltered search per board, filtered in your code: 3,000 requests. | 3,000 | Pro | $49 | $16.33 |
| 500 accounts, 1 search, weekly500 boards × 4 weeks = 2,000 requests. | 2,000 | Pay as you go | $40.20 | $20.10 |
Limits
What to plan for
- Only companies that use Greenhouse and publish a public board. Find the board token in the company's careers URL.
- Greenhouse's own Job Board API is public and free. If you only need Greenhouse and can write the filtering, call it directly; Clair saves the filtering and gives the same schema as its Indeed and Glassdoor APIs.
- Search returns 25 jobs per page. A large company's unfiltered board can run to dozens of pages, so filter on the request.
- Titles are free text. A signal term such as data engineer misses Analytics Engineer; list the variants.
FAQ
Common questions
How do I find a company's board token?
Open its careers page and look for boards.greenhouse.io/<token> or job-boards.greenhouse.io/<token> in the links. The token is usually the company name.
Is one search per board cheaper than one per signal?
Yes, when a board has fewer than about 25 open roles per page you would read. For large boards, filtering on the request reads fewer pages.
What about companies on other applicant tracking systems?
Indeed and Glassdoor list most companies' openings whatever system they use. Search them by company name to cover accounts not on Greenhouse.
Run it on your own products
200 requests a month free on each API, no card. Enough to run the pipeline on a short list before choosing a plan.
Bloomberg News API
Associated Press API
Glassdoor API
Greenhouse Jobs API

Crunchbase API
Website Contacts API