data-gov-catalog
Async Rust client for the data.gov Catalog API. Returns DCAT-US 3 metadata, cursor-paginated, no API key required.
The current data.gov backend. As of 2026 data.gov retired its CKAN Action API and replaced it with this purpose-built Catalog API. If you were previously calling
package_search/package_showagainstcatalog.data.gov, you want this crate (or the higher-leveldata-govwrapper). The legacydata-gov-ckancrate is retained for non-data.gov CKAN portals.
Requirements
- Rust 1.90+ (Rust 2024 edition)
- A Tokio runtime
Add to your project
[]
= "0.4"
= { = "1", = ["full"] }
Working inside this repository? data-gov-catalog = { path = "../data-gov-catalog" }.
Highlights
- ๐ Cursor-paginated full-text search with org / type / keyword / spatial filters
- ๐งพ DCAT-US 3 typed models (
Dataset,Distribution,Publisher,ContactPoint) - ๐๏ธ Organizations, keywords, locations, and harvest-record endpoints
- โ๏ธ Async via
reqwest+tokio; configurable TLS backend - ๐งช Wiremock-based unit tests + opt-in live integration tests
Quick start
use ;
use Arc;
async
Cursor-based pagination
The Catalog API has no random-access offset. The SearchResponse carries
an after cursor when more pages exist; pass it back unchanged on the
next call to advance one page:
# use ;
# use Arc;
# async
Filtering
use SearchParams;
// Datasets published by EPA, sorted by harvest date.
let params = new
.org_slug
.sort
.per_page;
// Federal-agency datasets tagged "air-quality".
let params = new
.org_type
.keyword;
// Spatial: datasets whose footprint intersects a GeoJSON geometry.
let params = new
.spatial_geometry
.spatial_within;
Single-dataset lookup
# use CatalogClient;
# async
API surface
| Method | Endpoint | Returns |
|---|---|---|
search(params) |
GET /search |
SearchResponse |
dataset_by_slug(slug) |
GET /search?slug=โฆ&per_page=1 |
Option<SearchHit> |
organizations() |
GET /api/organizations |
OrganizationsResponse |
keywords(size, min_count) |
GET /api/keywords |
KeywordsResponse |
locations_search(q, size) |
GET /api/locations/search |
LocationsResponse |
location_geometry(id) |
GET /api/location/{id} |
serde_json::Value (GeoJSON) |
harvest_record(id) |
GET /harvest_record/{id} |
HarvestRecord |
harvest_record_raw(id) |
GET /harvest_record/{id}/raw |
serde_json::Value |
harvest_record_transformed(id) |
GET /harvest_record/{id}/transformed |
Dataset (DCAT-US 3) |
Errors are surfaced through [CatalogError]:
RequestErrorโ network, DNS, TLS, or HTTP-protocol failureParseErrorโ response body was not valid JSON for the expected shapeApiError { status, message }โ the server returned a non-2xx status
Configuration
use ;
use Arc;
use Duration;
let http = builder
.timeout
.build?;
let config = Configuration ;
let client = new;
# Ok::
CatalogClient holds an Arc<Configuration> and is cheap to clone โ share
one instance across tasks rather than building a new client per request.
Cargo features
| Feature | Default | Effect |
|---|---|---|
native-tls |
yes | Use the platform TLS stack (reqwest/native-tls). |
rustls-tls |
no | Use rustls instead (reqwest/rustls). |
To use rustls:
[]
= { = "0.4", = false, = ["rustls-tls"] }
Development
The wiremock fixture tests live in tests/client_tests.rs and use captured
responses under tests/fixtures/. The live-network suite in
tests/integration_tests.rs is #[ignore]'d so it stays out of the
default cargo test run.
Higher-level wrappers
If you want download helpers, a CLI, or an MCP server on top of this client, look at the sibling crates:
data-govโ high-level client +data-govCLIdata-gov-mcp-serverโ MCP tools for AI agents
Disclaimer & license
This is an independent project and is not affiliated with data.gov or any government agency. For authoritative information, refer to the official data.gov portal.
Licensed under the Apache License 2.0.