# Indeed Expired Job Checker — Dead Listing Monitor (`scrapersdelight/indeed-job-status-checker`) Actor

Check Indeed job listings for $1 per 1,000 keys — live, expired, or removed. Bulk-verify jobkeys/URLs, harvest fresh keys by keyword + city, or schedule a nightly dead-listing monitor with Slack/email/webhook alerts. Full job data (salary, company, dates) on every key. No login or API key.

- **URL**: https://apify.com/scrapersdelight/indeed-job-status-checker.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job key checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## 💼 Indeed Expired Job Checker — Dead Listing Monitor

**Feed it Indeed jobkeys or job URLs and get back a clean verdict for every one — `live`, `expired`, or `removed` — plus the full job record (title, company, parsed salary, location, posting date) while it's still alive. Run it nightly in monitor mode and it flags only the jobs that JUST died, with Slack / email / webhook alerts, so your job board, ATS feed, or scraped database never serves a dead listing again.**

There is no dedicated Indeed status checker on Apify — the usual workaround is re-running a full Indeed *search* scraper and diffing the results yourself, which misses direct-key lookups entirely and costs a multiple per record. This actor does one job, cheaply:

| | **This actor** | General Indeed search scrapers |
|---|---|---|
| Check a SPECIFIC jobkey / job URL | ✅ direct lookup, 1 request per key | ❌ can only re-run searches and hope the job appears |
| Price per 1,000 checks | **$1** (`$0.001`/key) | typically several dollars per 1,000 *search results*, and you still have to diff |
| Explicit `expired` vs `removed` vs `live` verdict | ✅ three separated states, straight from Indeed's own flags | ❌ "absent from results" ≠ expired |
| Full job data on every key (salary min/max/currency, remote flag, dates, benefits, company rating) | ✅ | partial, varies |
| Newly-dead diff across runs (monitor mode) | ✅ named persistent state + `newlyDead` flag | ❌ DIY |
| Slack / email / webhook alerts on death | ✅ | ❌ |
| Failure handling | per-key retries with fresh proxy sessions, HTML + search-card fallbacks; a failed key is marked `unknown` (never falsely "dead") and **not billed** | a failed page usually just crashes or silently drops rows |

No login, no API key, no browser automation — the actor reads the same server-rendered JSON the Indeed page itself ships, one lightweight GET per job.

---

### What does Indeed Expired Job Checker do?

It answers one question at scale: **is this Indeed job still accepting candidates?**

- ✅ **Three clean states** — `live` (still posted), `expired` (Indeed shows "This job has expired"), `removed` (the key 404s — listing deleted). Plus `unknown` when every check path fails, so you never purge a live job by mistake.
- 📦 **Bulk input** — paste raw 16-hex jobkeys, `viewjob?jk=…` URLs, or `/job/<title>-<key>` URLs; mixed lists are fine, duplicates deduped, up to 5,000 keys per run.
- 🌱 **Harvest mode** — no keys handy? Give it a keyword + city and it mints 25 fresh jobkeys from Indeed search page 1 and checks them (also the built-in demo).
- 🧾 **The full job record on every checked key** — title, company (+ rating, review count, company page URL), formatted + geocoded location, remote flag, **parsed salary min/max/currency/type** plus the display text, posting date, date-on-Indeed, expiration date when present, job types, shift & schedule, benefits, skill attributes, advertiser/source employer name, recruiter phone when shown, urgent-hire and high-volume-hiring flags, apply-starts count, repost flag, full description (text + HTML), and a pruned `raw` object with everything else Indeed returns.
- 🔄 **Monitor mode** — persistent per-key state in a named key-value store; each run flags `newlyDead: true` only for jobs that flipped from live to expired/removed since the last run.
- 🔔 **Alerts** — Slack cards, email digests, or raw webhooks the moment a monitored listing dies.
- 🛡️ **Cloudflare-aware** — Indeed spot-checks traffic; every request retries with a fresh proxy session, then falls back from JSON → HTML page → search-card data before ever giving up.

