ATS Jobs & Change Feed
Pricing
from $1.00 / 1,000 results
ATS Jobs & Change Feed
Normalize public Greenhouse, Lever, Lever EU, Ashby, and SmartRecruiters job boards, then emit stable job-change events.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Roman V
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Normalize public Greenhouse, Lever, Lever EU, Ashby, and SmartRecruiters job boards into one
stable schema. Use snapshot mode for a current export or changes mode to
emit NEW, UPDATED, and REMOVED records against a prior snapshot.
Why this Actor
- Uses public job-board APIs without applicant data, cookies, or customer credentials.
- Preserves the existing provider normalization,
canonical_job_id, andcontent_hashcontract. - Deduplicates jobs before delivery and keeps the previous representative of a duplicate URL group when that job is still observed.
- Keeps source errors in the
OUTPUTsummary instead of emitting them as job records. - Preserves the last complete state for an incomplete source observation, so a temporary outage, rejected provider row, or result cap does not create false removals on the next run.
- Uses SmartRecruiters public Posting API list and numeric-detail endpoints only. It never follows redirects, converts returned references into requests, or accesses applicant or administration data.
Input
Use at least 256 MB of memory. Larger inputs within the documented limits may need more memory; this minimum is not a measured hosted peak.
Add each public board to sources with its provider and board token. For
example, use stripe for Greenhouse, spotify for Lever, or ashby for Ashby.
The optional companyName becomes the display name when the provider does not
return one.
SmartRecruiters boardName is the case-sensitive company identifier from its
public job URL. The provider checks list and detail identity before accepting a
posting. It retains distinct numeric posting IDs even when two postings share a
URL, title, reference number, language, or default-ad relationship.
The default sample checks the three listed boards and selects at most three
matching jobs per board, nine jobs total. Larger boards therefore normally
report PARTIAL with snapshot_complete=false. Larger exports are opt-in: set
the existing maxJobsPerSource and maxTotalJobs limits explicitly.
For a recurring change feed, set outputMode to changes and select the prior
run's complete_state_dataset_id in previousDatasetId. The read-only dataset
picker works with limited Actor permissions. You can instead pass normalized
items in previousJobs, but do not provide both inputs.
The Actor accepts at most 10,000 prior-state records. It reads up to 10,001
records to detect an oversized baseline even when maxTotalJobs is smaller.
Malformed, inaccessible, conflicting, or oversized baselines fail before any
source request or dataset-item delivery. The run can still incur the platform's
automatic Actor-start charge; it does not deliver billable dataset items.
Exact repeated records are collapsed. Different records with the same
canonical_job_id are rejected with PREVIOUS_DATASET_INVALID; do not combine
multiple observations of the same job into a baseline.
Complete state and partial observations
Filters run before maxJobsPerSource and maxTotalJobs. If either cap clips
matching jobs, the run is PARTIAL, snapshot_complete is false, and prior
rows from the affected source are carried into the saved state. Failed sources
and sources with rejected provider rows use the same carry-forward rule.
SmartRecruiters also reports EMPTY, COMPLETE, TRUNCATED, PARTIAL, or
MALFORMED in each source diagnostic. Only validated EMPTY and COMPLETE
observations authorize removals. Pagination changes, missing or short pages,
duplicate IDs, list/detail contradictions, malformed detail fields, and detail
request failures keep useful fresh rows but carry the unobserved prior rows.
Carried rows are state only: they are not emitted as default-dataset change
events, and their original scraped_at value is preserved.
The candidate state labels rows as FRESH or CARRIED in
_snapshot_freshness. fresh_records, carried_records, clipped_records,
rejected_records, and planned_state_records report its exact composition.
After persistence is confirmed, saved_state_records reports the stored count
and the summary reports the same dataset ID in
current_snapshot_dataset_id and complete_state_dataset_id; the latter is the
explicit chaining field. snapshot_complete describes observation
completeness, not whether carried state was saved.
Changing query, location, remoteOnly, or publishedAfter starts a new
filtered view and suppresses removals from the old view. Removing a source drops
that source from the selected view; adding it again produces new events. A
legacy snapshot without scope metadata receives a conservative migration.
Unknown legacy scope is never promoted by carry-forward. A removal requires
that the individual prior row has verified matching scope and its source was
observed completely in the current run. An unrelated legacy or failed source
does not suppress a verified removal from a complete source. Rows already lost
by an older incomplete implementation cannot be reconstructed.
If every source fails, the Actor carries bounded prior state, emits no change events, and exits with a nonzero all-sources-failed status. Recovery can still compare against that carried state.
Delivery and billing integrity
In pay-per-event mode, the Actor advances state only after every planned
dataset item has a confirmed charged_count acknowledgement. A zero or partial
acknowledgement, an invalid receipt, or a write exception produces a stable
failure summary and does not save or advertise a next snapshot. Confirmed
counts remain exact; a write exception reports an explicit lower bound because
the attempted item's delivery is unknown. Retry with the same prior snapshot.
The platform's automatic Actor-start charge is separate from dataset-item delivery. This repair does not change pricing or metering configuration.
Output
Each default-dataset item includes stable identity, normalized title, company,
location, description, direct application and job URLs, provider provenance,
timestamps, and change_type. The OUTPUT record includes source diagnostics,
event counts, scope and completeness fields, delivery accounting, and the next
state dataset ID when both delivery and state persistence are confirmed.
SmartRecruiters output preserves validated raw applyUrl and postingUrl
links. Its content comparison removes only oga, trid, and the five named
UTM keys on jobs.smartrecruiters.com; other query keys, paths, trailing
slashes, fragments, and unknown-host links remain semantic. Language,
default-ad, active, and visibility changes are semantic. UUID, job-ad ID, job
ID, and reference-number-only changes are not. When includeRaw is enabled,
the list and detail records omit creator and avatarUrl fields.
Each SmartRecruiters source is finite: 100 records per list page, at most 50
list pages, 5,050 list-plus-detail requests, 512 KiB per response, 64 MiB of
received response bodies, 15 seconds per request, and 45 seconds for the
source. Detail requests are sequential. Blocking DNS, TLS, headers, and body
reads run behind a killable worker-process deadline. Redirects, proxies,
credentials, cookies, and retries are not used. These limits can make a source
partial and are reported in provider_diagnostics for later unit-cost checks.
Scope
This Actor reads published employer job postings only. It does not submit job applications, collect candidate data, bypass access controls, or read private ATS administration APIs.