context69-sdk 0.4.0

Async Rust SDK for the Context69 HTTP API.
Documentation

context69-sdk

Async Rust SDK for the Context69 HTTP API.

context69-sdk is a PAT-only client. Initialize it with a personal access token that starts with ctx_pat_, then call the scoped HTTP APIs directly.

PAT-only initialization

use context69_sdk::Context69Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Context69Client::builder()
        .base_url("http://127.0.0.1:8096")?
        .with_personal_access_token("ctx_pat_example_token")?
        .build()?;

    let me = client.me().await?;
    println!("hello {}", me.user.login_name);
    Ok(())
}

The builder rejects empty tokens and non-PAT tokens. Protected APIs return Error::AuthenticationRequired if no PAT is configured.

Workspace example

use context69_sdk::{
    Context69Client,
    contracts::{CreateGroupRequest, CreateProjectRequest, GroupKind, Visibility},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Context69Client::builder()
        .base_url("http://127.0.0.1:8096")?
        .with_personal_access_token("ctx_pat_example_token")?
        .build()?;

    client
        .workspace()
        .create_group(&CreateGroupRequest {
            parent_group_key: None,
            group_key: "ops".to_string(),
            name: "Operations".to_string(),
            visibility: Visibility::Private,
            kind: Some(GroupKind::Shared),
        })
        .await?;

    client
        .workspace()
        .create_project(
            "ops",
            &CreateProjectRequest {
                project_key: "runbooks".to_string(),
                name: "Runbooks".to_string(),
                visibility: Visibility::Private,
            },
        )
        .await?;

    Ok(())
}

Source and library example

use chrono::NaiveDate;
use context69_sdk::{
    Context69Client,
    contracts::{
        CreateTextRequest, LibraryTextContentFormat, SourceConfigInput,
        UpsertLibraryTextRequest,
    },
};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Context69Client::builder()
        .base_url("http://127.0.0.1:8096")?
        .with_personal_access_token("ctx_pat_example_token")?
        .build()?;

    client
        .sources()
        .create_project_source(
            "ops",
            "runbooks",
            &SourceConfigInput {
                source_key: "alerts".to_string(),
                display_name: Some("Alerts".to_string()),
                description: Some("Operational alerts".to_string()),
                example_queries: vec!["recent paging incidents".to_string()],
                connection: "warehouse".to_string(),
                database_url: None,
                sync_strategy: "incremental".to_string(),
                connector_type: "postgres_sql".to_string(),
                base_query: "select * from alerts".to_string(),
                batch_size: 500,
                visibility: None,
            },
        )
        .await?;

    client
        .library()
        .create_library_text(&CreateTextRequest {
            folder_id: None,
            title: "Global Runbook".to_string(),
            content: "# Step 1\n\nFollow the checklist.".to_string(),
            content_format: LibraryTextContentFormat::Markdown,
            source_uri: Some("https://example.test/runbooks/global".to_string()),
            summary: Some("Global reference".to_string()),
        })
        .await?;

    client
        .library()
        .upsert_project_library_text(
            "ops",
            "runbooks",
            &UpsertLibraryTextRequest {
                external_id: "incident-42".to_string(),
                folder_id: None,
                title: "Incident 42".to_string(),
                content: "full text".to_string(),
                content_format: LibraryTextContentFormat::PlainText,
                source_uri: Some("https://example.test/incidents/42".to_string()),
                summary: Some("Postmortem".to_string()),
                published_at: NaiveDate::from_ymd_opt(2026, 7, 1),
                metadata_json: json!({"kind":"postmortem"}),
            },
        )
        .await?;

    // Multipart upload already supports Markdown files as long as the uploaded
    // part uses a `.md` filename or `text/markdown` content type.

    Ok(())
}

Settings example

use context69_sdk::Context69Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Context69Client::builder()
        .base_url("http://127.0.0.1:8096")?
        .with_personal_access_token("ctx_pat_example_token")?
        .build()?;

    let docling = client.settings().get_docling_settings().await?;
    println!("docling configured: {}", docling.configured);
    Ok(())
}

API coverage

  • client.workspace(): user directory, groups, projects, group members, project members
  • client.sources(): source connections, global sources, project sources, sync
  • client.library(): global tree/folder/file/job APIs, global library text, project library tree/folder/file/job APIs, project library text, multipart uploads
  • client.settings(): runtime, provider accounts, docling, search settings
  • client.search(): search and document lookup
  • Root client: me(), healthz()

Scope requirements

PATs must include the scopes required by the APIs you call:

  • workspace: user directory, groups, projects, memberships
  • sources: source connections, global sources, project sources, sync
  • library: global library, project library, library text APIs
  • settings: runtime settings, provider accounts, docling settings, search settings
  • search: search and document APIs

Breaking changes

  • with_access_token() was replaced by with_personal_access_token()
  • login(), refresh(), and logout() were removed from the main client
  • 401 Unauthorized responses are returned directly; the SDK no longer retries with refresh-cookie logic
  • JWT-only APIs are intentionally excluded from this client, including login/refresh/logout, PAT management, and admin-user APIs
  • Flat methods like client.create_group(...) were replaced by grouped APIs such as client.workspace().create_group(...)