# Apify Icims Job Monitor

> Track new iCIMS job postings without re-crawling a career site every day, using the Apify iCIMS Careers API Actor (johnvc/icims-careers-api) in change-detection mode. Set newerThan to a window like 24h or 7d and the Actor filters on the career site's own change data before it opens a single job page, so an employer with four hundred open requisitions costs you only the handful that actually moved. Add includeDetails false and each site costs one page fetch, which makes a daily poll of a large watchlist genuinely affordable. Rows carry url, requisition id, title, date posted and date updated, so diffing two runs tells you what opened, what was edited, and what closed. Use when the user wants job posting alerts, hiring signal, an ats api feed on a schedule, competitor headcount tracking, or a jobs change feed piped into Slack or a database. Pay per row returned, MCP-ready for Claude and other AI agents.

- Skill: `johnisanerd/apify-icims-job-monitor` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add johnisanerd/apify-icims-job-monitor`
- Raw SKILL.md: https://api.skillmd.com/api/skills/johnisanerd/apify-icims-job-monitor/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: johnisanerd (https://skillmd.com/u/johnisanerd)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/johnisanerd/apify-icims-job-monitor

---


# iCIMS Job Change Feed, Not a Nightly Re-Crawl

Poll a watchlist of employers daily and pay only for the requisitions that moved.

## When to use this skill

- The user wants to know when an employer posts something new, not what they have posted overall.
- They are building hiring signal, competitor tracking, or a jobs alert product.
- They already pulled a full snapshot and now need to keep it current.
- They want a scheduled feed into Slack, a database, or a spreadsheet.

Not for: the first full pull of an employer's jobs. Do that once with the companion apify-icims-jobs-api skill, then switch to this. See `references/actor-index.md`.

## Why this is cheap and a re-crawl is not

The classic iCIMS portal publishes its own change data for every live requisition. With `newerThan` set, the Actor applies the window to that data **before** it fetches any job page, so unchanged jobs are never opened. A naive scraper pays for all four hundred pages every night; this pays for the three that changed. On the modern career-site surface the same filter is applied to the site's own update field.

`includeDetails: false` takes it further: no job pages at all, just the list. One fetch per site.

## What you get

In list-only mode, one lean row per changed job:

- `url` (canonical and stable, the dedupe key), `id` (the employer's requisition number), `title`
- `date_posted`, `date_updated`
- `tenant`, `source_surface`, `source_domain`, `scraped_at`

The Actor's dataset also ships a **changes** view (url, date_updated, date_posted, title), which is the exact shape you want when diffing runs. Error rows carry `error_code` and `error_message` so an automated job can tell "nothing new" apart from "this employer left iCIMS".

## Prerequisites

- Apify account (sign up at https://apify.com?fpr=9n7kx3&fp_sid=skillrepo).
- Authentication via `apify login`, or an `APIFY_TOKEN` environment variable (Apify Console, Settings, Integrations).

## The Actor

- Store page: https://apify.com/johnvc/icims-careers-api?fpr=9n7kx3&fp_sid=skillrepo
- Actor ID: `johnvc/icims-careers-api`
- Pricing: pay per event; see the cost section below and `references/gotchas.md` for live-price commands.

## Run it with the Apify CLI

The cheapest daily poll there is:

```bash
apify actors call "johnvc/icims-careers-api" -i '{"startUrls":[{"url":"https://careers-rambus.icims.com"}],"newerThan":"24h","includeDetails":false}' \
  --json \
  --user-agent apify-awesome-skills/apify-icims-job-monitor \
  2>/dev/null
```

Brand-new requisitions only, ignoring edits to existing ones:

```bash
apify actors call "johnvc/icims-careers-api" -i '{"companies":["rambus","maxlinear"],"newerThan":"7d","cutoffField":"posted","includeDetails":false}' \
  --json \
  --user-agent apify-awesome-skills/apify-icims-job-monitor \
  2>/dev/null
```

A weekly digest with full detail on just the changed jobs:

```bash
apify actors call "johnvc/icims-careers-api" -i '{"startUrls":[{"url":"https://careers-rambus.icims.com"}],"newerThan":"7d","includeDetails":true,"descriptionFormat":"text"}' \
  --json \
  --user-agent apify-awesome-skills/apify-icims-job-monitor \
  2>/dev/null
