# Remote jobs feed - 2,000+ company career sites, no board tokens (`retrainmapdata/remote-jobs-feed`) Actor

Remote job postings from 2,099 verified company career sites on Greenhouse, Lever, Ashby and Workable. No board tokens to look up: the index ships inside the Actor. Filter by keyword, location, company and recency; each row says whether remote came from the ATS flag or the location text.

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

## Pricing

from $5.00 / 1,000 records

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Remote jobs feed — 2,000+ company career sites, no board tokens

Remote-flagged job postings read straight from companies' own applicant-tracking systems —
**Greenhouse, Lever, Ashby and Workable** — across a bundled index of **2,099 verified
company boards**. You do not look up a single board token: run it empty and it walks the
index, biggest board first, until it has as many remote jobs as you asked for.

These are the employers' own public, keyless job endpoints, so the rows are the postings as
the company published them — title, department, location, employment type, posted date,
apply link, description, and salary wherever the ATS carries one.

### What makes this different from a job aggregator

| | This Actor | A job-board scraper |
|---|---|---|
| Source | The employer's own ATS API | A third-party listings site |
| Freshness | Whatever the company published, at run time | Whatever the aggregator last crawled |
| Apply link | The company's real application page | Often a redirect or a re-post |
| Terms | Public, keyless, documented endpoints | Usually against the site's terms |

### Input

Everything is optional.

| Field | Meaning |
|---|---|
| `keyword` | Substring in title / department / team / description (`engineer`, `nurse`) |
| `location` | Substring in the posting's location(s) or country — remote roles are usually still region-limited |
| `max_records` | Stop after this many remote rows (default 200) |
| `max_boards` | How far down the index to walk (default 150, max 2,100) |
| `ats` | Limit to some of Greenhouse / Lever / Ashby / Workable |
| `company_contains` | Restrict the walk to matching company names or board slugs |
| `require_ats_flag` | Keep only rows the ATS itself flagged remote (see below) |
| `posted_within_days` | Only postings published in the last N days |

Empty input → the 150 biggest boards, up to 200 remote postings.

### The remote flag, honestly

Lever, Ashby and Workable each publish a remote/workplace flag. **Greenhouse does not.** So
for Greenhouse boards the flag is read from a "Workplace Type" metadata field when the
company filled one in, and otherwise inferred from the word "remote" in the location text.

Every row carries `remote_source`:

- `ats_flag` — the ATS declared it (Lever `workplaceType`, Ashby `isRemote`, Workable `telecommuting`)
- `location_text` — inferred from the location string
- `none` — no signal at all (these rows are never returned; only `remote = true` rows are)

Set **`require_ats_flag`** to drop everything that was inferred. The run summary reports how
many returned rows were inference-based.

### Output

One row per posting:

`ats · board · company · job_id · title · department · team · location · all_locations ·
country · remote · remote_source · workplace_type · employment_type · posted_at ·
updated_at · url · apply_url · description · salary_min · salary_max · salary_currency ·
salary_interval · salary_note · source_url · fetched_at · board_verified_at`

`RUN_SUMMARY` in the key-value store records the board index used, how many boards were read,
how many failed and why, request and byte counts, and the filters applied.

### The board index

`data/boards.csv`, shipped inside the image: company, ATS, board slug, job count at
verification, and the timestamp it was verified. Every board in it answered with at least one
live posting when it was checked — it is the RetrainMap ATS index behind
[retrainmap.com/data](https://retrainmap.com/data/), not a guessed list of slugs. Companies
do leave an ATS; a board that has gone 404 is listed in `RUN_SUMMARY.boards` with its error
rather than dropped in silence.

### When a run fails

If an ATS answers in a shape it does not document, the run **stops** with a `SourceError`
naming the endpoint. It never emits guessed rows. A single unreadable board is recorded and
the run continues; only every-board-failed is fatal.

### Politeness and identification

One request per board, at most one request per `request_interval_ms` (250 ms floor), two
retries with back-off on 429/5xx. Every request identifies the operator by product-token
`User-Agent` and carries a contact address in the standard `From:` header (RFC 9110 §10.1.2).

### Pricing

Pay per event: **$0.10** per run start + **$0.005** per job row.

***

Related: **ATS jobs** (the same normaliser for boards you name), **Company hiring signals**
(which companies opened or closed the most postings since your last run), and the full
109,000-posting weekly dataset at [retrainmap.com/data](https://retrainmap.com/data/).

By Steelyard Ventures LLC (brand: RetrainMap) · info@steelyardclinical.com

# Actor input Schema

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

Case-insensitive substring matched against title, department, team and description (e.g. 'engineer', 'nurse', 'customer success'). Empty = every remote job.

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

Case-insensitive substring matched against the posting's location(s) and country (e.g. 'united states', 'emea', 'canada'). Remote jobs are usually still region-limited, so this is the field that says where you may sit.

## `max_records` (type: `integer`):

Stop after this many remote job rows. The run walks boards until it reaches this number, so a small budget finishes fast.

## `max_boards` (type: `integer`):

How far down the index to walk (boards are ordered biggest-first). Raise it to widen the search when a narrow keyword returns too few rows; one request per board.

## `ats` (type: `array`):

Empty = all four. The index holds 983 Greenhouse, 655 Ashby, 317 Lever and 144 Workable boards.

## `company_contains` (type: `string`):

Restrict the walk to boards whose company name or board slug contains this text. Empty = the whole index.

## `require_ats_flag` (type: `boolean`):

Lever, Ashby and Workable publish a remote flag; Greenhouse does not, so those rows are read from a 'Workplace Type' field or inferred from the word 'remote' in the location. Turn this on to keep only the rows the ATS itself flagged (`remote_source` = ats\_flag).

## `posted_within_days` (type: `integer`):

Keep only postings published in the last N days. Postings the ATS published without a usable date are kept, not silently dropped.

## `request_interval_ms` (type: `integer`):

Politeness delay towards the ATS hosts. One request per board; the floor is 250 ms.

## `contact_email` (type: `string`):

Sent in the standard From: request header so the data owner can reach the operator (RFC 9110 s10.1.2).

## Actor input object example

```json
{
  "keyword": "engineer",
  "max_records": 100,
  "max_boards": 40,
  "require_ats_flag": false,
  "request_interval_ms": 400,
  "contact_email": "info@steelyardclinical.com"
}
```

# Actor output Schema

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

One row per remote-flagged job posting.

## `results_csv` (type: `string`):

The same rows as a CSV file.

# 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": "engineer",
    "max_records": 100,
    "max_boards": 40
};

// Run the Actor and wait for it to finish
const run = await client.actor("retrainmapdata/remote-jobs-feed").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": "engineer",
    "max_records": 100,
    "max_boards": 40,
}

# Run the Actor and wait for it to finish
run = client.actor("retrainmapdata/remote-jobs-feed").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 '{
  "keyword": "engineer",
  "max_records": 100,
  "max_boards": 40
}' |
apify call retrainmapdata/remote-jobs-feed --silent --output-dataset

```

## MCP server setup

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

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/RId7svMaUEC6OePZv/builds/aIr1TZyIAOMwbUpLF/openapi.json
