# Rust SDK (/sdk/rust)



The Rust SDK (`zumik-sdk`) is a thin async client over `reqwest`. It covers the core create/append
flow and diagnostics; the wider surface is reachable through the [HTTP API](/api-reference/introduction)
directly.

## Add the dependency [#add-the-dependency]

```toml
[dependencies]
zumik-sdk = "0.1.0"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
serde_json = "1"
```

## Authenticate [#authenticate]

```rust
use zumik_sdk::Client;

let client = Client::new("zk_live_...")?;
// or point at another host:
// let client = Client::with_base_url("https://api.zumik.ai", "zk_live_...")?;
```

The key is an explicit argument; the base URL defaults to `https://api.zumik.ai`. The bearer and
JSON content-type headers are set on the underlying `reqwest::Client`.

## Usage [#usage]

Every method is `async` and returns `anyhow::Result<serde_json::Value>`.

```rust
use zumik_sdk::Client;
use serde_json::json;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let client = Client::new("zk_live_...")?;

    let art = client.create_artifact("policy", "Run the linter before every commit.").await?;
    let bundle = client.create_bundle(json!({
        "items": [{ "artifact_id": art["id"], "role": "system" }]
    })).await?;
    let session = client.create_session(vec![bundle["id"].as_str().unwrap().to_string()]).await?;

    // Append an event with compare-and-swap (the body carries the CAS guards).
    let branch_id = session["default_branch_id"].as_str().unwrap();
    let event = client.append_event(
        session["id"].as_str().unwrap(),
        branch_id,
        json!({
            "expected_version": 0,
            "expected_head_event_id": null,
            "event": { "event_type": "user_message", "payload_ref": art["id"] }
        }),
    ).await?;

    client.create_snapshot(
        session["id"].as_str().unwrap(),
        branch_id,
        vec![
            art["id"].as_str().unwrap().to_string(),
            event["id"].as_str().unwrap().to_string(),
        ],
    ).await?;

    let resp = client.create_response("code.balanced", "Review the latest patch.").await?;
    println!("{}", resp["id"]);
    Ok(())
}
```

## Methods [#methods]

| Method                                                                      | Endpoint               |
| --------------------------------------------------------------------------- | ---------------------- |
| `create_response<T: Serialize>(model: &str, input: T)`                      | `POST /v1/responses`   |
| `create_artifact(artifact_type: &str, content: &str)`                       | `POST /v2/artifacts`   |
| `create_bundle(items: Value)`                                               | `POST /v2/bundles`     |
| `create_session(base_bundle_ids: Vec<String>)`                              | `POST /v2/sessions`    |
| `append_event(session_id: &str, branch_id: &str, body: Value)`              | `POST .../events`      |
| `create_snapshot(session_id: &str, branch_id: &str, manifest: Vec<String>)` | `POST .../snapshots`   |
| `run_diagnostic(traces: Value)`                                             | `POST /v2/diagnostics` |

## Error handling [#error-handling]

Errors surface as `anyhow::Error`. On any status ≥ 400 the method returns
`Err(anyhow!("zumik api error {status}: {payload}"))` - match on the status or parse the payload. The
SDK does not stream or retry.

<Note>
  This SDK does not yet expose native `/v2` responses, get/delete, purge, usage, or credentials. For
  those, send requests against the [HTTP API](/api-reference/introduction) with your own `reqwest::Client`.
</Note>
