# Stripe & Figma Jobs API (Greenhouse) + Departments (`jobatlas/normalized-greenhouse-jobs-scraper`) Actor

$0.2/1K jobs | Get jobs from the Stripe and Figma boards on Greenhouse with full descriptions, locations, departments and posting dates. Two tracked company boards, not every Greenhouse employer. No login or API key.

- **URL**: https://apify.com/jobatlas/normalized-greenhouse-jobs-scraper.md
- **Developed by:** [Job Atlas](https://apify.com/jobatlas) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.20 / 1,000 job 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

## Greenhouse Tracked Company Jobs Scraper (No Login)

$0.2/1K jobs | Get jobs from the Stripe and Figma boards on Greenhouse with full descriptions, locations, departments and posting dates. Two tracked company boards, not every Greenhouse employer. No login or API key. Independent, unofficial tool. Not affiliated with or endorsed by Greenhouse, Stripe or Figma.

### Search Stripe and Figma Greenhouse Jobs With Full Descriptions

Our scraper collects jobs from the two Greenhouse boards we track, Stripe and Figma, and lets you filter by keyword, posting age and your own rules on normalized fields. Every row carries the complete original description in text and HTML, the department, the location text and the apply link. It is ideal for job alerts on these two employers, hiring research and feeding your own job database.

**Coverage today:** two boards, Stripe and Figma. Jobs at other companies that use Greenhouse are not collected, and the earlier input that fetched any board you named is retired. Postings are only available once their full description has been verified, so a run can return fewer jobs than the live careers pages list.

- Need jobs from many employers instead of one tracked board? Our [LinkedIn Jobs Scraper](https://apify.com/jobatlas/linkedin-enrich-translate-normalize-scraper) searches LinkedIn by role and location. The trade-off: its postings come from LinkedIn, not from each employer's own Greenhouse board.
- Same output format for other applicant-tracking boards, each with its own tracked companies: [Ashby](https://apify.com/jobatlas/normalized-ashby-jobs-scraper) (Ashby's own board), [Lever](https://apify.com/jobatlas/normalized-lever-jobs-scraper) (Dun & Bradstreet), [SmartRecruiters](https://apify.com/jobatlas/normalized-smartrecruiters-jobs-scraper) (ServiceNow, Canva, Experian, Western Digital and Delivery Hero). Pick by employer.
- Browse all Job Atlas job scrapers: https://apify.com/jobatlas

#### Key Benefits

- No login or API key: nothing to set up and no account at risk. Your run reads stored postings and does not request the Greenhouse website.
- Low pricing: **$0.20 per 1,000 jobs**, with no start fee. Apify platform usage is included in that price.
- Complete descriptions only: a posting appears once its full description is verified, so every row carries the original text and HTML, not a snippet.
- No repeats across runs: schedule the same search and receive only postings you have not received yet.
- Optional AI enrichment and English translation: funded by us, off by default, no API key needed and no extra charge.

### How It Works

1. Provide your search. Every field is optional, and the prefilled form already returns real jobs.

   - (optional) Keyword (e.g., `engineer`, `customer success`). A case-insensitive phrase matched against the stored title, the employer and the complete description, so it also finds roles that only mention the word.
   - (optional) Posted within (e.g., `24h`, `7d`, `any`). Default is `any`. When Greenhouse gives no reliable original posting date, the reported date is the day the job was first stored; later refreshes do not make a posting look new.
   - (optional) Work arrangements (`remote`, `hybrid`, `onsite`). Empty means all. The Greenhouse postings we checked state no work arrangement (0 of 10 sample rows), and a remote-only filter returned no jobs in our check. Leave this filter empty here.
   - (optional) Advanced filters, a rule over normalized fields in the shared `nomad-agent-job-filter-v1` format. For example, jobs with a minimum pay of at least 50,000:

   ```json
   {
     "schemaVersion": "nomad-agent-job-filter-v1",
     "expression": {
       "field": "data.compensation.minimum",
       "operator": "gte",
       "value": 50000
     }
   }
   ```

   Place it under the `filters` field. Unknown values do not satisfy ordinary comparisons, so a rule only keeps jobs that state the field. Few Greenhouse postings carry pay (1 of 10 sample rows), so a pay filter removes most jobs on this board.
2. Set `maxItems` (default 100, at most 200; the prefilled form uses 10). Zero means 200. Filters, repeat suppression and failed enrichment can return fewer jobs.
3. Run the Actor. When it finishes, open the dataset for your jobs. The `RUN-SUMMARY` record in the key-value store shows data freshness, candidate and delivery counts, and the final status.

Run the same search again and you get only postings you have not received yet; set `dedupe.enabled` to `false` to see everything again. A non-empty `dedupe.key` deliberately shares delivery history across searches for the same Apify user, for example to keep one alert history per profile. If delivery cannot be confirmed, the run fails instead of claiming success.

If the stored data is unavailable or stale, the run fails instead of falling back to website scraping.

Greenhouse departments are the employer's own labels and can include internal codes, for example `9014 Metronome - R&D`.

#### Data You'll Receive

- Job details: title, complete description (text and HTML), department and posting date.
- Location: the location text as the employer wrote it (`locations[].raw`, for example `Seattle` or `Bengaluru`).
- Employer: `Stripe` or `Figma`.
- Links: the posting and apply URL.
- Pay: minimum, maximum, currency and period, on some jobs (1 of 10 in our sample).
- Source details: `custom.data` carries the Greenhouse board, internal job ID, requisition ID, first-published and updated timestamps, offices and departments.
- Stable ID and source key (`identity.source`, `identity.externalId`) for deduplication across runs.

#### Sample output data

Here is an example job from this Actor. Long descriptions are shortened with `…` and empty fields are left out for space (the long `offices` list in `custom.data` is also left out); the real output keeps them as `null`.

```json
{
  "schemaVersion": "nomad-agent-job-v1",
  "identity": {
    "url": "https://stripe.com/jobs/search?gh_jid=8257935",
    "source": "greenhouse",
    "externalId": "stripe_8257935"
  },
  "data": {
    "title": "Staff Software Engineer, Alloy Integrations",
    "company": {
      "name": "Stripe",
      "department": "9014 Metronome - R&D"
    },
    "locations": [
      {
        "raw": "Seattle"
      }
    ],
    "application": {
      "url": "https://stripe.com/jobs/search?gh_jid=8257935",
      "postedAt": "2026-10-15"
    }
  },
  "llm": {
    "status": "not_requested"
  },
  "raw": {
    "description": "Who we are\nAbout Stripe\nStripe is a financial infrastructure platform for businesses. Millions of co…",
    "descriptionHtml": "<h2>Who we are</h2>\n<h3>About Stripe</h3>\n<p><span style=\"font-weight: 400;\">Stripe is a financial i…"
  },
  "custom": {
    "data": {
      "board": "stripe",
      "language": "en",
      "nativeId": "8257935",
      "updatedAt": "2026-10-15T13:11:37-04:00",
      "departments": [
        {
          "id": 332493,
          "name": "9014 Metronome - R&D",
          "parentId": 88204
        }
      ],
      "internalJobId": 3573249,
      "requisitionId": "See Opening ID",
      "firstPublished": "2026-10-15T12:48:50-04:00"
    },
    "schemaId": "https://raw.githubusercontent.com/Exdenta/jobatlas/main/integrations/shared/greenhouse-v1.schema.json"
  }
}
```

### Greenhouse Jobs API

Results are stored in a dataset that you can export as CSV, JSON or Excel, or read on demand through the Apify API. To run it from code or on a schedule, send an input like this:

```json
{
  "schemaVersion": "nomad-agent-inventory-search-v1",
  "keyword": "engineer",
  "postedWithin": "any",
  "maxItems": 10,
  "dedupe": {
    "enabled": true,
    "key": ""
  }
}
```

Every dataset item follows the `nomad-agent-job-v1` format with six roots: `schemaVersion`, `identity`, `data`, `llm`, `raw` and `custom` ([schema](https://github.com/Exdenta/jobatlas/blob/main/integrations/shared/nomad-agent-job-v1.schema.json)). A missing fact is `null`; a known empty list is `[]`. Source-specific facts follow the [public Greenhouse schema](https://raw.githubusercontent.com/Exdenta/jobatlas/main/integrations/shared/greenhouse-v1.schema.json) named in `custom.schemaId`.

### Optional AI enrichment and English translation

Both are independent opt-ins and both are off by default. You do not supply any API key, and they add no charge on top of the per-job price.

```json
{
  "schemaVersion": "nomad-agent-inventory-search-v1",
  "keyword": "engineer",
  "maxItems": 10,
  "aiEnrichment": {
    "enabled": true,
    "accuracy": "silver"
  },
  "translateToEnglish": true,
  "dedupe": {
    "enabled": true,
    "key": ""
  }
}
```

- `aiEnrichment.enabled` fills supported unknown fields and records where each value came from in `llm`. It cannot overwrite facts the source states. Jobs whose requested enrichment fails are withheld. Without it, `llm.status` is `not_requested`. `aiEnrichment.accuracy` is `silver` or `gold`.
- `translateToEnglish` converts selected display fields into English. `raw.description` and `raw.descriptionHtml` always keep the original text.
- Only when you turn them on, description text goes to OpenRouter for extraction and selected display text goes to DeepL for translation, using our accounts. The routes deny provider data collection but do not guarantee zero retention or EU-only processing. Sanitized extracted facts and translations may be cached by us.
- Filters work on normalized values before English display translation.

### Moving from earlier releases

This release uses the input format `nomad-agent-inventory-search-v1`. Earlier source-specific inputs fail with migration guidance; replace them with `keyword` or `filters`. Original descriptions are always included. `identity.externalId` is the source's own posting ID as represented in this output and may be spelled differently from earlier releases, so the stable key is the pair `identity.source` plus `identity.externalId`. Update stored comparison keys when you migrate; your delivery history may allow a one-time repeat. The `custom` extension is new (earlier releases used `nomad-greenhouse-source-v1` with a different shape); the other five roots keep the `nomad-agent-job-v1` contract. The top-level `accuracy` field is a compatibility override for `aiEnrichment.accuracy` and never enables enrichment by itself.

#### Support and Feedback

We improve these scrapers from your feedback. If something breaks or you need a filter:

- Open an issue on the Actor's Issues tab.
- If this Actor saved you time, a short review on the Store helps other users find it.

### Run evidence

Checked on 2026-10-16 with small probe runs on the `latest` build as it was before the pay-per-event price took effect, each capped at 10 jobs or fewer:

- `NiejZzFfDjNZazZmx` (SUCCEEDED, build 1.0.4): keyword `engineer`, maxItems 10: 10 job(s).
- `LoRdTA3z9u4c9t8bR` (SUCCEEDED, build 1.0.4): keyword `engineer`, work arrangements `remote`, maxItems 10: 0 job(s).

The prefilled form (keyword `engineer`, up to 10 jobs, posted within `any`, repeat suppression on) is proven by run `NiejZzFfDjNZazZmx`: 10 jobs, each with its complete description. Select `latest` and keep the build number your run reports if you need to trace a result. The price is $0.20 per 1,000 jobs (a per-job result charge) with no start fee. A successful status alone does not prove complete coverage of the source, so inspect the dataset and `RUN-SUMMARY` together.

### Job Atlas

Explore the Job Atlas job-data and matching Actors:

- [LinkedIn Jobs Scraper](https://apify.com/jobatlas/linkedin-enrich-translate-normalize-scraper)
- [EURAXESS Jobs Scraper](https://apify.com/jobatlas/euraxess-enrich-translate-normalize-scraper)
- [Y Combinator Jobs Scraper](https://apify.com/jobatlas/ycombinator-enrich-translate-normalize-scraper)
- [AI Job Fit Scorer](https://apify.com/jobatlas/ai-job-fit-scorer)

[Product guide](https://github.com/Exdenta/jobatlas/blob/main/docs/normalized-greenhouse.md) | [Source and client examples](https://github.com/Exdenta/jobatlas) | [Setup skill](https://github.com/Exdenta/jobatlas/blob/main/.agents/skills/public-apify-actors/SKILL.md) | [Setup guide](https://github.com/Exdenta/jobatlas/blob/main/docs/public-actors-setup.md) | [Job Atlas job-data tools](https://jobatlas.dev/actors)

***

**Independent tool.** We built and run this Actor ourselves. Greenhouse, Stripe and Figma do not operate, sponsor or endorse it, and their names are used only to say which sites the data comes from.

# Actor input Schema

## `schemaVersion` (type: `string`):

Version marker for database-only normalized job search.

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

Maximum returned jobs. Zero means 200. Enrichment and filters may produce fewer matches.

## `postedWithin` (type: `string`):

Filter by the stored posting date. When Greenhouse publishes no original date, this is the first inventory admission date; later refreshes do not reset it. Positive durations are limited to 36500 days; use any for an unrestricted search.

## `workArrangements` (type: `array`):

Optional remote, hybrid, or onsite filter; empty means all.

## `dedupe` (type: `object`):

Suppress confirmed repeat deliveries for the same Apify user and search. Disable it for a stateless run.

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

Case-insensitive phrase matched against the stored title, employer, and complete original description.

## `accuracy` (type: `string`):

Compatibility override for aiEnrichment.accuracy. Prefer the accuracy field inside aiEnrichment; when this field is explicitly supplied, it takes precedence.

## `filters` (type: `object`):

Versioned filters over normalized fields. With enrichment off, only stored source facts are evaluated; unknown values do not satisfy ordinary comparisons.

## `aiEnrichment` (type: `object`):

Optional owner-funded enrichment fills unknown fields. Disabled by default. No customer API key is required.

## `translateToEnglish` (type: `boolean`):

Translate selected display fields using the owner service. Original descriptions remain unchanged. Independent of AI enrichment; disabled by default.

## Actor input object example

```json
{
  "schemaVersion": "nomad-agent-inventory-search-v1",
  "maxItems": 10,
  "postedWithin": "any",
  "workArrangements": [],
  "dedupe": {
    "enabled": true,
    "key": ""
  },
  "keyword": "engineer",
  "aiEnrichment": {
    "enabled": false,
    "accuracy": "silver"
  },
  "translateToEnglish": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `runSummary` (type: `string`):

No description

# 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 = {
    "schemaVersion": "nomad-agent-inventory-search-v1",
    "maxItems": 10,
    "postedWithin": "any",
    "workArrangements": [],
    "dedupe": {
        "enabled": true,
        "key": ""
    },
    "keyword": "engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("jobatlas/normalized-greenhouse-jobs-scraper").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 = {
    "schemaVersion": "nomad-agent-inventory-search-v1",
    "maxItems": 10,
    "postedWithin": "any",
    "workArrangements": [],
    "dedupe": {
        "enabled": True,
        "key": "",
    },
    "keyword": "engineer",
}

# Run the Actor and wait for it to finish
run = client.actor("jobatlas/normalized-greenhouse-jobs-scraper").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 '{
  "schemaVersion": "nomad-agent-inventory-search-v1",
  "maxItems": 10,
  "postedWithin": "any",
  "workArrangements": [],
  "dedupe": {
    "enabled": true,
    "key": ""
  },
  "keyword": "engineer"
}' |
apify call jobatlas/normalized-greenhouse-jobs-scraper --silent --output-dataset

```

## MCP server setup

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

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/ckQfdvSFDu0WUqhIz/builds/sOZG1xuuQoxhAabLG/openapi.json
