Greenhouse Jobs Lookup — Live Postings by Company
Pricing
from $3.00 / 1,000 successful lookups
Greenhouse Jobs Lookup — Live Postings by Company
Look up any company's live Greenhouse job board and get every open role — title, location, department, apply link. Paste company names or URLs, press Start. Charged once per company checked, no matter how many roles it has open — none open costs nothing.
Pricing
from $3.00 / 1,000 successful lookups
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
6 hours ago
Last modified
Categories
Share
Paste a list of companies and get every open role from each one's Greenhouse job board — title, location, department, and apply link — as one row per posting, or one row per company. No API key and no HTML scraping: this reads Greenhouse's own public job board API directly. Optional filters narrow results by title, location, or posting date, and a delta mode returns only the postings that are new since your last run.
Who it's for
The accountable_eel catalogue sells company intelligence columns for outbound. Each actor takes a list of domains or company identifiers and returns one flat, stably-named row per input — firmographics, registry IDs, tech stack, email route, hiring activity — the shape a Clay table, an n8n workflow, or an AI agent can consume without post-processing. Pricing is pay-per-event and per-domain: a few tenths of a cent for a row that was actually found, and nothing for a miss, so a list that doesn't enrich costs you next to nothing. Where an official source exists — VIES, GLEIF, SEC EDGAR, Brønnøysund, PRH, RDAP — it is queried directly instead of scraped. No seat licence, no monthly minimum, no credit system to decode. Here, the "identifier" is a Greenhouse board token or careers URL, and the "row" is a job posting — useful for sourcing candidates, watching a competitor's hiring, or tracking headcount signal across a target list.
Why this one
- Direct from Greenhouse's own API. No HTML scraping to break when a careers page gets
redesigned — this calls
boards-api.greenhouse.iothe same way Greenhouse's own careers pages do. - You pay per company, not per job. A board with 578 open roles and a board with 2 both cost
one
item-lookupcharge. A company with no board, or zero open roles, is a free miss. - Real filters, not a wall of raw fields. Title keyword include/exclude, location, remote-only, and posted-after-date all combine, so you can ask for exactly the roles you want instead of filtering 578 rows by hand afterward.
- A delta mode for watching hiring over time. Turn on
onlyNewSinceLastRun, put the actor on a schedule, and every run after the first returns only postings you haven't seen — a quiet week still gets a row, so you can tell "nothing new" from "the run broke." - Flexible input. A bare Greenhouse token or the full
boards.greenhouse.io/job-boards.greenhouse.iocareers URL both work — no need to go find the raw API slug first.
What you get
One row per open job posting by default — toggle "One row per job posting" off to get one row per
company instead, with the job list nested in jobs. The columns never move, whether or not
filters or delta mode are on:
| Field | Type / format | Description |
|---|---|---|
query | text | The company value you passed in, unchanged. |
found | boolean | true if the company has a Greenhouse board with at least one open role. Gates billing. |
status | text | OK, NOT_FOUND (no board or no open roles), or BAD_FORMAT (not a token or URL). |
boardToken | text | The board token, extracted from whatever you pasted. |
jobCount | number | Roles matched, after filters and delta filtering. |
totalJobCount | number | Roles on the board before filtering — shows what a filter dropped. |
newJobs | number | Roles new since your last run. Empty unless onlyNewSinceLastRun is on. |
firstRun | boolean | true on the baseline run for a watchlist. Empty unless delta mode is on. |
jobs | array | All matching jobs, each with the fields below. Expanded into separate rows in one-row-per-job mode. |
title | text | Job title. |
location | text | Office or region as Greenhouse lists it — e.g. "San Francisco", "Remote". |
departments | array | Department name(s), fetched from the board's separate department listing. |
remote | boolean | true if location or title reads as remote — matches "remote", "anywhere", "work from home", "wfh", "distributed". |
postedAt | date (ISO) | When Greenhouse first published the posting, falling back to updated_at. |
updatedAt | date (ISO) | When the posting was last edited. |
applyUrl | link | Direct apply link for the role. |
scrapedAt | date (ISO) | When this actor fetched the row. |
A company with no board, or a board with zero open roles, still returns one row with
found: false and a status/message explaining why — never charged.
Price
$5 per 1,000 companies, plus a $0.005 start fee. Misses (found:false) are never charged.
That works out to $0.005 per company whose board is found, on the FREE pricing tier (drops to
$0.003 on GOLD) — you're never billed for a company with no Greenhouse board or a BAD_FORMAT
input, no matter how many companies are in the list. However many roles a found company has open,
it's one charge: a board with 578 postings costs the same as one with 2.
1,000 companies through this actor: ~$5 if every one has a findable Greenhouse board, less if some don't. The same 1,000 rows through a credit-based enrichment platform: $80–$400. This actor does one thing — Greenhouse postings — and prices accordingly; it isn't a substitute for a general enrichment waterfall.
How to use
- In the Apify Console. Open the actor page and click Start — the
companiesfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"companies":["stripe"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
Paste one company per line — a bare Greenhouse token like stripe, or the full careers URL
(https://boards.greenhouse.io/stripe or https://job-boards.greenhouse.io/stripe). The token is
extracted automatically either way, so you don't need to go look up the raw API slug.
Common ways teams use this:
- Source candidates by pulling every open role matching a title keyword across a list of target companies in one pass.
- Watch a competitor's hiring with a fixed company list on a weekly schedule and delta mode on, so each run shows only what's new.
- Score hiring momentum across a target account list by reading
jobCountper company in one-row-per-company mode. - Find roles in a specific market by combining
locationswithtitleKeywordsinstead of exporting everything and filtering by hand. - Feed an ATS-aware outbound sequence by joining
applyUrlandpostedAtonto an existing account list in Clay or n8n.
For a standing watchlist, turn on onlyNewSinceLastRun in the 🔁 Watch for new jobs
section and put the actor on a schedule. The first run baselines (returns everything matching your
filters, firstRun: true); every run after that returns only postings it hasn't shown you before,
counted in newJobs. A quiet run still returns a row per company (jobCount: 0, newJobs: 0) so
you can tell "nothing new" from "the run failed" — and every company checked is still charged
once. Two schedules with different filter values keep separate seen-lists automatically, so
changing titleKeywords mid-stream just re-baselines that watchlist rather than corrupting it.
Input
{"companies": ["stripe"]}
One company per line — paste the Greenhouse token or the full careers page URL. Accepted formats: stripe, https://boards.greenhouse.io/stripe, https://job-boards.greenhouse.io/stripe.
To narrow what comes back, open the 🎯 Job filters section. All of these are optional, and they combine with AND across fields, OR within a field:
| Input | What it does |
|---|---|
titleKeywords | Keep only roles whose title contains at least one of these — ["engineer","designer"]. Case-insensitive, partial words count. |
excludeTitleKeywords | Drop roles whose title contains one of these — ["intern","contract"]. Applied after titleKeywords. |
locations | Keep only roles whose location contains one of these — ["Berlin","United Kingdom"]. |
remoteOnly | Keep only roles that read as remote. |
postedAfter | Keep only roles first published on or after this date — "2026-06-01". |
Leave every filter empty and you get every open role. jobCount (matched) and totalJobCount
(before filtering) both come back on every row, so a filtered result is never ambiguous — and a
company whose roles all get filtered out still returns a found: true row with jobCount: 0,
charged like any other found company, because it answered the question you asked.
Sample output
| query | found | status | boardToken | jobCount | totalJobCount | newJobs | firstRun | jobs | title | location | departments | remote | postedAt | updatedAt | applyUrl | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| stripe | true | OK | stripe | 589 | 589 | <all matching jobs (full list)> | Account Executive, AI Sales | San Francisco, CA | ["1175 Enterprise - Account Executives (NA)"] | false | 2026-02-03T15:19:01-05:00 | 2026-08-25T17:40:40-04:00 | https://stripe.com/jobs/search?gh_jid=7532733 | 2026-08-26T06:00:44.199Z |
That table lists every available column. In "one row per job posting" mode — the default — a real row reads like this:
{"query": "stripe","found": true,"status": "OK","boardToken": "stripe","jobCount": 589,"totalJobCount": 589,"title": "Account Executive, AI Sales","location": "San Francisco, CA","departments": ["1175 Enterprise - Account Executives (NA)"],"remote": false,"postedAt": "2026-02-03T15:19:01-05:00","updatedAt": "2026-08-25T17:40:40-04:00","applyUrl": "https://stripe.com/jobs/search?gh_jid=7532733","scrapedAt": "2026-08-26T06:00:44.199Z"}
A company with no Greenhouse board comes back as a miss and is never charged:
{"query": "not-a-real-company","found": false,"status": "NOT_FOUND","message": "No Greenhouse board found for this token","scrapedAt": "2026-08-26T06:00:44.199Z"}
Miss rows are still written to the dataset so you can see exactly which companies failed, rather than diffing your input list against the output.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"companies":["stripe"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"companies":["stripe"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~greenhouse-jobs-lookup/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"companies":["{{company}}"]}, mapping the row's company into the companies array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Greenhouse Jobs Lookup | Apify" — the agent will find and run this actor.
Tips
- Combine filters to build a watchlist query, not just a keyword search. plustitleKeywords: ["engineer"]
locations: ["Berlin"]plusremoteOnly: falsegets you Berlin-based engineering roles only, in one pass, instead of filtering a full dump afterward. - Put delta mode on a weekly schedule for competitor tracking.
onlyNewSinceLastRunplus a fixed company list turns this into a hiring-alert feed — you only see what changed since last time, and a quiet week still confirms the schedule is running. - Use
postedAfterfor "what opened this month", notupdatedAt. Greenhouse bumpsupdatedAton any edit, including typo fixes —postedAtonly moves when a role first goes live. - Switch to one-row-per-company mode for a headcount signal. Read
jobCountper company without pulling every posting into your table. - Don't combine delta mode with "Only keep rows containing." That filter runs on the finished
row and can drop the
newJobs: 0heartbeat row — the one row that tells you the schedule is still alive on a quiet week.
vs. alternatives
| What it costs | What you get | Trade-off | |
|---|---|---|---|
This actor (greenhouse-jobs-lookup) | $0.005 per company whose board is found (less on paid tiers), $0.005 actor start, nothing for a company with no Greenhouse board | Every open posting for a company's Greenhouse board — title, location, department, apply URL — filtered by role keyword, location or posting date, with onlyNewSinceLastRun for deltas | Greenhouse only. If your list is mixed-ATS, use ats-jobs-unified-lookup. Office data isn't returned — Greenhouse's own endpoint costs 78× the payload to include it. |
| TheirStack | $0.005–$0.03 per company | A job-postings dataset with history, normalised across many ATS platforms and job boards | Broader coverage than one platform, and it keeps history. This reads Greenhouse's own API live, at the bottom of that price range. |
| Greenhouse's own API | Free | The same JSON | It is the same JSON. This handles the board-token guessing, the second request departments actually live behind, filtering, deltas, and the retries — and hands you a flat table. |
| Clay | $0.08–$0.40 per enriched row in credits, on top of a seat | A whole enrichment workspace — waterfalls across dozens of providers, plus the table and the sequencing around it | If you want one place that does everything and you're not counting rows, that's Clay. This is one column, priced per column, callable from Clay via its HTTP step. |
Prices for third-party tools are their published list prices as of August 2026 and are not tracked here — check the vendor before relying on the comparison.
FAQ
Why does found say false, or a row come back empty?
Either the input didn't look like a Greenhouse token or URL (status: BAD_FORMAT), the company
doesn't have a Greenhouse board, or it currently has zero open roles (status: NOT_FOUND either
way). Check the message column for the specific reason.
Was I charged for that row?
Only if found is true. A company with no board, or no current openings, is free — check
status to confirm which case it was.
I got charged for a company that returned jobCount: 0 — why?
Its board exists and has open roles; they just didn't match your filters, or weren't new since
your last delta run. totalJobCount shows what was on the board before filtering. That's a real
answer to the question you asked, so it bills like any other found company. A company with no
board, or nothing open, is found: false and free.
How does delta state work, and can I reset it?
It lives in a named key-value store, greenhouse-jobs-lookup-state, inside your own Apify account
— nobody else can see it, and it holds only job IDs per company. Delete that store to reset every
watchlist. Changing your filters also starts a fresh watchlist automatically, since the filter
values are part of what identifies a seen-list.
Why is there no office field, and where do departments come from?
Greenhouse's job-listing endpoint omits both unless you request its heavyweight response, which
inlines every job's full HTML description — a large payload multiplier on a board with hundreds of
roles. So departments is filled from one extra request to the board's separate department
listing; if that request fails, every role still comes back, just with an empty departments
cell. Offices aren't reported at all, because the only endpoints carrying them cost far more than
the field is worth — better no column than a permanently blank one. location carries the place
information, and remoteOnly matches on both location and title.
Does this hit rate limits on large company lists? It calls Greenhouse's public board API once per company (twice with the departments hop), with its own timeouts and retries. That API is unauthenticated and public — the same one Greenhouse's own careers pages call — so no proxy is needed. Large lists just take proportionally longer.
Is this GDPR-safe to run against EU companies? Everything returned is already published publicly on each company's own careers page — titles, locations, departments, apply links. No personal data about applicants or employees is collected. You remain responsible for how you use the output downstream.
Can an AI agent call this directly? Yes — it's registered with the Apify MCP server. An agent with that MCP connected can find and run "Greenhouse Jobs Lookup" by name and get dataset rows back without you writing any integration code; see Use it from Clay, n8n, Make, or an AI agent.
Related actors
- ATS Jobs Unified Lookup — check a company across Greenhouse, Lever, Ashby, and other ATS platforms in one call when you don't know which one they use.
- Lever Jobs Lookup — the same lookup, filters, and delta mode for companies on Lever.
- Ashby Jobs Lookup — the same lookup, filters, and delta mode for companies on Ashby.