Discovery¶
The API is self-describing: everything you need to query a dataset — its endpoint, columns, types, row count, even a sample row — is available at runtime. Build against discovery and your integration keeps working as datasets are added.
List datasets¶
Standard paginated envelope of dataset summaries: slug, domain, title,
description, update_frequency, source organization, updated_at, and endpoint —
the serving path, so you can go straight from the list to the data without building URLs.
?domain= narrows the list to one domain; an unknown domain is a 422 listing the valid
ones. Like the data endpoints, the list is strict: any other unrecognized parameter is a
422 (for full-text search use /v1/search?q=).
Inspect one dataset¶
The detail response adds everything a client needs:
| Field | Meaning |
|---|---|
endpoint |
The serving path — /v1/transport/vehicle_registry |
export_endpoint |
The bulk export path |
available_filters |
Columns you may filter on |
sortable_fields / selectable_fields |
Columns valid in ?sort= / ?fields= |
row_schema |
Column → type map ({"county": "string", "vehicle_count": "integer", ...}) |
row_count |
Current number of rows |
sample |
One real row, so you can see actual values |
latest_ingestion |
Provenance of the newest successful ingestion run |
latest_ingestion is the full provenance record:
{
"version": 3,
"source_url": "https://data.gov.ro/dataset/.../parc-auto-la-31.12.2023.csv",
"source_file": "parc-auto-la-31.12.2023.csv",
"checksum": "a193925c0d27...",
"pipeline_version": "0.1.0+91b1917980c5",
"rows_imported": 382667,
"rows_failed": 0,
"imported_at": "2026-07-20T18:55:12Z",
"duration_ms": 6520,
"rows_per_sec": 95666
}
Use version / imported_at to detect refreshes,
and source_url + checksum when you need to cite or audit exactly which upstream file
the rows came from.
Generic client pattern¶
Discovery makes a dataset-agnostic client trivial:
def fetch(client: httpx.Client, dataset_id: str, **filters) -> list[dict]:
detail = client.get(f"/v1/datasets/{dataset_id}").json()
unknown = set(filters) - set(detail["available_filters"])
if unknown:
raise ValueError(f"{dataset_id} has no columns {unknown}")
return client.get(detail["endpoint"], params=filters).json()["data"]
rows = fetch(client, "physicians", county="CLUJ")
async function fetchDataset(datasetId, filters = {}) {
const headers = { Authorization: `Bearer ${API_KEY}` };
const detail = await (
await fetch(`${BASE}/v1/datasets/${datasetId}`, { headers })
).json();
const params = new URLSearchParams(filters);
const page = await (
await fetch(`${BASE}${detail.endpoint}?${params}`, { headers })
).json();
return page.items;
}
OpenAPI¶
The same information is available statically: /openapi.json (and Swagger UI at /docs)
documents every dataset endpoint with its real per-column response schema — generated from
the same configuration that drives the ingestion pipeline. Use it for codegen or
Postman import.