### Who is it for?

- 🗂️ **Job-board operators** purging dead Indeed-sourced listings nightly (the #1 user complaint on any job board is applying to a dead job).
- 🔁 **ATS / job-feed vendors** keeping syndicated feeds clean for clients.
- 📊 **Labor-market & recruiting analysts** measuring real time-to-fill — the expiry date IS the signal.
- 🤖 **Scraped-database owners** re-validating Indeed records before resale or display.
- 🎯 **Sales teams** timing outreach to companies whose postings just closed (they hired — or gave up).

### How to use it (step by step)

1. Click **Try for free**.
2. Paste your **Job keys or URLs** (one per line) — or leave it empty and set a **Harvest keyword** + **location** to demo on 25 fresh keys.
3. *(Optional)* set **Max keys per run** to bound cost.
4. Click **Start**, open the **Dataset** tab, filter `status != "live"` — that's your purge list.
5. *(Recurring)* turn on **monitorMode**, attach an Apify **Schedule** (e.g. nightly), add a Slack/webhook/email channel — you'll only hear about jobs that *just* died.

#### Quick start (bulk check)

```json
{
  "jobKeys": [
    "ddb19acf24fc4188",
    "https://www.indeed.com/viewjob?jk=cfc9d259e17574cb",
    "https://www.indeed.com/job/warehouse-associate-0a27464dd26940cf"
  ]
}
````

#### Nightly purge monitor

```json
{
  "jobKeys": ["…your feed's jobkeys…"],
  "monitorMode": true,
  "alertOnDead": true,
  "slackWebhookUrl": "https://hooks.slack.com/services/…"
}
```

#### Demo / harvest mode

```json
{ "keyword": "warehouse", "location": "Dallas, TX", "maxKeys": 10 }
```

### Input

| Field | What it does |
|-------|--------------|
| `jobKeys` | jobkeys and/or Indeed job URLs to check (deduped; max 5,000/run) |
| `keyword` + `location` | harvest mode when `jobKeys` is empty — check 25 fresh keys from search page 1 |
| `maxKeys` | hard cap per run (0 = all provided keys) |
| `monitorMode` | persist per-key status across runs; flag `newlyDead` transitions |
| `alertOnDead` | in monitor mode, alert on each newly expired/removed job |
| `webhookUrl` / `slackWebhookUrl` / `emailRecipients` | alert channels |
| `proxyConfiguration` | default Apify proxy; switch to RESIDENTIAL for large batches |
| `requestConcurrency` | parallel checks, 1–5 (default 2) |

### Output

One record per checked key. The essentials:

```json
{
  "jobKey": "0a27464dd26940cf",
  "status": "live",
  "url": "https://www.indeed.com/viewjob?jk=0a27464dd26940cf",
  "checkedAt": "2026-06-12T21:04:11.000Z",
  "checkSource": "spa",
  "title": "Warehouse Associate",
  "company": "Recycle 2 Support",
  "companyUrl": "https://www.indeed.com/cmp/Recycle-2-Support-4",
  "companyRating": 4,
  "companyReviewCount": 2,
  "location": "Flower Mound, TX 75028",
  "city": "Flower Mound",
  "state": "TX",
  "postalCode": "75028",
  "latitude": 33.033405,
  "longitude": -97.06766,
  "remote": false,
  "salaryMin": 15.5,
  "salaryMax": 15.5,
  "salaryCurrency": "USD",
  "salaryType": "HOURLY",
  "salaryText": "$15.50 an hour",
  "datePublished": "2026-05-03T05:23:18.413Z",
  "jobTypes": ["Full-time"],
  "benefits": ["Health insurance", "Dental insurance"],
  "sourceEmployerName": "Recycle 2 Support",
  "isRepost": true,
  "descriptionText": "…full text…",
  "raw": { "…everything else Indeed returned…": "…" }
}
```

Dead keys come back as `"status": "expired"` (Indeed's own expired flag, usually still with title/company) or `"status": "removed"` (HTTP 404 — listing deleted). In monitor mode each record also carries `previousStatus` and `newlyDead`.

Export to **JSON, CSV, Excel, or HTML**, or pull via the **Apify API** straight into your purge pipeline.

### How much does it cost?

Pay-per-event — you pay per check, no subscription:

| Event | What it covers | Price |
|-------|----------------|-------|
| `lot-scraped` | each jobkey checked (live, expired, or removed — `unknown` is FREE) | **$0.001** / key |
| `new-lot-detected` | each NEWLY-expired/removed job found in monitor mode | **$0.005** / job |
| `monitor-run-completed` | each scheduled monitor run | ~$0.01 / run |
| `alert-delivered` | each Slack/email/webhook push | ~$0.002 / alert |

*(Final per-event prices are set on the actor's pricing page.)*

**$1 per 1,000 keys checked.** A 10,000-listing feed verified nightly costs about $10/month plus a half-cent for each dead listing it catches.

### Is it legal? (read this)

The actor reads **publicly available listing data** — the same pages anyone can open without an account. The records are job/employer data, not personal data (the only person-adjacent field is a recruiter phone number when Indeed itself displays one publicly). **Note:** Indeed's Terms of Service restrict automated access; this is a ToS-gray area like all Indeed scraping. Use it on listings you have a legitimate operational need to verify (e.g. your own syndicated feed), respect rate limits, and consult your counsel for commercial use. You are responsible for your use of the data.

### FAQ

**What is an Indeed jobkey?**
The 16-character hex id in every Indeed job URL (`viewjob?jk=ddb19acf24fc4188`). It's the stable identifier for a listing — paste either the key or any URL containing it.

**What's the difference between `expired` and `removed`?**
`expired` = the page still exists and Indeed marks it "This job has expired" (title/company usually still returned). `removed` = the key returns 404 — the listing was deleted outright. Both are dead for purge purposes.

**Can it tell me WHEN a job expired?**
It returns Indeed's `expirationDate` when the page exposes one, plus the posting date and the check timestamp. For exact death timing, run monitor mode on a schedule — the `newlyDead` flag brackets death to the run interval.

**Do I need an Indeed account, login, or API key?**
No. Every check is a plain GET to a public page.

**Does a `live` result include the job details?**
Yes — full title, company, parsed salary (min/max/currency/type), location with coordinates, remote flag, job types, benefits, description, and more, with the rest preserved under `raw`.

**How does monitor mode work?**
State lives in a named key-value store (`indeed-job-status-monitor-state`), scoped per input list or search. Each run compares current status to the last known status; only live→dead transitions (and first sightings of already-dead keys) are flagged `newlyDead` and alerted. All checked keys are still output with their current status.

**What happens when Indeed blocks a request?**
Indeed's Cloudflare layer occasionally spot-checks. The actor retries up to 5× with a fresh proxy session, then falls back to the HTML page, then to same-run search-card data. If everything fails, the key is marked `unknown` — never falsely "dead" — and you are **not charged** for it.

**Can it check thousands of keys?**
Yes — up to 5,000 per run (batch larger feeds across runs). At the default concurrency a 1,000-key batch takes roughly 15–20 minutes. For large batches, switch the proxy to RESIDENTIAL.

**Can it find jobkeys for me?**
Harvest mode pulls the 25 fresh keys from page 1 of any keyword+location search. It deliberately does not paginate deeper (Indeed login-walls page 2) — split by city/keyword for volume.

**Why did some keys come back `unknown`?**
All three check paths failed (usually sustained Cloudflare challenges on datacenter IPs). Re-run those keys with residential proxies. Unknowns are free.

**Does it work outside the US?**
This version targets indeed.com (US). International Indeed domains (indeed.co.uk, ca.indeed.com, …) use the same key format — open an issue if you want them supported.

**How do I plug it into my pipeline?**
Webhook alerts for push, or pull the dataset via the Apify API (`status`, `newlyDead` fields are made for `WHERE` clauses). Make/Zapier/n8n all work.

### You might also like

- 📈 Job-posting intent & hiring-signal monitors
- 🏢 Company review and employer-data scrapers
- 🧹 Other dead-link and listing-status checkers

### Feedback

Found an edge case or want international Indeed domains? Open an issue on the actor — fast fixes and feature requests welcome.

# Actor input Schema

## `jobKeys` (type: `array`):

The Indeed jobs to check — paste raw 16-hex jobkeys (e.g. 'ddb19acf24fc4188'), viewjob URLs (…/viewjob?jk=…), or /job/<title>-<key> URLs, one per line. Duplicates are deduped. Leave EMPTY to use harvest mode (keyword + location below) instead.

## `keyword` (type: `string`):

Harvest mode (used only when 'Job keys or URLs' is empty): search this keyword on indeed.com and check the 25 fresh jobkeys from page 1. Great for a quick demo or for minting test keys.

## `location` (type: `string`):

Harvest mode: the 'where' box of the Indeed search, e.g. 'Dallas, TX' or 'Remote'. Leave empty for nationwide results.

## `maxKeys` (type: `integer`):

Hard cap on jobkeys checked this run (cost/safety guard). 0 = all provided keys (up to 5,000/run). Harvest mode yields at most 25 keys (Indeed login-walls page 2+).

## `monitorMode` (type: `boolean`):

Recurring watcher: remembers each key's last status (in a named key-value store) and flags jobs that are NEWLY expired/removed since the last run ('newlyDead': true) — the nightly purge feed. Pair with an Apify Schedule. All checked keys are still output with their current status.

## `alertOnDead` (type: `boolean`):

In monitor mode, deliver an alert for each NEWLY expired/removed job via the channels below.

## `webhookUrl` (type: `string`):

POST endpoint for newly-dead alert payloads (Make / Zapier / n8n / your ATS sync). One JSON body per dead listing.

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL for formatted dead-listing cards.

## `emailRecipients` (type: `array`):

Email addresses for the newly-dead digest (sent via apify/send-mail).

## `proxyConfiguration` (type: `object`):

Proxy settings. Indeed's Cloudflare layer blocks datacenter IPs, so this defaults to RESIDENTIAL — keep it on residential for reliable results. The actor also retries each fetch with a fresh session automatically.

## `requestConcurrency` (type: `integer`):

Parallel status checks (1–5). Keep modest — higher concurrency raises the chance of Cloudflare spot-checks.

## `diagnose` (type: `boolean`):

Dev only. Dumps the raw harvest cards + the first spa JSON response to the key-value store (DEBUG\_HARVEST\_CARDS / DEBUG\_SPA\_JSON) for parser verification. Leave off for normal runs.

## Actor input object example

```json
{
  "keyword": "warehouse",
  "location": "Dallas, TX",
  "maxKeys": 10,
  "monitorMode": false,
  "alertOnDead": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "requestConcurrency": 2,
  "diagnose": false
}
```

# Actor output Schema

## `items` (type: `string`):

The dataset of checked Indeed jobkeys (one record per key: live | expired | removed | unknown).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keyword": "warehouse",
    "location": "Dallas, TX",
    "maxKeys": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/indeed-job-status-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keyword": "warehouse",
    "location": "Dallas, TX",
    "maxKeys": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/indeed-job-status-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keyword": "warehouse",
  "location": "Dallas, TX",
  "maxKeys": 10
}' |
apify call scrapersdelight/indeed-job-status-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=scrapersdelight/indeed-job-status-checker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Indeed Expired Job Checker — Dead Listing Monitor",
        "description": "Check Indeed job listings for $1 per 1,000 keys — live, expired, or removed. Bulk-verify jobkeys/URLs, harvest fresh keys by keyword + city, or schedule a nightly dead-listing monitor with Slack/email/webhook alerts. Full job data (salary, company, dates) on every key. No login or API key.",
        "version": "0.1",
        "x-build-id": "L9kaoMpWVf3S0VmYo"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scrapersdelight~indeed-job-status-checker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scrapersdelight-indeed-job-status-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/scrapersdelight~indeed-job-status-checker/runs": {
            "post": {
                "operationId": "runs-sync-scrapersdelight-indeed-job-status-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/scrapersdelight~indeed-job-status-checker/run-sync": {
            "post": {
                "operationId": "run-sync-scrapersdelight-indeed-job-status-checker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "jobKeys": {
                        "title": "Job keys or URLs",
                        "type": "array",
                        "description": "The Indeed jobs to check — paste raw 16-hex jobkeys (e.g. 'ddb19acf24fc4188'), viewjob URLs (…/viewjob?jk=…), or /job/<title>-<key> URLs, one per line. Duplicates are deduped. Leave EMPTY to use harvest mode (keyword + location below) instead.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "keyword": {
                        "title": "Harvest keyword",
                        "type": "string",
                        "description": "Harvest mode (used only when 'Job keys or URLs' is empty): search this keyword on indeed.com and check the 25 fresh jobkeys from page 1. Great for a quick demo or for minting test keys."
                    },
                    "location": {
                        "title": "Harvest location",
                        "type": "string",
                        "description": "Harvest mode: the 'where' box of the Indeed search, e.g. 'Dallas, TX' or 'Remote'. Leave empty for nationwide results."
                    },
                    "maxKeys": {
                        "title": "Max keys per run",
                        "minimum": 0,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Hard cap on jobkeys checked this run (cost/safety guard). 0 = all provided keys (up to 5,000/run). Harvest mode yields at most 25 keys (Indeed login-walls page 2+).",
                        "default": 100
                    },
                    "monitorMode": {
                        "title": "Monitor mode (dead-listing watcher)",
                        "type": "boolean",
                        "description": "Recurring watcher: remembers each key's last status (in a named key-value store) and flags jobs that are NEWLY expired/removed since the last run ('newlyDead': true) — the nightly purge feed. Pair with an Apify Schedule. All checked keys are still output with their current status.",
                        "default": false
                    },
                    "alertOnDead": {
                        "title": "Alert on newly-dead listings",
                        "type": "boolean",
                        "description": "In monitor mode, deliver an alert for each NEWLY expired/removed job via the channels below.",
                        "default": true
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "POST endpoint for newly-dead alert payloads (Make / Zapier / n8n / your ATS sync). One JSON body per dead listing."
                    },
                    "slackWebhookUrl": {
                        "title": "Slack webhook URL",
                        "type": "string",
                        "description": "Slack incoming-webhook URL for formatted dead-listing cards."
                    },
                    "emailRecipients": {
                        "title": "Email recipients",
                        "type": "array",
                        "description": "Email addresses for the newly-dead digest (sent via apify/send-mail).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Proxy settings. Indeed's Cloudflare layer blocks datacenter IPs, so this defaults to RESIDENTIAL — keep it on residential for reliable results. The actor also retries each fetch with a fresh session automatically.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    },
                    "requestConcurrency": {
                        "title": "Request concurrency",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Parallel status checks (1–5). Keep modest — higher concurrency raises the chance of Cloudflare spot-checks.",
                        "default": 2
                    },
                    "diagnose": {
                        "title": "Diagnostic mode (dev)",
                        "type": "boolean",
                        "description": "Dev only. Dumps the raw harvest cards + the first spa JSON response to the key-value store (DEBUG_HARVEST_CARDS / DEBUG_SPA_JSON) for parser verification. Leave off for normal runs.",
                        "default": false
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
