# Freshness tiers & source coverage

> Choose a freshness tier per request. Every record reports its own lastCheckedAt, and GET /v1/sources returns the live coverage catalog with health signals.

- **HTML:** https://offendersearch.app/docs/freshness
- **Base URL:** https://api.offendersearch.app
- **Authentication:** `X-API-Key` request header
- **OpenAPI:** https://offendersearch.app/openapi.json · https://offendersearch.app/openapi.yaml
- **All documentation as markdown:** https://offendersearch.app/docs.md

## Freshness tiers

Freshness is an optional per-request `freshness` parameter with two values. It defaults to `daily` — the most current tier — billed at the base rate plus $0.01 per call. Pass `weekly` for the same dataset one tier behind, with no surcharge. Every record returns a `lastCheckedAt` either way, so currency is a value on the response rather than an assumption about the service.

| Tier | What you get | Price | Best for |
| --- | --- | --- | --- |
| `daily (default)` | The most current coverage tier | Base + $0.01 / call | Anything where currency decides the outcome: pre-employment screening, tenant checks, live compliance |
| `weekly` | One tier behind daily — identity fields are equivalent | Included at base rate (no surcharge) | Bulk and batch work, and periodic re-screens |

Base is $0.15 per call, dropping to $0.11 after 2,000 calls a month; the default daily freshness adds $0.01 per call, and weekly freshness has no surcharge.

**Send `daily` when currency decides the outcome** — pre-employment screening, tenant checks, live compliance. **Send `weekly` for bulk and periodic work**: it is the same nationwide dataset one tier behind, and identity fields — name, date of birth, offence history, aliases — are equivalent.

```json
{
  "query": { "firstName": "John", "lastName": "Doe", "dob": "1980-04-12" },
  "freshness": "daily"
}
```

## Currency is answered per request

Two fields carry it, and both are on every response. `sources[].lastCheckedAt` is when that jurisdiction’s copy of the record was last confirmed, and `sourceStatus[].lastCheckedAt` is the same question at the jurisdiction level for every jurisdiction the search touched — including the ones that returned no match. Read them rather than a general statement about the dataset: they are contract fields, and they answer the question for the exact record and the exact request in front of you.

```json
{
  "source": {
    "jurisdiction": "NJ",
    "registryName": "State Sex Offender Registry",
    "recordUrl": "https://…",
    "scrapedAt": "2026-08-13T04:12:00Z",
    "lastCheckedAt": "2026-08-13T04:12:00Z",
    "sourceUpdatedAt": "2026-08-11T00:00:00Z"
  },
  "sources": []
}
```

`sourceUpdatedAt` is the date the jurisdiction itself states it last changed the record; it is `null` where a jurisdiction publishes no such date.

## GET /v1/sources — List sources

The coverage catalog: every jurisdiction we cover, by code, name, and live health.

**Authentication:** `X-API-Key` header.

The live coverage catalog: every jurisdiction the API covers, with its code, display name, and health signals such as typical latency and last successful refresh. Use it to render your own coverage UI or to decide which `jurisdictions` to name.

### What you can do

- **Coverage.** Every jurisdiction with its code and name.
- **Health.** Typical latency and last successful refresh timestamps, per jurisdiction.

### Request

**cURL**

```bash
curl https://api.offendersearch.app/v1/sources \
  -H "X-API-Key: $OFFENDERSEARCH_KEY"
```

**Node**

```javascript
const res = await fetch("https://api.offendersearch.app/v1/sources", {
  headers: { "X-API-Key": process.env.OFFENDERSEARCH_KEY },
});
const sources = await res.json();
for (const s of sources) console.log(s.id, s.scope, s.covers.join(","));
```

**Python**

```python
import os, requests

resp = requests.get(
    "https://api.offendersearch.app/v1/sources",
    headers={"X-API-Key": os.environ["OFFENDERSEARCH_KEY"]},
)
for s in resp.json():
    print(s["id"], s["scope"], ",".join(s["covers"]))
```

### Response

```json
[
  {
    "id": "NJ",
    "name": "State Sex Offender Registry",
    "covers": ["NJ"],
    "health": { "lastSuccessAt": "2026-07-25T09:14:00Z", "typicalLatencyMs": 380 }
  },
  {
    "id": "CA",
    "name": "State Sex Offender Registry",
    "covers": ["CA"],
    "health": { "lastSuccessAt": "2026-07-25T09:14:00Z", "typicalLatencyMs": 410 }
  }
]
```

---

## Related

- Previous: [Pagination & response size](https://offendersearch.app/docs/pagination.md)
- Next: [Jurisdictions & codes](https://offendersearch.app/docs/jurisdictions.md)
- Index: [Offendersearch API documentation](https://offendersearch.app/docs.md)
