---
title: "Whether each research provider will still sell us work"
method: GET
path: "/v1/admin/health/providers"
tags: ["meta"]
---

# Whether each research provider will still sell us work

`GET /v1/admin/health/providers`

## Request

- Base URL: `https://api.hyperresearch.ai`
- URL: `https://api.hyperresearch.ai/v1/admin/health/providers`
- Auth: API key in cookie `hr_session`

One cheap authenticated GET per provider that has a key in this deployment, cached five minutes. OpenRouter is asked `/auth/key` and `/credits`; Firecrawl its credit-usage endpoint. Parallel and Exa bill per search and have no free status call, so they are listed under `skipped` rather than probed. No key, no key fragment and no provider response body is ever returned. Staging run_01M2NEDNYM3DM4FFRYJ2VCVBBM (2026-09-16) is why this exists: the only symptom of an out-of-credit account was a run dying at step 10.

## Response `200`

Per-provider health

- ProviderHealth
  - `checked_at` string, required
  - `cached` boolean, required: True when served from the five-minute memo rather than the wire.
  - `cache_ttl_seconds` integer, required
  - `providers` ProviderHealthRow[], required
    - `provider` 'openrouter' | 'firecrawl' | 'parallel' | 'exa', required
    - `status` 'ok' | 'unauthorized' | 'billing' | 'unknown', required: `ok` the key works and the account can pay; `billing` the key works and the account CANNOT pay (402, or a zero balance); `unauthorized` the key is rejected (401/403); `unknown` the provider gave no usable answer — never read as healthy.
    - `detail` 'payment_required' | 'insufficient_credits' | 'key_rejected' | 'probe_failed' | 'unexpected_status' | 'unreadable_response' | 'null', nullable, required: Fixed token written by us. Never a provider body, which could echo the key back.
    - `credits_remaining` number, nullable, required
    - `credits_unit` 'usd' | 'credits' | 'null', nullable, required
    - `http_status` integer, nullable, required
  - `skipped` object[], required: Providers with no row, and why. `no_key`: this deployment holds no key for it. `no_probe_endpoint`: it has no free authenticated status endpoint, so probing it would spend money every five minutes. Neither is a failure, and neither means healthy.
    - `provider` 'openrouter' | 'firecrawl' | 'parallel' | 'exa', required
    - `reason` 'no_key' | 'no_probe_endpoint', required

## Other responses

- `400`: Invalid request
- `401`: Authentication failed
- `403`: Insufficient scope or plan
- `404`: Not found
- `429`: Rate limited or over quota
- `500`: Internal error

---

[API](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api.md) · [All operations](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/revisions/726ef831ebf4?raw)
