# Provider status

> How do I check whether each upstream provider is working right now?

Source: https://docs.betterjobs.cc/resources/provider-status/

BetterJobs depends on six partner providers and its own index. When one is slow or down, your results can be thinner. `GET /v1/providers` tells you the live state of each source, and every search response tells you which sources actually answered.

## Check status

`GET /v1/providers` is free. It lists every source BetterJobs can route to, whether your plan includes it, and its status.

**curl**

```bash
curl https://api.betterjobs.cc/v1/providers \
  -H "Authorization: Bearer $BETTERJOBS_API_KEY" \
  -H "BetterJobs-Version: 2026-10-01"
```

**Python**

```python
import os
import requests


resp = requests.get(
    "https://api.betterjobs.cc/v1/providers",
    headers={
        "Authorization": f"Bearer {os.environ['BETTERJOBS_API_KEY']}",
        "BetterJobs-Version": "2026-10-01",
    },
    timeout=30,
)
resp.raise_for_status()
for p in resp.json()["data"]:
    print(p["slug"], p["status"], "enabled" if p["enabled_on_your_plan"] else "not on plan")
```

**TypeScript**

```ts
const res = await fetch("https://api.betterjobs.cc/v1/providers", {
  headers: {
    Authorization: `Bearer ${process.env.BETTERJOBS_API_KEY}`,
    "BetterJobs-Version": "2026-10-01",
  },
});
if (!res.ok) throw new Error(`BetterJobs ${res.status}: ${await res.text()}`);
const { data } = await res.json();
for (const p of data) {
  console.log(p.slug, p.status, p.enabled_on_your_plan ? "enabled" : "not on plan");
}
```

Illustrative response, seen from a Growth plan:

```json
{
  "data": [
    { "slug": "betterjobs", "name": "BetterJobs index", "enabled_on_your_plan": true, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" },
    { "slug": "reqbeat", "name": "Reqbeat", "enabled_on_your_plan": false, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" },
    { "slug": "signalsapi", "name": "SignalsAPI", "enabled_on_your_plan": false, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" },
    { "slug": "theirstack", "name": "TheirStack", "enabled_on_your_plan": true, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" },
    { "slug": "jobspipe", "name": "JobsPipe", "enabled_on_your_plan": false, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" },
    { "slug": "coresignal", "name": "Coresignal", "enabled_on_your_plan": false, "status": "degraded", "last_checked_at": "2026-10-11T09:00:00Z" },
    { "slug": "techmap", "name": "Techmap", "enabled_on_your_plan": true, "status": "operational", "last_checked_at": "2026-10-11T09:00:00Z" }
  ]
}
```

## Fields

| Field                  | Type                                                                                                 | Meaning                                                                                                                                         |
| ---------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `slug`                 | `betterjobs` \| `reqbeat` \| `signalsapi` \| `theirstack` \| `jobspipe` \| `coresignal` \| `techmap` | Source id. The same slug appears in `sources[].provider`, `waterfall.providers` and `metadata.providers`. `betterjobs` is the BetterJobs index. |
| `name`                 | string                                                                                               | Display name.                                                                                                                                   |
| `enabled_on_your_plan` | boolean                                                                                              | Whether your plan can route to this source. `GET /v1/account` lists the same set as `providers_enabled`.                                        |
| `status`               | `operational` \| `degraded` \| `down`                                                                | Live state of the source.                                                                                                                       |
| `last_checked_at`      | date-time                                                                                            | When this status was last checked.                                                                                                              |

What each status means for you:

| `status`      | What to expect                                                                                                                 |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `operational` | Normal.                                                                                                                        |
| `degraded`    | The source is answering badly, for example slowly or with errors. It is more likely to show up in `metadata.providers.failed`. |
| `down`        | The source is not answering. Expect it in `metadata.providers.failed` on every request that tries it.                          |

Sending a provider that is not enabled on your plan in `waterfall.providers` returns `403 plan_required`, with `error.required_plan` and `error.upgrade_url`. See [Errors](https://docs.betterjobs.cc/platform/errors.md#plan_required).

## How degradation affects your results

A failing provider never fails your request. BetterJobs waits up to `waterfall.timeout_ms` (default 10,000 ms), drops any provider that errors or misses it, and returns what the others found.

You get `200` with `metadata.status: "partial"`. The failed provider is in `metadata.providers.failed`:

```json
{
  "metadata": {
    "status": "partial",
    "credits_charged": 1,
    "providers": {
      "tried": ["betterjobs", "techmap", "theirstack", "coresignal"],
      "hit": ["betterjobs", "techmap", "theirstack"],
      "failed": [{ "provider": "coresignal", "code": "provider_timeout" }],
      "contributions": { "betterjobs": 1, "techmap": 0, "theirstack": 0 }
    }
  }
}
```

- `code` is `provider_timeout` (missed `timeout_ms`) or `provider_error` (the provider returned an error).
- You pay only for jobs returned. A provider that failed costs nothing.
- Jobs only that provider would have found are missing from this page.
- An async search that ends this way has `status: "partial"`.

`metadata.providers` is the receipt for each request: `tried` (asked), `hit` (returned at least one match), `failed`, and `contributions` (unique jobs each source added first).

> When a partial result is not good enough
>
> - **Retry later.** A repeat is cheap: jobs you already paid for come back free.
> - **Give slow providers more time.** Raise `waterfall.timeout_ms`, up to 30,000.
> - **Route around it.** Set `waterfall.providers` to the list without the failing source.
> - **Branch in code.** Treat `metadata.status: "partial"` as “complete, but maybe not exhaustive”. For backfills, re-run partial pages once the provider is `operational` again.

## What this page does not show

- **Uptime history and latency percentiles.** Not published during the preview. They are published at GA. Each response reports its own `latency_ms` in `metadata`.
- **Per-provider coverage and freshness.** These differ by source. What each provider says about itself is on its card under [Providers](https://docs.betterjobs.cc/providers.md), attributed to that provider. For your own queries, read `metadata.field_coverage` and `metadata.providers.contributions`.

## Related

- [Waterfall](https://docs.betterjobs.cc/concepts/waterfall.md) for how providers are tried.
- [Choose a strategy](https://docs.betterjobs.cc/guides/choose-a-strategy.md) for picking a strategy and providers.
- [Troubleshooting](https://docs.betterjobs.cc/resources/troubleshooting.md) for partial and empty results.
