# BetterJobs index

> What is the BetterJobs index, and why is it on every plan?

Source: https://docs.betterjobs.cc/providers/betterjobs-index/

The BetterJobs index is our own job sources: an owned crawl of employer career pages and ATSs. It is the one source on every plan, including Free.

BetterJobs index

`betterjobs`

Our own job sources: an owned crawl of employer career pages and ATSs.

- Sources

  Employer career pages and ATSs crawled by BetterJobs

- Volume

  Published at GA. Live counts per request in metadata.providers.contributions.

- Freshness

  Published at GA. Each job carries first\_seen\_at, last\_seen\_at and last\_verified\_at.

- Cost

  1 credit per unique job returned, same as every source

Every plan.

Facts BetterJobs.

## What it is

BetterJobs crawls employer career pages and the ATSs behind them. Jobs found there go into the index. It is not a partner provider. No third party sits between the employer’s page and your result.

Because we run it ourselves:

- It is on **every plan**. Free (1,000 credits to test, no card) and Starter search the index only.
- `cheapest_first`, the default strategy, asks it **first**. Partner providers are added only when the index cannot fill the page.
- `own_only` restricts a search to it. Use this on Free and Starter, or when you want the simplest licensing.

## What it contributes to a BetterJobs job

The index reads the employer’s own posting, so it tends to supply the fields that live on that page. In the spec’s illustrative example, the index contributed these fields to a canonical job:

```json
{
  "provider": "betterjobs",
  "provider_job_id": "bj_idx_5521907",
  "url": "https://jobs.acme-robotics.example/revops-lead",
  "first_seen_at": "2026-10-08T06:40:00Z",
  "last_seen_at": "2026-10-11T06:10:00Z",
  "fields": ["title", "description", "apply_url", "location", "employment_type", "posted_at"]
}
```

Illustrative. On real jobs, `sources[].fields` tells you exactly what the index supplied. See [Provenance and confidence](https://docs.betterjobs.cc/concepts/provenance-and-confidence.md).

## Refresh

We do not publish a refresh number for the index yet. It is published at GA. Every job carries its own timestamps instead:

- `sources[].first_seen_at` and `sources[].last_seen_at` for the index’s entry: when our crawl first and last saw the posting.
- `last_verified_at` on the job: the latest time the job was confirmed live at its origin.

See [Freshness and lifecycle](https://docs.betterjobs.cc/concepts/freshness-and-lifecycle.md).

## Volume

Published at GA. Each search reports what the index added: `metadata.providers.contributions.betterjobs` counts the unique jobs it contributed first.

## Search the index only

**curl**

```bash
curl https://api.betterjobs.cc/v1/jobs/search \
  -H "Authorization: Bearer $BETTERJOBS_API_KEY" \
  -H "BetterJobs-Version: 2026-10-01" \
  -H "Content-Type: application/json" \
  -d '{
    "filters": {
      "title_or": ["Head of RevOps", "Head of Revenue Operations"],
      "country_code_or": ["DE", "AT", "CH"],
      "posted_within_days": 7
    },
    "waterfall": { "strategy": "own_only", "max_credits": 50 },
    "limit": 25
  }'
```

**Python**

```python
import os
import requests


resp = requests.post(
    "https://api.betterjobs.cc/v1/jobs/search",
    headers={
        "Authorization": f"Bearer {os.environ['BETTERJOBS_API_KEY']}",
        "BetterJobs-Version": "2026-10-01",
    },
    json={
        "filters": {
            "title_or": ["Head of RevOps", "Head of Revenue Operations"],
            "country_code_or": ["DE", "AT", "CH"],
            "posted_within_days": 7,
        },
        "waterfall": {"strategy": "own_only", "max_credits": 50},
        "limit": 25,
    },
)
resp.raise_for_status()
body = resp.json()
print(len(body["data"]), body["metadata"]["credits_charged"])
```

**TypeScript**

```ts
const resp = await fetch('https://api.betterjobs.cc/v1/jobs/search', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.BETTERJOBS_API_KEY}`,
    'BetterJobs-Version': '2026-10-01',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    filters: {
      title_or: ['Head of RevOps', 'Head of Revenue Operations'],
      country_code_or: ['DE', 'AT', 'CH'],
      posted_within_days: 7,
    },
    waterfall: { strategy: 'own_only', max_credits: 50 },
    limit: 25,
  }),
});
if (!resp.ok) throw new Error(`BetterJobs ${resp.status}`);
const body = await resp.json();
console.log(body.data.length, body.metadata.credits_charged);
```

## Cost

Same as every source: 1 credit per unique job returned. Duplicates and empty searches are free. A job the index and a partner both found is one job and one credit. See [Credits and billing](https://docs.betterjobs.cc/concepts/credits-and-billing.md).

> Free and Starter: only the index
>
> On Free and Starter, sending a partner slug in `waterfall.providers` returns `403 plan_required`. Growth adds 2 partner providers; Pro and above add all six. See [Providers](https://docs.betterjobs.cc/providers.md#which-plan-includes-which-provider).

## Provider docs

None. This is our own source. Everything about it is on this site.

## Related

- [The waterfall](https://docs.betterjobs.cc/concepts/waterfall.md)
- [Choose a strategy](https://docs.betterjobs.cc/guides/choose-a-strategy.md)
- [Canonical jobs](https://docs.betterjobs.cc/concepts/canonical-jobs.md)
