Working recipes for reading job postings from ATS public APIs
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Documented (README)
git clone https://github.com/HwangByeongSeon/ats-job-feed-recipesResumen de Tools
# ATS job feed recipes
[](https://allmcps.com/mcp/career-site-job-feed)
Working code for pulling job postings straight out of company applicant tracking systems —
Greenhouse, Lever, Workday, Ashby, Workable, SmartRecruiters, Breezy, Personio, Pinpoint and
Rippling — and doing something useful with them.
Every script here runs as-is. Set `APIFY_TOKEN` and go.
```bash
export APIFY_TOKEN=... # https://console.apify.com/settings/integrations
python python/new_jobs_to_csv.py
```
## Why this exists
Each of these platforms publishes an open JSON endpoint that the company's own careers page reads —
no key, no login, no scraping of rendered HTML. The awkward parts are everything around that:
- **Every platform has a different shape.** Greenhouse nests offices and departments; Workday sends
a POST and reports posting age as the string `"Posted 30+ Days Ago"`; SmartRecruiters caps a
response at 100 rows whatever `limit` you pass; Breezy answers `403` for a board that does not
exist, where everyone else uses `404`.
- **Finding out who is on which platform is the actual work.** There is no public directory of
Greenhouse or Personio boards. The slug is in a careers URL somewhere, if you can find the
careers URL.
- **Dates are unreliable.** Three of these ten platforms publish no posting date at all, so any
"posted in the last N days" filter has to decide what to do with rows whose age is unknown.
The scripts below use [Apify Actors](https://apify.com/starbright_overlap) that have already dealt
with all of that and return one row shape across every platform. You can equally point them at the
raw endpoints — the [notes](#raw-endpoints) at the bottom list them.
## Recipes
| File | What it does |
|---|---|
| [`javascript/watch-companies.mjs`](javascript/watch-companies.mjs) | Diff a shortlist between runs — what opened, what closed |
| [`javascript/salary-data.mjs`](javascript/salary-data.mjs) | Postings that publish a pay range, normalised to an annual figure |
| [`python/one_company.py`](python/one_company.py) | Every open role at one company, from its careers URL |
| [`python/new_jobs_to_csv.py`](python/new_jobs_to_csv.py) | Only postings that appeared since the last run, appended to CSV |
These Actors bill per row delivered. Every script caps itself at a couple of hundred rows and
reads `MAX_ROWS` if you want more, so running an example does not produce a surprise.
## The row shape
Every recipe gets the same fields, whichever platform the job came from:
```json
{
"provider": "greenhouse",
"company": "Databricks",
"companySlug": "databricks",
"jobId": "7845321",
"title": "Staff Software Engineer",
"location": "San Francisco, CA",
"department": "Engineering",
"employmentType": "Full-time",
"remote": false,
"postedAt": "2026-08-14T09:12:00.000Z",
"applyUrl": "https://boards.greenhouse.io/databricks/jobs/7845321",
"salary": null,
"descriptionText": "...",
"scrapedAt": "2026-08-19T11:02:41.883Z"
}
```
`companySlug:jobId` is stable while a posting is open, which is what makes the diffing recipes work.
## What each platform actually publishes
Measured from live boards, not from vendor documentation. Useful before you build on any one of them:
| Field | Workday | SmartRecruiters | Greenhouse | Workable | Lever | Ashby | Breezy | Personio | Pinpoint | Rippling |
|---|---|---|---|---|---|---|---|---|---|---|
| title, company, location | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| applyUrl | yes | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| postedAt | partial | yes | yes | yes | yes | yes | yes | no | no | no |
| department | no | yes | yes | yes | yes | yes | yes | yes | yes | yes |
| employmentType | yes | yes | no | yes | yes | yes | yes | yes | yes | no |
| descriptionText | no | no | yes | yes | yes | yes | no | no | yes | no |
| salary | no | no | no | no | no | yes | yes | no | 37% | no |
Workday's `partial` is the `"Posted 30+ Days Ago"` problem: an exact age becomes a timestamp, a
vague one stays `null` rather than being invented.
## Raw endpoints
If you would rather call the platforms directly, these are the public endpoints. All of them answer
without a key. Replace `{company}` with the board slug.
| Platform | Endpoint |
|---|---|
| Greenhouse | `https://boards-api.greenhouse.io/v1/boards/{company}/jobs?content=true` |
| Lever | `https://api.lever.co/v0/postings/{company}?mode=json` |
| Ashby | `https://api.ashbyhq.com/posting-api/job-board/{company}?includeCompensation=true` |
| SmartRecruiters | `https://api.smartrecruiters.com/v1/companies/{company}/postings?limit=100&offset=0` |
| Workable | `https://apply.workable.com/api/v1/widget/accounts/{company}?details=true` |
| Breezy | `https://{company}.breezy.hr/json` |
| Personio | `https://{company}.jobs.personio.de/search.json` |
| Pinpoint | `https://{company}.pinpointhq.com/postings.json` |
| Rippling | `https://api.rippling.com/platform/api/ats/v1/board/{company}/jobs` |
| Workday | `POST https://{tenant}.{cluster}.myworkdayjobs.com/wday/cxs/{tenant}/{site}/jobs` |
Two things that will bite you if you write your own client:
- **SmartRecruiters** returns at most 100 postings per response regardless of `limit`. Page with
`offset`, and take the real total from `totalFound` rather than counting rows.
- **Breezy** returns `403`, not `404`, for a subdomain with no board on it. Treating that as rate
limiting and backing off turns a half-hour job into a fourteen-hour one.
## Licence
MIT. The Actors these scripts call are commercial and priced per row; the code here is not.
Lo que la gente pregunta sobre ats-job-feed-recipes
¿Qué es HwangByeongSeon/ats-job-feed-recipes?
+
HwangByeongSeon/ats-job-feed-recipes es tools para el ecosistema de Claude AI. Working recipes for reading job postings from ATS public APIs Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-08-19.
¿Cómo se instala ats-job-feed-recipes?
+
Puedes instalar ats-job-feed-recipes clonando el repositorio (https://github.com/HwangByeongSeon/ats-job-feed-recipes) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar HwangByeongSeon/ats-job-feed-recipes?
+
Nuestro agente de seguridad ha analizado HwangByeongSeon/ats-job-feed-recipes y le ha asignado un Trust Score de 95/100 (tier: Verified). Revisa el desglose completo de comprobaciones superadas y flags en esta página.
¿Quién mantiene HwangByeongSeon/ats-job-feed-recipes?
+
HwangByeongSeon/ats-job-feed-recipes es mantenido por HwangByeongSeon. La última actividad registrada en GitHub es del 2026-08-19, con 0 issues abiertos.
¿Hay alternativas a ats-job-feed-recipes?
+
Sí. En ClaudeWave puedes explorar tools similares en /categories/tools, ordenados por popularidad o actividad reciente.
Despliega ats-job-feed-recipes en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/hwangbyeongseon-ats-job-feed-recipes)<a href="https://claudewave.com/repo/hwangbyeongseon-ats-job-feed-recipes"><img src="https://claudewave.com/api/badge/hwangbyeongseon-ats-job-feed-recipes" alt="Featured on ClaudeWave: HwangByeongSeon/ats-job-feed-recipes" width="320" height="64" /></a>Más Tools
A single CLAUDE.md file to improve Claude Code behavior, derived from Andrej Karpathy's observations on LLM coding pitfalls.
An AI skill that provides design intelligence for building professional UI/UX across multiple platforms.
🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman
CLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies
The best-benchmarked open-source AI memory system. And it's free.
The fastest, litest AI Gateway. Rust core with Python SDK. Call 100+ LLM APIs in OpenAI (or native) format with cost tracking, guardrails, load balancing, and logging [Bedrock, Azure, OpenAI, Anthropic, OpenAI, VertexAI, vLLM, Nvidia NIM]