# Changelog of Greenhouse, Lever & Ashby Jobs Scraper - New Postings Mode (`halvenlabs/ats-jobs-scraper`) Actor

- **URL**: https://apify.com/halvenlabs/ats-jobs-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/halvenlabs/ats-jobs-scraper.md

## Changelog

All notable changes to this Actor are documented here.

### 1.5.0

#### Features

- **SmartRecruiters support** — the fourth ATS platform, alongside Greenhouse, Lever, and Ashby. Accepts `smartrecruiters:token`, careers/jobs page URLs, and API URLs; boards with more than 100 postings are paged through automatically. Note: SmartRecruiters' public list API doesn't expose descriptions, so `descriptionText` is empty for this platform.
- New `remoteOnly` filter input — keep only jobs the ATS marks remote (or with a 'remote' location), matching the remote filter competing ATS scrapers expose.

### 1.4.0

#### Fixed

- **Closed jobs are no longer re-reported (and re-charged) on every run.** Once a closed posting has been pushed, its key is dropped from the monitor snapshot; previously the same closed job was emitted again on every subsequent run for up to 90 days. If it reappears on the board it is correctly "new" again.
- **New-job mode no longer loses postings**: a new job cut off by `maxItems` or the charge budget now stays "new" for the next run. Previously it was recorded as seen without ever reaching the dataset, so `onlyNewJobs` runs would never deliver it. (Jobs excluded by the user's own title/location filters are still recorded — deliberate, unchanged.)

### 1.3.1

#### Fixes

- Greenhouse **embed board URLs** (`boards.greenhouse.io/embed/job_board?for=<token>`) now resolve to the right company token instead of the literal token `embed`.
- Percent-encoded tokens pasted as URLs (e.g. `jobs.ashbyhq.com/My%20Company`) are now decoded before the API URL is built, instead of being double-encoded into a 404.
- HTML-entity decoding in plain-text descriptions now decodes `&amp;` last, so double-escaped text (e.g. `&amp;lt;`) is decoded exactly once and can no longer reintroduce markup into `descriptionText`.
- When the pay-per-event budget limit is reached, the actor now actually stops emitting items (boards are still fetched so new/closed-postings history stays accurate).
- "Last seen" history entries with a missing or corrupt timestamp are now pruned instead of being retained forever.

### 1.3.0

#### Features

- New **closed-postings detection**: `includeClosedJobs` input emits a row (`isClosed: true`) for jobs seen in a previous run but no longer listed on a board actually checked this run. The persisted per-account history now stores a small snapshot (title/department/location/jobUrl) per job, not just a timestamp, so closed rows carry useful context instead of just an ID.
- Guarded against false positives: a board dropped from input, or one that fails transiently, never causes its previously-seen jobs to be reported as closed — only boards successfully checked in the current run are considered (verified with a live test: dropping a board from input produced 0 false "closed" rows for it).

### 1.2.0

#### Features

- New **"new postings" mode**: every row gets an `isNew` field, and the `onlyNewJobs` input filters output to just jobs not seen in a previous run. History is tracked per Apify account in a named key-value store, independent of the in-run `maxItems`/title/location filters, with a 90-day rolling retention.
- Renamed the actor to lead with the ATS platform names for discoverability, since "ATS Jobs Scraper — Greenhouse, Lever & Ashby" is already used verbatim by two other Store listings.

### 1.1.0

#### Features

- Added **Ashby** as a third supported ATS platform (`ashby:token` or `https://jobs.ashbyhq.com/…`), alongside Greenhouse and Lever, using Ashby's public job board API.
- New `compensationSummary` field, populated from Ashby's published salary/equity ranges (`null` for Greenhouse/Lever).

### 1.0.0

Initial release.

#### Features

- Full extraction with a flat, CSV/Excel-friendly dataset schema and a Store output table view.
- `maxItems` cap enforced globally (safe under concurrency), plus input validation with clear, fail-fast errors.
- Pay-per-event pricing: `actor-start` + per-result-item charging (charged only after an item is produced).
- Apify Proxy support, automatic retries with backoff, and graceful per-item degradation (one bad page never crashes the run).
- Resumable & migration-safe via `Actor.useState` (no double-charge on platform migration).

#### Security & robustness

- Input/redirect SSRF guards (block localhost, private/reserved IPs, cloud-metadata, `file://`) with DNS-rebinding resolution checks where user URLs are fetched.
- ReDoS-safe extraction patterns and response-body size caps.
- Push-failure rollback so a failed push never silently loses items or mischarges.
