# data-gov-ckan
Async Rust client for CKAN APIs. Typed models, ergonomic helpers, works with any CKAN-compatible portal.
[](../LICENSE)
> ## โ ๏ธ data.gov no longer uses CKAN
>
> As of 2026 the data.gov catalog is served by a purpose-built
> [Catalog API](https://resources.data.gov/catalog-api/) โ see the
> [`data-gov-catalog`](../data-gov-catalog/) crate in this workspace.
>
> **This crate is retained, not deprecated.** CKAN still powers many other
> open-data portals (European, state, municipal, and university instances) and
> the client works unchanged against any compliant CKAN deployment โ just
> point `Configuration::base_path` at your target host.
>
> **Maintenance status.** Active workspace development now focuses on the
> Catalog API. `data-gov-ckan` will continue to receive bug fixes and security
> patches, but new features are unlikely unless a contributor steps up.
> Issues and PRs are welcome.
## Requirements
- Rust **1.90+** (Rust 2024 edition)
- Cargo and git
```bash
rustup toolchain install stable
rustup default stable
```
## Install / depend
Use the published crate from crates.io:
```toml
[dependencies]
data-gov-ckan = "0.4"
tokio = { version = "1", features = ["full"] }
```
Working inside this repository? Point to the local path instead: `data-gov-ckan = { path = "../data-gov-ckan" }`. If you need the bleeding edge between releases, swap in the git dependency form: `data-gov-ckan = { git = "https://github.com/dspadea/data-gov-rs", package = "data-gov-ckan" }`.
## Highlights
- ๐ Coverage of the common CKAN `action/*` endpoints (`package_search`,
`package_show`, `organization_list`, `group_list`, `tag_list`, `user_list`,
and the matching autocomplete helpers)
- โ
Strongly typed models generated from the official OpenAPI spec
- ๐ Configurable base URL, authentication, and user-agent handling
- โ๏ธ Async support via `reqwest` + `tokio`
- ๐งช Wiremock-based unit tests plus optional live integration tests
## Quick start
```rust
use data_gov_ckan::{CkanClient, Configuration};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = CkanClient::new(Arc::new(Configuration::default()));
let results = client.package_search(Some("climate"), Some(10), Some(0), None).await?;
println!("Found {} datasets", results.count.unwrap_or(0));
if let Some(datasets) = results.results {
for dataset in datasets.iter().take(3) {
let title = dataset.title.as_deref().unwrap_or(&dataset.name);
println!("โข {title}");
}
}
Ok(())
}
```
### Custom configuration & auth
```rust
use data_gov_ckan::{ApiKey, CkanClient, Configuration};
use std::sync::Arc;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Configuration {
base_path: "https://demo.ckan.org/api/3".to_string(),
api_key: Some(ApiKey {
prefix: None,
key: "your-api-key".to_string(),
}),
..Configuration::default()
};
let client = CkanClient::new(Arc::new(config));
let dataset = client.package_show("example-dataset").await?;
println!("Dataset: {}", dataset.title.as_deref().unwrap_or(&dataset.name));
Ok(())
}
```
Filtering with Solr-style query strings:
```rust
let fq = r#"organization:"gsa-gov" AND res_format:"CSV""#;
let results = client.package_search(Some("budget"), Some(20), Some(0), Some(fq)).await?;
```
### Solr query syntax
The `q` (full-text) and `fq` (filter query) parameters are passed directly to
CKAN's Solr-backed `package_search` endpoint. Typical patterns:
- Wildcards: `q=climat*`
- Phrase search: `q="air quality"`
- Fielded filters: `fq=organization:epa-gov AND res_format:CSV`
- Range queries: `fq=metadata_modified:[2020-01-01T00:00:00Z TO NOW]`
Use `fq` for structured filtering and `q` for free-text searches. When building
`fq` strings programmatically, quote values containing spaces to ensure correct
Solr parsing.
## API surface
Core methods include `package_search`, `package_show`, `organization_list`, `group_list`, `tag_list`, and `user_list`. Autocomplete helpers cover datasets, organisations, groups, tags, and users. Errors are surfaced through the `CkanError` enum with variants for request, parse, and API failures.
## Development
```bash
git clone https://github.com/dspadea/data-gov-rs.git
cd data-gov-rs/data-gov-ckan
cargo build
cargo test # unit + wiremock tests; live integration tests are #[ignore]'d
cargo run --example debug_search
cargo run --example raw_response
```
Live-network integration tests are marked `#[ignore]` and target a CKAN
instance you configure (legacy data.gov fixtures are kept for historical
reference). Run them explicitly with `cargo test -- --ignored`.
## Authentication options
- API keys: set `Configuration.api_key = Some(ApiKey { .. })`
- Basic auth: populate `Configuration.basic_auth`
- Custom headers: configure the inner `reqwest::Client` before passing the configuration into `CkanClient`
Reuse the same `CkanClient` for multiple requests to benefit from connection pooling. Combine async calls with `tokio::try_join!` for improved throughput.
## 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](https://www.data.gov/) portal.
Licensed under the [Apache License 2.0](LICENSE).