Jobs
Job-market data: normalized ATS job listings across Greenhouse, Lever, Ashby, and Workday, cross-board keyword search, Levels.fyi salary bands, and the async job status endpoints that power Pry's own background work.
What it scrapes
| Source | Data |
|---|---|
| ATS boards (greenhouse/lever/ashby/workday) | Normalized job postings per company (title, location, department, URL, posted date) |
| Multiple ATS boards | Cross-board keyword search (q matches title or location) |
| Levels.fyi | Per-level salary bands (total comp, base, stock, bonus) by company + role |
| Pry's async queue | Job status and results (GET /v1/job/{job_id}) + Pryfile job listing |
Endpoints
Router: routers/jobs.py · tag: Jobs
| Method | Path | Summary |
|---|---|---|
| GET | /v1/job/{job_id} | Async job status + result |
| GET | /v1/jobs | List jobs in a Pryfile (path default pry.yml) |
| GET | /v1/jobs/search | Cross-board keyword search (q, limit 1–100, default 20) |
| GET | /v1/jobs/salary/{company} | Salary bands from Levels.fyi (role default software_engineer) |
| GET | /v1/jobs/{board}/{company} | ATS job listings (limit 1–500, default 50) |
| GET | /v1/jobs/{board}/job/{job_id} | One job's full detail (company query param required) |
Routing note:
/v1/jobs/searchand/v1/jobs/salary/{company}are registered before the parametrized/v1/jobs/{board}/{company}route so the static segments are never swallowed by the{board}match.
GET /v1/jobs/{board}/{company}
Supported boards: greenhouse, lever, ashby, workday. Company is the
company slug on that board (e.g. stripe).
curl -X GET "http://localhost:8005/v1/jobs/greenhouse/stripe?limit=5" \
-H "Authorization: Bearer <key>"
Response (200):
{
"success": true,
"board": "greenhouse",
"company": "stripe",
"data": [
{
"id": "1234567",
"title": "Software Engineer, Backend",
"location": "Remote (US)",
"department": "Engineering",
"posted_at": "2026-08-10",
"url": "https://boards.greenhouse.io/stripe/jobs/1234567"
}
]
}
GET /v1/jobs/search
curl -X GET "http://localhost:8005/v1/jobs/search?q=backend&limit=10" \
-H "Authorization: Bearer <key>"
Response (200):
{
"success": true,
"data": [
{
"board": "greenhouse",
"company": "stripe",
"title": "Software Engineer, Backend",
"location": "Remote (US)",
"url": "https://boards.greenhouse.io/stripe/jobs/1234567"
}
]
}
GET /v1/jobs/salary/{company}
curl -X GET "http://localhost:8005/v1/jobs/salary/stripe?role=software_engineer" \
-H "Authorization: Bearer <key>"
Response (200):
{
"success": true,
"data": {
"company": "Stripe",
"role": "software_engineer",
"levels": [
{
"level": "L3",
"total_comp": 210000,
"base": 160000,
"stock": 35000,
"bonus": 15000
},
{
"level": "L4",
"total_comp": 280000,
"base": 190000,
"stock": 70000,
"bonus": 20000
}
]
}
}
Async job status
curl -X GET "http://localhost:8005/v1/job/abc123" \
-H "Authorization: Bearer <key>"
Response (200):
{
"success": true,
"data": {
"id": "abc123",
"status": "completed",
"result": {"pages": 12}
}
}
GET /v1/jobs?path=pry.yml lists all jobs defined in a Pryfile with their
current status and configuration.
MCP tools
No dedicated MCP tool for the jobs endpoints yet. The pry_template catalog
includes job-board templates (e.g. linkedin) — search with
pry_search_templates and run with pry_template.
Who uses this
- Talent intelligence — track a competitor's open roles and hiring velocity by board + company.
- Recruiters / market researchers — salary bands from Levels.fyi for comp benchmarking.
- Job aggregators — cross-board search as a lightweight feed source.
- Internal automation —
GET /v1/job/{job_id}to poll Pry's own async scrape/crawl jobs.
Next steps
- Browser Automation — automate application portals
- Extraction API — extract job postings from any careers page
- Monitoring — watch job boards for new postings