data-gov-ckan 0.4.0

Client for Data.Gov CKAN
Documentation

data-gov-ckan

Async Rust client for CKAN APIs. Typed models, ergonomic helpers, works with any CKAN-compatible portal.

License: Apache 2.0

⚠️ data.gov no longer uses CKAN

As of 2026 the data.gov catalog is served by a purpose-built Catalog API — see the 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
rustup toolchain install stable
rustup default stable

Install / depend

Use the published crate from crates.io:

[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

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

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:

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

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 portal.

Licensed under the Apache License 2.0.