Static data API
TidyBank publishes approved catalog data as immutable static files. No API key is required.
Base URL: https://data.tidybank.net/
Registry and asset paths below are relative to that origin. Consumers should store the versioned asset ID and verify the published checksums rather than scraping the website.
Registry endpoints
| Endpoint | Purpose | JSON Schema |
|---|---|---|
api/catalog/index.json | First approved-asset index shard. Each shard contains at most 500 assets and declares its zero-based shard.index and total shard.of. Further shards are named index-1.json, index-2.json, and so on. | Download index.schema.json |
api/catalog/publications.json | Every publication and release represented in the committed catalog, with per-release asset counts. | Download publications.schema.json |
api/catalog/datasets.json | Approved assets as queryable datasets, including CSV and optional Parquet paths. | Download datasets.schema.json |
api/catalog/concepts.json | Reviewed/published ontology concepts, external mappings, value-scheme and hierarchy summaries, and approved asset-column bindings. An empty concepts array is a valid registry. | Download concepts.schema.json |
All registry paths point to files on data.tidybank.net; they are never duplicated under the website origin. Registry generation is deterministic and the committed integrity lock is checked in CI. concepts.json receives the same canonical-JSON SHA-256 lock treatment as the asset, publication, and dataset registries; only generated_at is excluded from canonical hashing where that field exists.
datasets.json derives table_name by replacing every / and - in the asset ID with _. For example, abs/australian-industry/2023-24/table-7 becomes abs_australian_industry_2023_24_table_7. Generation fails rather than publishing if two asset IDs produce the same SQL identifier. version is the release slug.
Discovery endpoints
These machine-readable documents are published on the website origin and generated from the same cached catalog projection as the static pages:
| Endpoint | Purpose |
|---|---|
/catalog.dcat.json | Approved assets serialized as a DCAT 3 JSON-LD dcat:Catalog. Every dcat:Dataset includes the recorded licence, agency publisher, data-origin distributions, media types, SHA-256 checksums, known temporal coverage, and committed topic themes. |
/sitemap.xml | Sitemap index for the deterministic home/docs, data hierarchy, topic, and concept section sitemaps. Latest aliases, 404, and internal stubs are excluded. |
/sitemaps/{pages,data,topics,concepts}.xml | Fixed sitemap partitions for public canonical pages, the complete data hierarchy, committed topic routes, and reviewed concept routes. Their union is checked against every built public canonical. |
/feed.atom | Atom feed of the 100 most recent approved decisions for assets that remain approved. Entry timestamps come from append-only approval-record content, never filesystem mtimes. |
/robots.txt | Crawler policy and the absolute sitemap-index URL. |
DCAT datasets are ordered by immutable asset ID, distributions preserve the recorded CSV/JSON/Parquet order, and themes are ordered by committed topic slug. The executable Zod contract in src/lib/site/dcat.ts is checked against the approved asset set during every build and in CI. A backwards-incompatible DCAT shape or meaning change requires a documented profile/version decision just as registry contract changes require a schema-version bump.
Atom entry IDs combine the immutable asset URL with the approval decision and its append-only decided_at value, so an unchanged decision retains the same identifier across builds. A later re-approval produces a separate Updated dataset entry. The feed-level updated value is the newest included decision timestamp; an empty feed uses the documented fixed epoch rather than a build-time timestamp. Every HTML page links the feed with rel="alternate".
The DCAT document, sitemap family, robots file, and Atom feed are deterministic projections rather than immutable versioned asset endpoints: their bytes may change when approved catalog or approval-record content changes. They do not carry the registry integrity lock or a self-checksum. Consumers that need byte integrity should follow the SHA-256 values on DCAT distributions or in each asset’s metadata.json; CI instead regenerates these discovery documents, validates their contracts and catalog reconciliation, and verifies byte-identical output for unchanged inputs.
Per-asset endpoints
Replace <asset-id> with the four-segment ID <publisher>/<publication>/<release>/<table>.
| Endpoint | Purpose | JSON Schema |
|---|---|---|
data/<asset-id>/metadata.json | Identity, provenance, license, distribution sizes, and distribution checksums. | Download metadata.schema.json |
data/<asset-id>/recipe.json | The reviewed RecipeV01 transformation. | Download recipe-v01.schema.json |
data/<asset-id>/schema.json | Tidy-table columns, types, and row count. | Download schema.schema.json |
data/<asset-id>/preview.json | Bounded preview rows. | Download preview.schema.json |
data/<asset-id>/semantics.json | Column roles and semantic bindings. | Download semantics.schema.json |
data/<asset-id>/report.json | Validation checks and outcomes. | Download report.schema.json |
data/<asset-id>/source.url.json | Recorded agency URL, source-workbook SHA-256, retrieval time, and availability. | Download source.url.schema.json |
data/<asset-id>/tidy.csv | UTF-8 CSV data. | Described by the asset’s schema.json. |
data/<asset-id>/tidy.json | JSON row data. | Described by the asset’s schema.json. |
data/<asset-id>/tidy.parquet | Parquet data when listed in metadata. | Described by the asset’s schema.json. |
data/<asset-id>/overlay.html | Human-review source overlay. | HTML, no JSON Schema. |
data/<asset-id>/reconstructed.html | Human-review reconstructed table. | HTML, no JSON Schema. |
Stability and immutability
A versioned release path such as data/abs/australian-industry/2023-24/table-7/tidy.parquet is immutable once published. Corrections that change data or its recipe receive a new versioned release or an explicitly recorded replacement; consumers must not expect bytes at a versioned URL to change silently.
Website routes of the form /data/<publisher>/<publication>/latest/<table> are mutable static HTML aliases. Each alias contains a canonical link, an immediate meta refresh, and a visible link to the latest approved versioned asset page; it does not promise an HTTP 3xx response or an API redirect. The target may move when a release is approved. Registries and reproducible analyses should use the canonical versioned asset ID, never a /latest/ alias.
Registry documents and per-asset manifest envelopes (metadata.json, schema.json, preview.json, semantics.json, report.json, and source.url.json) carry schema_version; backwards-incompatible field or meaning changes require a schema-version bump and a documented migration. recipe.json follows RecipeV01’s own version field. tidy.json is row data described by the asset’s schema.json, not a versioned manifest envelope. Additive fields follow the applicable contract’s version policy, and strict consumers should validate against the linked schema they support.
Checksums
metadata.json records sha256 and byte length for each generated distribution. source.url.json records the original workbook SHA-256. A checksum is written as sha256:<64 lowercase hexadecimal characters>. Verify downloaded bytes before processing or caching them. A source checksum mismatch means the agency workbook changed after ingest; it is an availability signal, not permission to accept unreviewed bytes.
License and attribution
The seeded ABS assets are published under Creative Commons Attribution 4.0 (CC-BY-4.0). Reusers must credit the Australian Bureau of Statistics, identify TidyBank’s transformation, link the licence, and indicate changes. License terms are per asset: always read metadata.json fields source.license.spdx_or_label and source.license.url before reuse. A future asset may carry different obligations.
Runnable example
This approved seeded asset is used by the site and test corpus:
abs/australian-industry/2023-24/table-7
Fetch and inspect its metadata and CSV:
BASE='https://data.tidybank.net/data/abs/australian-industry/2023-24/table-7'
curl --fail --location "$BASE/metadata.json" | python -m json.tool
curl --fail --location --output table-7.csv "$BASE/tidy.csv"
Read the same CSV with pandas:
python - <<'PY'
import pandas as pd
url = "https://data.tidybank.net/data/abs/australian-industry/2023-24/table-7/tidy.csv"
frame = pd.read_csv(url)
print(frame.head())
print(frame.shape)
PY
Query the Parquet distribution directly with DuckDB:
duckdb -c "INSTALL httpfs; LOAD httpfs; SELECT * FROM read_parquet('https://data.tidybank.net/data/abs/australian-industry/2023-24/table-7/tidy.parquet') LIMIT 5;"
For production use, fetch metadata.json, verify the selected distribution’s byte length and SHA-256, and retain the immutable asset ID plus the applicable contract version (schema_version, or RecipeV01 version) with derived results.