# JazzHR Jobs API | Search Every Company Job Board (`johnvc/jazzhr-jobs-api`) Actor

Search live job postings across every company hiring on JazzHR (applytojob.com). No company URL needed. Returns titles, employers, locations, posting dates, apply links, and full descriptions in markdown, HTML, or text, plus a directory of every employer on the platform.

- **URL**: https://apify.com/johnvc/jazzhr-jobs-api.md
- **Developed by:** [John](https://apify.com/johnvc) (community)
- **Categories:** Jobs, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 job records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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

## JazzHR Jobs API

Search live job postings across every company hiring on JazzHR (applytojob.com) with one API call. Most JazzHR tools make you supply a company URL first. This one already knows every employer on the platform, so you can search all of them at once, or narrow to a single board. In practice it works as a read-only JazzHR API for public job data: no API keys, no login, nothing to install.

This is an independent tool. It is not affiliated with, endorsed by, or connected to [JazzHR](https://www.jazzhr.com/) or Employ Inc. It reads only public job postings.

### What you can extract

| Field | What it is |
|---|---|
| `title`, `descriptionMarkdown` | Job title and the full description, in markdown, HTML, or plain text |
| `companyName`, `companySlug`, `companyWebsite`, `boardUrl` | The employer, their site, and their JazzHR board |
| `city`, `region`, `postalCode`, `country`, `isRemote` | Where the job is, and whether it is remote |
| `employmentType`, `experienceLevel` | Full time, part time, contract, and the seniority the employer asked for |
| `datePosted`, `validThrough` | When the employer posted it and when it expires |
| `applyUrl`, `canonicalUrl` | The application link, plus the employer's own branded careers URL when they use one |

### A JazzHR API that already knows every employer

You do not need a company URL to start. Leave the input empty and the search covers every employer on the platform.

Switch to the company directory mode and you get the employer list itself: every business hiring on JazzHR, with a live count of their open roles. That is a useful thing to have before you decide which boards are worth pulling in full.

Descriptions come back as markdown, so you can hand them to an LLM without stripping HTML first.

Two things happen quietly that matter more than they sound. About a quarter of live postings publish no structured job data at all; those get read from the page markup instead of coming back half empty. And roughly a fifth of the entries in the platform index point at roles that have already closed, which are skipped and never billed. You pay for jobs you actually receive.

Delta mode handles the rest: turn it on and each scheduled run returns only the postings you have not seen before.

### What is applytojob.com?

[applytojob.com](https://applytojob.com) is the domain where JazzHR hosts its customers' career pages. When a company uses JazzHR to hire, their job board lives at company.applytojob.com, and application emails come from that domain too, which is why so many people search for it after applying somewhere. Every public board hosted there is what this Actor indexes: one search covers all of them.

### Use cases

- Scrape job postings for a niche job board fed by small and mid-sized employers the big aggregators miss.
- Give an AI career assistant live job data with descriptions it can read directly.
- Find companies hiring for a role in your territory, then sell to them.
- Feed job posting data into hiring-velocity dashboards by company, city, or title.
- Alert a team whenever a competitor posts a new opening.

### 🔌 Integrations: turn JazzHR postings into a live feed

One run answers a question. The integrations are how this becomes a pipeline you stop thinking about.

- **Tasks and Schedules.** Save your search as an Apify Task, put it on a weekly schedule, and switch on `newJobsOnly`. From then on the dataset only ever contains postings that appeared since the last run: a self-maintaining new-jobs feed.
- **n8n, Make, and Zapier.** Trigger runs and consume results through [Apify's integrations](https://docs.apify.com/platform/integrations), so new postings can land in Slack, Sheets, Airtable, or your CRM.
- **Databases and storage.** Push each run's dataset to Postgres, Supabase, or S3 with the standard Apify dataset integrations, and query job posting data with SQL.
- **Webhooks.** Fire a webhook on run completion to kick off your own processing the moment a delta run finds something new.
- **MCP.** AI agents can run the whole loop themselves; see the Claude section below.

### Input parameters

Every field is optional. Running with no input at all returns a sample of jobs from across the platform.

| Parameter | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | array | empty | Company boards such as `https://company.applytojob.com`, or individual job URLs. Empty searches every employer. |
| `keywords` | array | empty | Job title words to keep. Applied before each posting is opened, so it also makes the run cheaper. |
| `outputMode` | select | `jobs` | `jobs` for full records, `urlsOnly` for the job index, `companiesOnly` for the employer directory. |
| `descriptionFormat` | select | `markdown` | `markdown`, `html`, `text`, or `all`. |
| `companies` / `excludeCompanies` | array | empty | Company slugs to include or skip. For `acme.applytojob.com` the slug is `acme`. |
| `location` | string | empty | Text match on city, state, postal code, or country. |
| `employmentType` | select | `ANY` | Full time, part time, contractor, temporary, intern, or other. |
| `remoteOnly` | boolean | `false` | Keep only remote roles. |
| `postedAfter` | string | empty | `YYYY-MM-DD`. Uses the employer's real posting date. |
| `maxItems` | integer | `100` | Row cap. The platform holds over 100,000 live jobs, so this is what keeps a first run small. |
| `newJobsOnly` | boolean | `false` | Return only postings not seen in an earlier run. |
| `firstRunBehavior` | select | `emitAll` | On the first delta run, return everything or just record what exists today. |
| `deltaStoreName` | string | `jazzhr-seen-jobs` | Named store holding the remembered job IDs. Change it to keep separate delta histories per search. |
| `maxConcurrency` | integer | `10` | Parallel page reads, up to 25. |
| `proxyConfiguration` | object | direct | Optional Apify Proxy settings. Direct connections work; leave off unless you hit blocking. |

### Example output

```json
{
  "id": "job_20260617184930_ZL9U2ROWTQWMZDDD",
  "jobId": "vMHpWDZa3l",
  "title": "Account Executive",
  "companyName": "Ease Inc",
  "companySlug": "easeinc",
  "companyWebsite": "http://www.ease.io",
  "boardUrl": "https://easeinc.applytojob.com",
  "applyUrl": "https://easeinc.applytojob.com/apply/vMHpWDZa3l/Account-Executive",
  "canonicalUrl": "https://careers.easeinc.com/apply/vMHpWDZa3l/Account-Executive",
  "city": "Irvine",
  "region": "CA",
  "postalCode": "92618",
  "country": "US",
  "locationText": "Irvine, CA, US",
  "isRemote": true,
  "employmentType": "FULL_TIME",
  "experienceLevel": "Mid Level",
  "datePosted": "2026-06-17",
  "validThrough": "2026-09-15",
  "descriptionMarkdown": "Ease is hiring an Account Executive to help manufacturers improve quality, safety, and operational performance...",
  "parseStatus": "full",
  "scrapedAt": "2026-08-10T18:22:04Z"
}
```

The company directory mode returns a different, much smaller row:

```json
{
  "companySlug": "easeinc",
  "boardUrl": "https://easeinc.applytojob.com",
  "jobCount": 17,
  "sampleJobTitles": ["Account Executive", "Implementation Manager"],
  "scrapedAt": "2026-08-10T18:22:04Z"
}
```

### Pricing

You pay per row returned, and the three output modes are priced differently because they cost very differently to produce. Full job records carry the highest rate since each one is a separate page read. The job index and the company directory are built from a handful of requests, so they are priced far lower and are the cheap way to survey the whole platform before deciding what to pull in full. Nothing is charged for postings that turn out to be expired, for rows removed by your filters, or for jobs suppressed by delta mode. Current rates are on the Store page.

### How to get started

1. Open the Actor and press Start. With no input it returns a sample of jobs from across the platform.
2. Add `keywords` to narrow to the roles you care about, or `startUrls` to target one employer.
3. Switch `outputMode` to `companiesOnly` to see who is hiring before pulling any descriptions.
4. Raise `maxItems` once the shape of the output looks right.

[View on Apify Store](https://apify.com/johnvc/jazzhr-jobs-api?fpr=9n7kx3)

Ready-made Python and MCP walkthroughs live in the [example repo](https://github.com/johnisanerd/jazzhr-jobs-api-example).

### 🔌 Use this API from Claude (MCP)

Add this Actor as a tool in [Claude Code](https://claude.ai/referral/uIlpa7nPLg) (free trial), [Claude Cowork](https://claude.ai/referral/uIlpa7nPLg) (free trial), or any other MCP client, through the hosted Apify MCP server:

https://mcp.apify.com/?tools=actors,docs,johnvc/jazzhr-jobs-api

Setup walkthrough:

https://www.youtube.com/watch?v=jREWahDGhJM

Apify MCP integration docs: https://docs.apify.com/platform/integrations/mcp

### 💸 Pay per run with crypto (x402)

The JazzHR Jobs API supports agentic payments via the [x402 protocol](https://docs.apify.com/platform/integrations/x402).
AI agents and MCP clients can pay for runs in USDC (on Base) with no Apify account or API token needed:
point your agent at the [Apify MCP server](https://mcp.apify.com/?tools=actors,docs,johnvc/jazzhr-jobs-api) and it can
discover, pay for, and run this Actor autonomously. Read the
[Apify x402 announcement](https://apify.com/change-log/pay-for-apify-actors-with-x402?fpr=9n7kx3) for details.

### FAQ

#### Is this an API or a web scraper?

Both, honestly. Under the hood it reads public pages the way a scraper does. What you get is an API: structured JSON on demand, filters, stable field names, and no HTML in sight unless you ask for it. If you have been trying to scrape job postings yourself, this is the version where someone else maintains the parser.

#### Do I need a company URL to use this?

No. That is the main difference from other JazzHR tools. Leave `startUrls` empty and the Actor searches every employer on the platform. Supply a board URL only when you want one specific company.

#### How many jobs and companies are there?

The platform index currently lists a little over 114,000 postings across roughly 7,500 employers. A portion of those postings have already been filled or withdrawn; the Actor skips them and does not bill for them.

#### Why do some rows have no posting date?

Employers publish their postings in two different ways. Where a posting carries structured job data, the real posting date and expiry date come with it. Where it does not, the title, company, location, employment type, and description are read from the page instead, and no date is available. The `parseStatus` field tells you which kind of row you are looking at.

#### How do I get only jobs posted since my last run?

Turn on `newJobsOnly`. The Actor remembers the job IDs it has returned and skips them next time. On the very first run, set `firstRunBehavior` to `seedOnly` if you want it to record what exists today and return nothing, so the following run is a clean list of new postings.

#### Can I run it on a schedule?

Yes, and that is the intended way to use it. Save your input as a Task, add a schedule, and turn on delta mode so each run returns only new postings. The Integrations section above shows where to send the results.

#### How do I use the JazzHR API from other apps?

Every run is reachable over the Apify REST API, so anything that can make an HTTP request can start a search and read the results. n8n, Make, and Zapier all have ready connectors, listed in the Integrations section.

#### Can AI assistants run this through an MCP server?

Yes. The hosted MCP server URL in the Claude section above registers this Actor as a tool, so an assistant can search postings, pull the company directory, and pay per result without you writing any code.

#### Can I get salaries?

Salary is not a separate field because most employers on this platform write pay into the job description rather than into a structured field. Search `descriptionMarkdown` for it.

#### Why did my run return fewer rows than maxItems?

Either the filters matched fewer jobs than the cap, or the run hit the budget you set for it. The run log states which, along with how many postings were filtered out and how many had already expired.

#### Is applytojob.com legit?

Yes. It is the hosting domain for JazzHR customer career pages, so a real company you applied to will send mail from it. If an offer arrived from that domain for a job you never applied to, treat it with the same suspicion as any unsolicited offer.

#### Where does JazzHR post jobs?

Each customer gets a public board on applytojob.com, and [JazzHR](https://www.jazzhr.com/) syndicates postings out to external boards the employer chooses. This Actor reads the public boards, which are the complete, first-party source.

#### Is scraping this data allowed?

The Actor reads only public job postings and the public [sitemap index](https://www.sitemaps.org/) that the platform itself publishes for search engines in its robots.txt. It signs in to nothing and collects no candidate or applicant data. Job boards are one of the most common public data sources for an [applicant tracking system](https://en.wikipedia.org/wiki/Applicant_tracking_system) ecosystem, and this one stays strictly on the public side.

### 🔗 Related Tools

Hiring data rarely stops at one platform. These pair well with this Actor:

- [LinkedIn Jobs API](https://apify.com/johnvc/linkedin-jobs-api?fpr=9n7kx3) for the roles large employers post publicly.
- [Workday Careers API](https://apify.com/johnvc/workday-careers-api?fpr=9n7kx3) for enterprise job boards on Workday.
- [iCIMS Careers API](https://apify.com/johnvc/icims-careers-api?fpr=9n7kx3) for the Fortune 500 heavy iCIMS platform.
- [Google Jobs Scraper](https://apify.com/johnvc/google-jobs-scraper---pay-per-result?fpr=9n7kx3) for how postings appear in Google's job search.

There are simpler JazzHR tools on the Store, like [this one](https://apify.com/benthepythondev/jazzhr-jobs-scraper?fpr=9n7kx3), that fetch a handful of rows from a board URL you already know. Fine for a spot check; this Actor is for when you need the whole platform, filters, and a feed that keeps itself current.

***

### 🌐 About Alpha OSINT

This Actor is part of [Alpha OSINT](https://www.alphaosint.com), toolset of financial and operations data sources and APIs.
For support or requests for this actor, please start a ticket [directly on our support page](https://apify.com/johnvc/jazzhr-jobs-api/issues/open?fpr=9n7kx3).

Last Updated: 2026.08.18

# Actor input Schema

## `startUrls` (type: `array`):

Optional. JazzHR company boards such as https://company.applytojob.com or individual job URLs. Leave empty to search every company on the platform.

## `keywords` (type: `array`):

Optional. Keep only jobs whose title contains any of these words, for example nurse, welder, account executive. Matched against the job URL before each job page is fetched, so filtering here makes runs cheaper.

## `outputMode` (type: `string`):

jobs returns full job records with descriptions. urlsOnly returns the job index without opening each posting, which is the cheapest way to list everything. companiesOnly returns one row per employer with a job count, a directory of every company hiring on JazzHR.

## `descriptionFormat` (type: `string`):

How to return each job description. Markdown is compact and reads well in AI agents and LLM pipelines, html preserves the original markup, text is plain prose, all returns every format.

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

Optional. Company slugs to include, taken from the subdomain of a JazzHR board. For https://acmecorp.applytojob.com the slug is acmecorp.

## `excludeCompanies` (type: `array`):

Optional. Company slugs to skip. Useful for filtering out staffing agencies or employers you already track.

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

Optional. Case-insensitive text match against the city, state, postal code, or country of the job, for example Austin, CA, or 92618.

## `employmentType` (type: `string`):

Keep only jobs of this employment type. Leave on Any to include everything.

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

Keep only postings the employer flagged as remote.

## `postedAfter` (type: `string`):

Optional. Keep only jobs the employer posted on or after this date, in YYYY-MM-DD form. Uses the real posting date from the job page.

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

Stop after this many rows. The platform holds well over 100,000 live jobs, so this cap is what keeps an exploratory run small and cheap.

## `newJobsOnly` (type: `boolean`):

Return only postings this Actor has not returned in an earlier run. Job IDs are remembered between runs, which turns a schedule into a feed of newly posted jobs.

## `firstRunBehavior` (type: `string`):

What the first run should do when Only jobs not seen before is on. Emit all returns everything and remembers it. Seed only returns nothing and just records what exists today, so the next run is a clean list of new jobs.

## `deltaStoreName` (type: `string`):

Named key-value store that holds the job IDs seen so far. Change it to keep separate delta histories for separate searches.

## `maxConcurrency` (type: `integer`):

How many job pages to read at once. Lower it if the source starts rejecting requests; the Actor also slows itself down automatically when error rates rise.

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

Optional. Route requests through Apify Proxy. Direct connections work by default, so leave this off unless you hit blocking.

## Actor input object example

```json
{
  "startUrls": [],
  "keywords": [
    "software engineer"
  ],
  "outputMode": "jobs",
  "descriptionFormat": "markdown",
  "companies": [],
  "excludeCompanies": [],
  "location": "",
  "employmentType": "ANY",
  "remoteOnly": false,
  "postedAfter": "",
  "maxItems": 100,
  "newJobsOnly": false,
  "firstRunBehavior": "emitAll",
  "deltaStoreName": "jazzhr-seen-jobs",
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `allResults` (type: `string`):

Every row this run produced.

## `overview` (type: `string`):

Job rows with the headline fields: title, company, location, type, and apply link.

## `companies` (type: `string`):

One row per employer with an open-jobs count and a link to their board.

## `jobUrls` (type: `string`):

The job index: IDs, titles, and apply links without full descriptions.

# 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 = {
    "startUrls": [],
    "keywords": [
        "software engineer"
    ],
    "outputMode": "jobs",
    "descriptionFormat": "markdown",
    "companies": [],
    "excludeCompanies": [],
    "location": "",
    "employmentType": "ANY",
    "postedAfter": "",
    "maxItems": 100,
    "firstRunBehavior": "emitAll",
    "deltaStoreName": "jazzhr-seen-jobs",
    "maxConcurrency": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("johnvc/jazzhr-jobs-api").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 = {
    "startUrls": [],
    "keywords": ["software engineer"],
    "outputMode": "jobs",
    "descriptionFormat": "markdown",
    "companies": [],
    "excludeCompanies": [],
    "location": "",
    "employmentType": "ANY",
    "postedAfter": "",
    "maxItems": 100,
    "firstRunBehavior": "emitAll",
    "deltaStoreName": "jazzhr-seen-jobs",
    "maxConcurrency": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("johnvc/jazzhr-jobs-api").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 '{
  "startUrls": [],
  "keywords": [
    "software engineer"
  ],
  "outputMode": "jobs",
  "descriptionFormat": "markdown",
  "companies": [],
  "excludeCompanies": [],
  "location": "",
  "employmentType": "ANY",
  "postedAfter": "",
  "maxItems": 100,
  "firstRunBehavior": "emitAll",
  "deltaStoreName": "jazzhr-seen-jobs",
  "maxConcurrency": 10
}' |
apify call johnvc/jazzhr-jobs-api --silent --output-dataset

```

## MCP server setup

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

```

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/Kv1kG2WbLlEvSe4Yc/builds/WVmlbvkWdtEcjDVOi/openapi.json
