gov-uk-sdk-core 0.1.0

Shared HTTP client, auth, errors, and content negotiation for GOV.UK / Companies House SDK crates.
Documentation

gov-uk-rs-sdk

Rust workspace for Companies House and related GOV.UK HTTP APIs.

  • gov-uk-rs-sdk (this repo’s root src/) — published umbrella crate with a harness module (ApiResponse, ApiError, ApiRequest, into_api_result), prelude, and examples.
  • crates/gov-uk-sdk-core — shared reqwest client, auth, rate limiting, negotiation, errors.
  • crates/gov-uk-ch-* — thin product crates (Public Data, Document stub, …).

Harness (root src/harness)

Type Role
ApiResponse<T> Success envelope: body + Content-Type / CH-Expiry-Date (NegotiatedMeta)
ApiError Alias of SdkError
ApiRequest Chaining wrapper around SdkRequest + send_json_api / send_empty_api
into_api_result Maps SdkResult<NegotiatedResponse<T>>ApiResult<ApiResponse<T>>

Low-level behaviour stays in gov-uk-sdk-core; the harness only composes types for one import path.

Crates

Path Package Role
src/ (root [package]) gov-uk-rs-sdk Umbrella + harness + prelude
crates/gov-uk-sdk-core gov-uk-sdk-core HTTP stack, auth, limits, negotiation
crates/gov-uk-ch-public-data gov-uk-ch-public-data Public Data API
crates/gov-uk-ch-document gov-uk-ch-document Document API (stub)

Usage

From crates.io (after publish):

[dependencies]

gov-uk-rs-sdk = { version = "0.1", features = ["ch-public-data"] }

tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Local path (workspace root):

gov-uk-rs-sdk = { path = ".", features = ["ch-public-data"] }

Configuration (.env)

  1. Copy .env.example to .env in the repo root.
  2. Set COMPANIES_HOUSE_API_KEY (from the Developer Hub).
  3. .env is gitignored — never commit real keys. The committed .env.example documents variables only.

Examples and the ignored integration test call dotenvy::dotenv() so a local .env is picked up automatically when you run from the workspace root.

Do not commit API keys. Prefer .env locally, CI secrets, or a vault in production.

use gov_uk_rs_sdk::harness::{into_api_result, ApiRequest};
use gov_uk_rs_sdk::prelude::*;
use std::env;

#[tokio::main]
async fn main() -> Result<(), ApiError> {
    let key = env::var("COMPANIES_HOUSE_API_KEY").expect("COMPANIES_HOUSE_API_KEY");
    let client = SdkClient::builder(Auth::ApiKey { key })
        .build()
        .expect("client build");

    let profile = into_api_result(get_company_profile(&client, "00000006").await)?;
    println!("{:?}", profile.body().company_name);

    let typed = ApiRequest::get(&client, "company/00000006")?
        .accept_mime(COMPANY_PROFILE_ACCEPT_LATEST)
        .send_json_api::<CompanyProfile>()
        .await?;
    println!("{:?}", typed.body().company_number);

    let search = into_api_result(
        search_companies(&client, &SearchCompaniesQuery { q: "treasure" }).await,
    )?;
    println!("hits: {}", search.body().items.len());

    Ok(())
}

Features (gov-uk-rs-sdk)

  • ch-public-data (default) — Public Data API.
  • ch-document — Document API stub.
  • full — all product crates.

Thin integration (core + one product only)

gov-uk-sdk-core = "0.1"

gov-uk-ch-public-data = "0.1"

Examples

set COMPANIES_HOUSE_API_KEY=your_key

cargo run -p gov-uk-rs-sdk --example company_profile

cargo run -p gov-uk-rs-sdk --example search_companies

Tests

cargo test --workspace

Live Companies House call (ignored by default):

set COMPANIES_HOUSE_API_KEY=your_key

cargo test -p gov-uk-rs-sdk --test live_public_data -- --ignored

See CHANGELOG.md for release notes.

Publishing to crates.io

Publish in dependency order (all from this repo root):

  1. cargo publish -p gov-uk-sdk-core
  2. cargo publish -p gov-uk-ch-document
  3. cargo publish -p gov-uk-ch-public-data
  4. cargo publish -p gov-uk-rs-sdk

Why step 2 is required: gov-uk-ch-document is an optional feature dependency on the umbrella, but Cargo still resolves every [dependencies] entry against crates.io when you package gov-uk-rs-sdk. If gov-uk-ch-document is not published yet, cargo publish -p gov-uk-rs-sdk fails with no matching package named gov-uk-ch-document. Publish the leaf crates (2 and 3) before the umbrella (4).

Workspace [workspace.dependencies] already sets compatible version + path for internal crates. After gov-uk-sdk-core is on crates.io, downstream publishes resolve it by version.

Dry run (the umbrella dry-run only succeeds after steps 1–3 have been published, or use --dry-run per crate after each real publish):

cargo publish -p gov-uk-sdk-core --dry-run

cargo publish -p gov-uk-ch-document --dry-run

cargo publish -p gov-uk-ch-public-data --dry-run

cargo publish -p gov-uk-rs-sdk --dry-run

Companies House notes

  • Auth: HTTP Basic — username = API key, password empty. OAuth uses Auth::Bearer { token }.
  • Rate limits: Up to 600 requests / 5 minutes per application; 429 when exceeded. Client-side throttle is on by default — .enable_companies_house_rate_limit(false) to disable. Avoid tight retry loops; respect Retry-After. Attempts to bypass limits can result in bans.
  • Versioning: Per-resource Accept / Content-Type MIME + version=; 406 / 410 / CH-Expiry-Date — see core types and developer docs.

Adding a new API product crate

  1. Add crates/gov-uk-ch-<name>/ depending only on gov-uk-sdk-core.
  2. Register it in root [workspace.members] and [workspace.dependencies] with version + path.
  3. Add optional dependency + feature on root gov-uk-rs-sdk and extend prelude.

License

MIT — see LICENSE.