# Expired Jobs Feed - Detect Closed and Removed Job Listings (`hirebase/expired-jobs`) Actor

Get every job removed from company career pages since a date - job ids and slugs ready to delist from your database or job board. 80,000+ expirations a day across 4M+ jobs. Run it on a schedule next to the Hirebase job scrapers to keep your listings fresh.

- **URL**: https://apify.com/hirebase/expired-jobs.md
- **Developed by:** [Hirebase](https://apify.com/hirebase) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Expired Jobs Feed - Detect Closed and Removed Job Listings

Get every job that has been **taken down from a company career page** since a date - the job ids and slugs you need to delist it from your database, job board or CRM. 80,000+ expirations are detected every day across 4,000,000+ jobs scraped directly from career pages. Powered by [Hirebase](https://www.hirebase.org).

Adding new jobs is the easy half of running a job board. The hard half is knowing which ones have closed: stale listings frustrate candidates and quietly kill trust. This actor is that half.

**Why this actor?**

- 🧹 **Delist with confidence** - every record is a job Hirebase detected as gone from the employer's own career page.
- 🔑 **Same keys as the job scrapers** - `id`, `jobSlug` and `companySlug` match the fields every Hirebase job actor returns, so it's a straight join.
- 🏢 **Only the companies you track** - pass a list of company slugs and pay only for their expirations.
- 🔁 **Built for schedules** - *Only new since last run* skips anything an earlier run already returned, so overlapping windows are never billed twice.
- ⚡ **Handles full-day volume** - large windows are pulled as one bulk export instead of thousands of slow pages.

### How to use it

1. Set **Expired within (days)** - `1` covers yesterday and today - or an exact **Expired on or after** date.
2. Optionally list **Only these companies** to keep just the employers you care about.
3. Turn on **Only new since last run** and run it on an [Apify Schedule](https://docs.apify.com/platform/schedules) - daily is typical.
4. Delete every returned `id` from your store.

### Example input

```json
{
  "expiredWithinDays": 1,
  "companySlugs": ["stanley-black-decker-inc"],
  "onlyNewSinceLastRun": true,
  "maxResults": 100000
}
```

### Output

A real record:

```json
{
  "id": "6aa3702092ba799df784edd0",
  "jobSlug": "zuo-ye-yuan-operative-65f0bcbf",
  "companySlug": "stanley-black-decker-inc",
  "dateExpired": "2026-09-18"
}
```

`dateExpired` is the day Hirebase detected the job was gone - not necessarily the day the employer removed it. Export to JSON, CSV or Excel, or pipe into Make, n8n, Zapier, Google Sheets or the Apify API.

### Keeping a job board in sync

Run two actors on the same schedule:

1. Any Hirebase job scraper - [Job Search](https://apify.com/hirebase/job-search), [Fresh Jobs Feed](https://apify.com/hirebase/jobs-feed) or an ATS scraper - with **Only new since last run** on. Insert what it returns.
2. This actor with **Only new since last run** on. Delete what it returns.

### Pricing

Pay per result - you are only charged for expired jobs actually returned, up to **1,000,000 per run**. Jobs skipped by the company filter or already returned in an earlier run are never charged. Without a company filter a single day is 80,000+ records, so set **Max results** to cover a full day if you sync the whole feed.

### FAQ

**Do I need an API key?**
No - API access is built into the actor.

**What if a run hits Max results before the window is done?**
With *Only new since last run* on, the next run resumes from the same date and skips everything already returned, so nothing is lost - it just takes more runs. Raise **Max results** to finish in one.

**Can I filter by job board, category or location?**
Not directly - expiry records carry only the job and company identifiers. Filter by company here, or match the ids against your own store, which only holds the jobs you care about anyway.

**How far back can I go?**
Up to 90 days per run. Larger windows are fetched with a bulk export, so even a full week (~1M records) completes.

**Is this legal?**
The data comes from publicly posted job listings on company career pages, accessed via the Hirebase API.

# Actor input Schema

## `expiredWithinDays` (type: `integer`):

Return jobs that expired from today back this many days. <code>0</code> = today only, <code>1</code> = yesterday and today. Ignored when "Expired on or after" is set.

## `expiredOnOrAfter` (type: `string`):

Only jobs that expired on or after this date, as <code>YYYY-MM-DD</code>. Overrides "Expired within (days)".

## `companySlugs` (type: `array`):

Company slugs to keep, one per line (the <code>companySlug</code> field the job actors and Company Search return). Leave empty for every company. The whole feed is scanned and filtered, so you only pay for matches.

## `onlyNewSinceLastRun` (type: `boolean`):

Skip expired jobs this actor (or saved task) already returned in an earlier run with the same filters. The first run returns the whole window. Recommended for scheduled syncs, so an overlapping window is never billed twice.

## `maxResults` (type: `integer`):

Maximum number of expired jobs to save (up to 1,000,000 per run). A single day can hold 80,000+ expirations across all companies. You are only charged for results actually returned.

## Actor input object example

```json
{
  "expiredWithinDays": 1,
  "onlyNewSinceLastRun": false,
  "maxResults": 10000
}
```

# Actor output Schema

## `results` (type: `string`):

Every job that expired in the window, one dataset item per job.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("hirebase/expired-jobs").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("hirebase/expired-jobs").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{}' |
apify call hirebase/expired-jobs --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hirebase/expired-jobs"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/bMeuKSZrC0vTe6g9z/builds/2JZjsYLqlMrnQezxX/openapi.json
