# Careers Job Feed: Greenhouse, Lever, Ashby & More (`suresignal/company-careers-job-feed`) Actor

Only pay for new jobs. Watch company careers pages on Greenhouse, Lever, Ashby, Workable, SmartRecruiters & Recruitee: new postings each run, free removed-job alerts, salary, remote, seniority, domain.

- **URL**: https://apify.com/suresignal/company-careers-job-feed.md
- **Developed by:** [SureSignal](https://apify.com/suresignal) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $18.00 / 1,000 jobs

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

## Company Careers Job Feed — Greenhouse, Lever, Ashby & More

### Only pay for new jobs.

**Don't pay for the same job postings over and over.** Watch the careers pages of the companies you care about. Each run delivers only the jobs that are new since your last run, plus a **free** notice for every job that disappears.

Most job feeds give you every open role again on every pull. You pay again for postings you already have, then spend time diffing and deduplicating them. This Actor remembers what it has delivered for each watchlist. In our tests, a repeat run over the same companies skipped 100% of jobs already delivered and charged $0 for them. Duplicates are collapsed before you see them. You spend less, your feed has less clutter, and you have one less thing to manage.

**A decision is only as good as the information behind it.** Knowing which target account just opened four data-engineering roles, or which competitor quietly closed its sales hiring, can be worth a quarter's pipeline. At $0.018 a job, the data costs pennies by comparison.

#### What it does

Reads the official public job-board APIs of Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee: no proxies, no logins, no fragile page scraping. Each job comes with salary range, normalized location, remote/hybrid/onsite, seniority, department and the company's website domain.

***

### Who it's for

- **Sales and GTM teams** using job postings as **hiring signals** — "they just opened 4 data-engineering roles" is the best reason to reach out this week. Works with Clay, HubSpot, Salesforce, Make, Zapier and n8n.
- **Recruiters and talent teams** tracking competitors' and target companies' openings the moment they go live.
- **Job boards and niche job sites** that need a reliable **job listing API** for a curated set of employers, with removed-job notices so expired listings come down automatically.
- **Investors and analysts** watching headcount plans at portfolio and peer companies.
- **AI agents and developers** who want a **job postings API** for specific companies without maintaining six ATS integrations.

### Why this instead of a big job database?

Large job databases are great for "every job on the internet". This Actor is built for "**these 200 companies, and tell me the moment something changes**":

| | This Actor | Typical job database Actor |
|---|---|---|
| Source | Live from each company's ATS at run time | Pre-indexed copy, often hours old |
| You choose the companies | Yes — URL, `ats:slug`, domain or name | Filter a shared index |
| New since last run | Built in, per watchlist (`monitorId`) | Time-window only |
| Removed / closed jobs | Same run, **free** | Separate Actor or extra cost |
| Salary | ATS pay fields first, then parsed from the description, with `salarySource` | Varies |
| Duplicate postings | Collapsed (same title + location) | Often passed through |
| Resume after a limit | `NEXT_CURSOR` | Usually start over |

If you need millions of jobs from thousands of ATSs you don't know in advance, a database product is the better fit. If you know which companies matter, this is faster, fresher and cheaper per useful row.

### Supported job boards

| ATS | Example input | Salary from ATS field |
|---|---|---|
| Greenhouse | `https://boards.greenhouse.io/stripe` or `greenhouse:stripe` | From description |
| Lever | `https://jobs.lever.co/palantir` or `lever:palantir` | Yes (`salaryRange`) |
| Ashby | `https://jobs.ashbyhq.com/ramp` or `ashby:ramp` | Yes (compensation) |
| Workable | `https://apply.workable.com/huggingface` | From description |
| SmartRecruiters | `https://jobs.smartrecruiters.com/BoschGroup` | — |
| Recruitee | `https://bunq.recruitee.com` | Yes when published |

**Don't know which ATS a company uses?** Enter `ramp.com` or just `notion`. The Actor tries each supported board and uses the one that answers. Companies it can't find are listed in the `NOT_FOUND_COMPANIES` record of the run's key-value store, and they are never charged.

### What you get for each job

```json
{
  "id": "ashby:ramp:e5232cce-a23a-4f03-b12e-dac510d08cd3",
  "status": "new",
  "ats": "ashby",
  "companyName": "Ramp",
  "companyDomain": "ramp.com",
  "title": "Senior Security Engineer, Endpoint",
  "department": "Security / IT Eng",
  "seniority": "senior",
  "employmentType": "FullTime",
  "location": "New York, NY (HQ)",
  "city": "New York City", "region": "NY", "country": "US",
  "isRemote": false,
  "workplaceType": "hybrid",
  "salaryMin": 172000, "salaryMax": 236000,
  "salaryCurrency": "USD", "salaryPeriod": "year",
  "salarySource": "ats",
  "postedAt": "2026-07-08T14:39:41Z",
  "url": "https://jobs.ashbyhq.com/ramp/e5232cce-a23a-4f03-b12e-dac510d08cd3",
  "applyUrl": "https://jobs.ashbyhq.com/ramp/e5232cce-a23a-4f03-b12e-dac510d08cd3/application",
  "descriptionText": "About Ramp\nRamp is building the smart infrastructure for finance teams…"
}
```

*(A real record from a test run in October 2026, trimmed.)*

When a job is taken down you get a **free** record like `{"status": "removed", "title": "...", "url": "...", "firstSeenAt": "...", "removedAt": "..."}` so you know it was filled or closed and how long it was open.

**Fields:** `id`, `status` (new / active / removed), `ats`, `companySlug`, `companyName`, `companyDomain`, `companyDomainSource`, `title`, `department`, `seniority`, `employmentType`, `location`, `allLocations`, `city`, `region`, `country` (ISO-2), `isRemote`, `workplaceType` (remote / hybrid / onsite), `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` (year / month / hour), `salarySource` (ats / description), `postedAt`, `updatedAt`, `firstSeenAt`, `removedAt`, `url`, `applyUrl`, `requisitionId`, `descriptionText` (optional), `descriptionHtml` (optional).

### How to use it

1. Paste your companies, one per line — careers URLs, `ats:slug`, domains or names.
2. Optional filters: title keywords, excluded keywords, departments, seniority, locations, countries, remote only, workplace type, salary present, minimum annual salary, posted within N days.
3. Run. The first run returns all matching open jobs. Every run after that returns only **new** jobs plus free **removed** notices.
4. Save it as a **task** and add a **schedule** (daily or hourly). Use a different `monitorId` for each watchlist so their histories stay separate.
5. Send results anywhere with Apify integrations: webhooks, Zapier, Make, n8n, Google Sheets, Slack, or the API (`/runs/last/dataset/items`).

#### Recipes

- **Hiring-signal alerts for sales:** your target-account domains + `titleKeywords: ["data engineer", "revops", "security"]` + daily schedule → Slack or your CRM.
- **Remote engineering job board:** 300 startup boards + `remoteOnly: true` + `seniority: ["senior","staff"]` + `onlyWithSalary: true`, with removed notices to expire listings.
- **Competitor headcount watch:** 10 competitors, `onlyNew: false` once a week → count open roles by department over time.

### Pricing

Pay per result: **$0.018 per job delivered** ($18 per 1,000), plus Apify's tiny per-run start fee. You pay only for jobs that pass your filters.

**Always free:** removed-job notices, duplicates we collapse, jobs you filter out, companies that aren't found, and input-error messages.

| Use case | Jobs per month | Approx. cost |
|---|---|---|
| 50 target accounts, daily, new jobs only | ~600 | ~$11 |
| 300-company niche job board, daily | ~4,000 | ~$72 |
| One full snapshot of 20 companies | ~1,500 | ~$27 |

Volumes are illustrative; your cost depends on how often your companies post. Set **Max jobs per run** to cap spend — the run stops cleanly and saves a cursor.

### Reliability

- Uses each ATS's **public job-board API** — the same endpoints that power companies' own careers pages — not fragile page scraping.
- Retries with backoff on rate limits and server errors; one failing company never kills the run.
- If a run stops at your limit, the key-value store holds `NEXT_CURSOR`. Paste it into **Resume cursor** and it continues from that company. With "Only new" on (the default), jobs already delivered are not charged twice.
- A company's history is only updated after its jobs are delivered, so an interrupted run never makes you miss a new job.

### What this Actor doesn't do

- **No LinkedIn, Indeed or Glassdoor.** Only first-party company job boards.
- **Workday, iCIMS, Taleo, SuccessFactors and other enterprise ATSs aren't supported yet.**
- **No company discovery.** You bring the list of companies; it doesn't search for every company using Greenhouse.
- **No currency conversion.** Salaries are in the currency the employer posted. `minSalary` compares numbers as-is.
- **Seniority is derived from the job title** (and SmartRecruiters' level field). It is a strong hint, not a guarantee.
- **Greenhouse and Workable rarely expose salary as a field**, so salary there depends on whether the employer wrote it in the description.

### FAQ

**Does Greenhouse have an API for job postings?**
Yes. Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Recruitee all publish public job-board endpoints so companies can show jobs on their own sites. This Actor reads those endpoints and gives you one consistent schema across all six.

**Do I need an API key for Greenhouse, Lever or Ashby?**
No. Public job boards don't require keys. You only need an Apify account.

**How do I find a company's board slug?**
You usually don't need to. Enter the domain or name. If auto-detect misses, open the company's careers page, click a job, and copy the URL — `boards.greenhouse.io/<slug>`, `jobs.lever.co/<slug>`, `jobs.ashbyhq.com/<slug>`.

**How does "new since last run" work?**
For each `monitorId` the Actor remembers which job IDs it has seen per company. Jobs not seen before are `new`. Jobs seen before but now missing come back as `removed`. Turn on **Reset monitor** to start over.

**Is scraping careers pages legal?**
This Actor only reads job listings that employers publish publicly for anyone to see, through the endpoints their careers pages use. It collects no candidate data and doesn't log in anywhere. You're responsible for how you use the data; check the terms of the sites you rely on and the laws that apply to you.

**Can I use this as a free job posting API?**
Runs are pay-per-result, but new Apify accounts get monthly free platform credit, which covers small watchlists.

**Can AI agents call it?**
Yes, through the Apify API or Apify's MCP server. The input takes plain company names, so an agent can ask "what is Ramp hiring for?" without knowing which ATS Ramp uses.

### Support

Found a company that doesn't resolve, or need another ATS? Open an issue on the Issues tab with the careers-page URL. We aim to fix broken boards quickly.

### More from SureSignal

Other SureSignal data feeds that pair well with this one:

- [Recently Funded Startups: SEC Form D Leads](https://apify.com/SureSignal/sec-form-d-funding-leads): find companies that just raised money.
- [Google Ads Transparency Monitor](https://apify.com/SureSignal/google-ads-transparency-library): track competitors' new Google ads.
- [AI Search Visibility Tracker](https://apify.com/SureSignal/ai-search-visibility-tracker): check if ChatGPT and Perplexity mention your brand.
- [YouTube Transcript Scraper & Channel Monitor](https://apify.com/SureSignal/youtube-transcript-scraper): get transcripts of new videos from channels you follow.

Need a source or field we don't cover? Open an issue on the **Issues** tab and describe what you need.

# Actor input Schema

## `companies` (type: `array`):

One per line. Paste a careers-page URL (boards.greenhouse.io/stripe, jobs.lever.co/palantir, jobs.ashbyhq.com/ramp, apply.workable.com/huggingface, jobs.smartrecruiters.com/Visa, bunq.recruitee.com), an 'ats:slug' pair (greenhouse:stripe), or just a domain or name (ramp.com) and the Actor finds the board for you.

## `onlyNew` (type: `boolean`):

Deliver only jobs that weren't on the board last time this monitor ran. First run for a company returns all its open jobs. Turn off to get every open job each run.

## `includeRemoved` (type: `boolean`):

Add a free 'status: removed' record for every job that disappeared since the last run — a filled or closed role.

## `monitorId` (type: `string`):

Keeps separate 'seen' history per watchlist. Use a different ID for each saved task.

## `resetMonitor` (type: `boolean`):

Forget history for this monitor ID and start fresh.

## `titleKeywords` (type: `array`):

E.g. engineer, sales, data. Case-insensitive.

## `excludeTitleKeywords` (type: `array`):

Drop jobs whose title contains any of these.

## `departments` (type: `array`):

E.g. Engineering, Sales, Marketing.

## `seniority` (type: `array`):

Keep only these levels (derived from the job title).

## `locations` (type: `array`):

Free-text match on location, e.g. New York, London, Berlin.

## `countries` (type: `array`):

E.g. US, GB, DE. Remote jobs with no stated country are kept unless you switch that off below.

## `includeRemoteAnyCountry` (type: `boolean`):

When filtering by country, also keep remote jobs that don't state a country.

## `remoteOnly` (type: `boolean`):

Keep only remote jobs.

## `workplaceTypes` (type: `array`):

Keep only these workplace types.

## `onlyWithSalary` (type: `boolean`):

Keep only jobs where a pay range was found.

## `minSalary` (type: `integer`):

Drop yearly-paid jobs whose top of range is below this (any currency, no conversion).

## `postedWithinDays` (type: `integer`):

Drop jobs first published more than this many days ago.

## `dedupe` (type: `boolean`):

Collapse the same title + location posted twice by one company.

## `findCompanyDomain` (type: `boolean`):

Add companyDomain from job descriptions or a verified homepage match.

## `includeDescription` (type: `boolean`):

Clean plain-text job description.

## `includeDescriptionHtml` (type: `boolean`):

Original HTML description.

## `maxDescriptionChars` (type: `integer`):

Truncate description text to this many characters.

## `maxItems` (type: `integer`):

Stop after this many charged jobs. A cursor is saved so you can continue.

## `cursor` (type: `string`):

Paste NEXT_CURSOR from a run that stopped at its limit to continue where it left off.

## `concurrency` (type: `integer`):

Companies fetched in parallel.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/stripe",
    "lever:palantir",
    "ramp.com",
    "notion"
  ],
  "onlyNew": true,
  "includeRemoved": true,
  "monitorId": "default",
  "resetMonitor": false,
  "includeRemoteAnyCountry": true,
  "remoteOnly": false,
  "onlyWithSalary": false,
  "dedupe": true,
  "findCompanyDomain": true,
  "includeDescription": true,
  "includeDescriptionHtml": false,
  "maxDescriptionChars": 20000,
  "maxItems": 1000,
  "concurrency": 6
}
```

# Actor output Schema

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

All records from this run (new-only by default).

## `runState` (type: `string`):

Key-value store with NEXT_CURSOR and other run records.

# 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 = {
    "companies": [
        "https://boards.greenhouse.io/stripe",
        "lever:palantir",
        "ramp.com",
        "notion"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("suresignal/company-careers-job-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 = { "companies": [
        "https://boards.greenhouse.io/stripe",
        "lever:palantir",
        "ramp.com",
        "notion",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("suresignal/company-careers-job-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 '{
  "companies": [
    "https://boards.greenhouse.io/stripe",
    "lever:palantir",
    "ramp.com",
    "notion"
  ]
}' |
apify call suresignal/company-careers-job-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,suresignal/company-careers-job-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/UPFlJAKfHXBWD3urX/builds/x7oEqoSiWRzNddZ6Q/openapi.json