```

Confirm live pricing and the input schema before scheduling a large watchlist:

```bash
apify actors info "johnvc/icims-careers-api" --json \
  --user-agent apify-awesome-skills/apify-icims-job-monitor \
  2>/dev/null
```

Every call carries the three flags this repo expects: `--json`, `--user-agent apify-awesome-skills/apify-icims-job-monitor`, and `2>/dev/null`.

## Run it from Claude or another AI agent (MCP)

The Actor is MCP-ready. Add the hosted server URL:

`https://mcp.apify.com/?tools=actors,docs,johnvc/icims-careers-api`

Then ask, for example: "Which of these five employers posted anything new this week?" MCP setup docs: https://docs.apify.com/platform/integrations/mcp

## Workflow

1. Pull one full snapshot first with the companion skill, and store it keyed on `url`.
2. Switch to `newerThan` plus `includeDetails: false` for the recurring poll.
3. Match the window to the cadence. A daily job uses `24h`; a weekly one uses `7d`. Overlap slightly rather than exactly, so a slow publish is not missed.
4. Choose `cutoffField`. Use `updated` to catch edits as well as new reqs, `posted` for new requisitions only.
5. Diff against the stored snapshot: a `url` you have never seen is a new job, a known `url` with a newer `date_updated` is an edit, and a `url` that stops appearing in a full run is a closed job.
6. Schedule it in the Apify Console under Schedules once the shape is right.

## Inputs that matter here

- `newerThan` (string): ISO date, timestamp, or `24h` / `7d` / `2w`. This is the whole point of the skill.
- `cutoffField` (enum `updated`, `posted`, default `updated`)
- `includeDetails` (boolean): set false for the cheap list-only feed
- `startUrls` (array of `{url}`) and `companies` (array of strings): the watchlist
- `keywords` (array of strings): narrow the feed to roles you care about
- `maxJobsPerSite`, `maxJobs`, `detailConcurrency`, `descriptionFormat`, `proxyConfiguration`: as in the companion skill

## Cost

Billing is pay per event, plus a negligible platform fee per dataset row. Confirm live prices with the info command above.

- List-only rows are charged on a cheaper event than full job rows. That gap is what makes daily polling viable.
- A quiet day on a watchlist costs close to the run-start charge alone, because there are almost no rows.
- A busy week still only bills the jobs that actually changed.

Suggested confirmation thresholds: warn the user over about $5; get explicit confirmation over about $20. Present cost as "around $X", never a guarantee.

## Honest limits

- Closed jobs are not announced. A requisition that disappears is only detectable by comparing against a full run, not from a change feed.
- On the search-fallback path, when a site exposes no change data, the filter is applied after fetching and the run logs a warning. The saving is smaller there.
- `newerThan` in the future returns zero rows. That is correct, not a failure.
- The Actor keeps no history of its own. Storing snapshots and diffing them is your side of the job.
- Error rows still cost a dataset item and the run still costs its start charge.

## Troubleshooting

- Zero rows every run: normal for a quiet employer. Widen `newerThan` once to confirm the pipe works.
- Too many rows: you are on `cutoffField: "updated"` and the employer is touching postings. Switch to `posted`.
- Rows without descriptions: expected in list-only mode. Set `includeDetails: true` for the ones you want to expand.
- The same job appears as new twice: you are keying on title or on a slugged URL. Key on `url`, which is canonical.
- `ip_gated` or `tenant_not_found` on a schedule: the employer changed something. Investigate before assuming a code failure.

See `references/gotchas.md` for cost guardrails and error recovery, and `references/actor-index.md` for the Actor routing table.

## Related Actors

- Workday Careers API: https://apify.com/johnvc/workday-careers-api?fpr=9n7kx3&fp_sid=skillrepo
- Google Jobs Scraper: https://apify.com/johnvc/Google-Jobs-Scraper?fpr=9n7kx3&fp_sid=skillrepo
- LinkedIn Company API: https://apify.com/johnvc/linkedin-company-api?fpr=9n7kx3&fp_sid=skillrepo
- Crunchbase Company API: https://apify.com/johnvc/crunchbase-company-api?fpr=9n7kx3&fp_sid=skillrepo

