API Reference
Read-only JSON API serving the DecayStats Erosion Index, Decay
Index, and per-stratum decomposition for 52 geographies and 10
household archetypes. URL-versioned at /api/v1/.
No authentication. Open CORS. Per-IP rate-limited.
Overview
- Base URL.
https://decaystats.com/api/v1 - Protocol. HTTPS only. All endpoints
GET. - Content type.
application/json; charset=utf-8 - Versioning. URL-prefixed (
/v1/). Backward-incompatible changes get a/v2/prefix. - CORS. Open (
*) for all/api/*paths. - Provenance. Every response includes
methodology_version,basket_version, andgenerated_at.
Getting started
No API key required. No auth header required. All endpoints are public read-only.
curl https://decaystats.com/api/v1/health
Authentication
None. Every endpoint is public read-only. No
Authorization header, query token, or API key is
read by the application. If future write endpoints are added,
they will be introduced under a separate path with auth
documented inline; the read API will remain unauthenticated.
Rate limits
Global per-IP limits enforced by Flask-Limiter:
- 120 requests per minute per client IP
- 5,000 requests per day per client IP
Exceeding either limit returns HTTP 429 with the
error body documented in Error format.
The retry_after_seconds field indicates suggested
back-off (default 60). Higher tiers are not offered; clients
requiring sustained throughput should cache locally — responses
are stable until the next ingest run.
Response conventions
Every successful response is wrapped in a provenance envelope:
{
"methodology_version": "2.0.4",
"basket_version": "1.0.12",
"generated_at": "2026-05-27T14:22:03.119482+00:00",
"data": <endpoint-specific payload>
}
Some endpoints add sibling keys alongside data
(for example coverage_months on series endpoints).
Numeric types. All index levels and rates are
JSON numbers. Internal computation uses Decimal;
serialization converts to float at the response
boundary.
Period strings. Monthly periods are
YYYY-MM. Annual periods are YYYY.
Both order lexicographically.
Common query parameters
Accepted on all v1.1 endpoints (archetype, state, series). Ignored on v1.0 endpoints (/index/*, /basket, /methodology).
| Parameter | Type | Default | Behavior |
|---|---|---|---|
basket_version |
string | active version | Pin response to a specific locked basket version. Stable downstream consumers should pin. |
as_of |
YYYY-MM-DD | none | Reserved for v1.1.x point-in-time queries. Currently accepted but not applied — returns same data as omitting the parameter. |
Error format
Errors return a JSON body and a matching HTTP status code.
{
"error": "not_found",
"message": "Unknown geography 'ZZ'. Valid: 'US' or a USPS 2-letter state code."
}
| HTTP | error | Trigger |
|---|---|---|
| 400 | (Flask default) | Required query parameter missing. |
| 404 | not_found | Unknown path, archetype, or geography; wrong-level geography for path. |
| 429 | rate_limited | Per-IP rate limit exceeded. Body includes retry_after_seconds. |
| 500 | internal_error | Unhandled server-side exception. Body never includes a stack trace. |
Endpoints — Health & Status
Lightweight liveness probe. Reports overall app status, methodology and basket versions, and a single database-connectivity check. Intentionally cheap so it can be polled at high frequency — the per-source data-freshness scan lives at /api/v1/status.
Status values: ok or degraded. degraded when the database connectivity ping fails.
curl https://decaystats.com/api/v1/health
Example response
{
"status": "ok",
"methodology_version": "2.0.4",
"basket_version": "1.0.12",
"database": "ok"
}
Per-source data-freshness readiness report. Each registered source's latest period is compared against its publish-lag SLA and bucketed GREEN / YELLOW / RED. Heavier than /api/v1/health (one query per source); intended for dashboards and monitoring, not high-frequency probing.
Status values: ok or degraded. degraded when any source is blocking-stale or the freshness check itself errored.
curl https://decaystats.com/api/v1/status
Example response
{
"methodology_version": "2.0.4",
"basket_version": "1.0.12",
"data": {
"status": "ok",
"data_freshness": {
"summary": { "any_blocking": false, "any_warning": false, "checked": 11 },
"sources": [ { "source": "eia", "status": "GREEN", "days_old": 6, "cadence": "monthly", "max_lag_days": 60 } ],
"blocking_sources": []
}
}
}
Endpoints — Index (v1.0)
National-only surface. Retained for backward compatibility.
National-Average headline numbers — the public-citation surface.
Fields: as_of_month, long_run_decay_pct, rolling_12_month_decay_pct, long_run_half_life_years, rolling_12_month_half_life_years, long_run_first_month, long_run_last_month, coverage_months, erosion_index.
curl https://decaystats.com/api/v1/index/headline
Latest values for all 10 archetypes side-by-side. Returns an array; is_headline: true marks national_average.
curl https://decaystats.com/api/v1/index/archetypes
Full monthly time series for one archetype at the national level.
Path parameters. archetype: one of national_average, homeowner, renter, working_parent, retiree, income_lowest_quintile, income_second_quintile, income_middle_quintile, income_fourth_quintile, income_highest_quintile.
Observation shape. {period, erosion_index, decay_index_12m_pct, half_life_12m_years}.
curl https://decaystats.com/api/v1/index/retiree/series
Per-stratum latest price-relative table — machine-readable form of the DecayStats-vs-CPI comparison.
Per row. {stratum, first_period, last_period, latest_relative, coverage_months} anchored at 2000-01 = 1.0.
curl https://decaystats.com/api/v1/index/strata
Endpoints — Geographies
Index of all 52 published geographies, grouped by level (national, states).
Top-level fields. national, states, total_count, published_series_total, level_construction_note.
curl https://decaystats.com/api/v1/geographies
Endpoints — Archetype (v1.1)
Geography- and archetype-first routing per the v1.1 contract.
National headline for one archetype. Same fields as /index/headline plus archetype and geography: "US".
curl https://decaystats.com/api/v1/archetype/working_parent/headline
Full monthly time series for one archetype at the national level.
curl https://decaystats.com/api/v1/archetype/renter/series
Per-stratum X-ray decomposition. Each row: {stratum, weight, rate_pct, contribution_pp, coverage_months}. Contributions sum approximately to the headline long-run Decay Index.
curl https://decaystats.com/api/v1/archetype/retiree/decomposition
Endpoints — State (v1.1)
USPS 2-letter codes (50 states + DC). National CEX weights × state-specific prices, with documented per-stratum fallback when state-level data is unavailable.
Per-state coverage map. For each stratum: which source band drives the value (state | national), when state-specific data begins, and what share of basket weight is genuinely state-specific.
This endpoint is the §5.8 disclosure surface — readers can see how much of a state headline is genuinely state-resolved versus national-pass-through.
curl https://decaystats.com/api/v1/state/CA/coverage
State × archetype headline. Same shape as the archetype headline endpoint with geography set to the state code.
curl https://decaystats.com/api/v1/state/CA/archetype/retiree/headline
Full state × archetype monthly time series.
curl https://decaystats.com/api/v1/state/TX/archetype/working_parent/series
Per-stratum X-ray for (state, archetype). Same row shape as the archetype decomposition.
curl https://decaystats.com/api/v1/state/NY/archetype/renter/decomposition
Endpoints — Generic series (v1.1)
Flexible time-series query. Two modes depending on whether stratum is supplied.
Required query params. archetype (one of 10 slugs).
Optional. geography (default US), stratum (if present, returns per-stratum price relatives), basket_version, as_of.
curl "https://decaystats.com/api/v1/series?archetype=retiree&geography=FL"
curl "https://decaystats.com/api/v1/series?archetype=retiree&geography=FL&stratum=healthcare_premium"
Endpoints — Basket & Methodology
Locked basket definition. Per-archetype stratum weights, headline-archetype identifier, canonical stratum list, per-stratum source map.
curl https://decaystats.com/api/v1/basket
Methodology version + a short summary of the load-bearing pillars, with links to the canonical documents.
curl https://decaystats.com/api/v1/methodology
Versioning policy
URL versioning. All endpoints live under /api/v1/. Backward-incompatible changes get a new prefix (/api/v2/). The /v1/ surface continues to serve until announced sunset.
What counts as breaking (requires a new prefix):
- Removing an endpoint.
- Removing or renaming a field in a successful response.
- Changing the type of a field.
- Tightening enum values for an existing parameter.
- Changing the semantics of an existing field.
What is additive (same /v1/ prefix):
- Adding a new endpoint.
- Adding a new field to an existing response.
- Adding a new accepted enum value (e.g., a new archetype or geography).
- Adding a new optional query parameter.
Three independent version axes:
| Axis | Field | Bumps on |
|---|---|---|
| API contract | /v1/ URL prefix | Breaking changes |
| Methodology | methodology_version | Any change to how the index is computed |
| Basket | basket_version | Any change to the locked basket (items, weights, source-precedence) |