> ## Documentation Index
> Fetch the complete documentation index at: https://docs.incident.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Rust SDK

> Call the incident.io API from async Rust with typed requests and responses for every endpoint.

The Rust SDK gives you a typed, async client for the whole incident.io API. There's a function for every endpoint and a type for every request and response, all generated from our OpenAPI specification. Forgetting a required parameter is a compile error, and the types are shaped so that the API adding a field or an enum value never is.

It requires Rust 1.88 or later and an async runtime. The examples below use `tokio`, but any runtime works, since the client is built on `reqwest`.

## Installing

```bash theme={null}
cargo add incident-io tokio --features tokio/macros,tokio/rt-multi-thread
```

## Your first request

You'll need an API key from **Settings > API keys** (see [API keys](/admin/api-keys)). Then:

```rust theme={null}
use incident_io::apis::{configuration::Configuration, incidents_v2_api};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut config = Configuration::new();
    config.bearer_access_token = Some("my-api-key".to_owned());

    let params = incidents_v2_api::IncidentsV2ListParams::new().set_page_size(25);
    let result = incidents_v2_api::incidents_v2_list(&config, params).await?;

    for incident in result.incidents {
        println!("{} {}", incident.reference, incident.name);
    }

    Ok(())
}
```

## Parameters and payloads

Every endpoint is an async function that takes a `&Configuration` and a params struct, even endpoints with no parameters today. That's deliberate: when the API adds a parameter, it becomes a new field on a struct you already use, rather than a change to the function's signature.

`new()` takes the endpoint's required parameters. Optional ones are chainable `set_*` methods, which take the value directly rather than `Some(value)`:

```rust theme={null}
// No required parameters.
let params = incidents_v2_api::IncidentsV2ListParams::new()
    .set_page_size(25)
    .set_sort_by("created_at_newest_first");

// One required path parameter.
let params = incidents_v2_api::IncidentsV2ShowParams::new("01ABC...");
```

Request payloads work the same way:

```rust theme={null}
use incident_io::models::incidents_create_payload_v2::Visibility;
use incident_io::models::IncidentsCreatePayloadV2;

let body = IncidentsCreatePayloadV2::new(idempotency_key, Visibility::Public)
    .set_name("Checkout is down");

let params = incidents_v2_api::IncidentsV2CreateParams::new(body);
```

Every generated type is `#[non_exhaustive]`, so you can't build one with a struct literal. Use `new()` and the `set_*` methods instead. This is what lets us add fields to the API without breaking your build.

## Pagination

List endpoints are cursor-paginated. Read the next cursor from `pagination_meta.after` and pass it back:

```rust theme={null}
let mut after: Option<String> = None;

loop {
    let mut params = incidents_v2_api::IncidentsV2ListParams::new().set_page_size(100);
    if let Some(cursor) = &after {
        params = params.set_after(cursor);
    }

    let page = incidents_v2_api::incidents_v2_list(&config, params).await?;
    for incident in &page.incidents {
        println!("{} {}", incident.reference, incident.name);
    }

    match page.pagination_meta.and_then(|meta| meta.after) {
        Some(cursor) => after = Some(cursor),
        None => break,
    }
}
```

## Filtering

List endpoints filter on a map of operator to values, sent as `created_at[gte]=2024-05-01`. The operators each field accepts are in its docs, and are commonly `one_of`, `not_in`, `gte`, and `lte`.

```rust theme={null}
use std::collections::HashMap;

let mut created_at = HashMap::new();
created_at.insert("gte".to_owned(), vec!["2024-05-01".to_owned()]);

let params = incidents_v2_api::IncidentsV2ListParams::new().set_created_at(created_at);
```

## Errors

Every endpoint returns `Result<T, Error<SomethingError>>`, where the inner enum has a variant per documented status code. Documenting another status code is a backwards-compatible change for us, so these enums need a wildcard arm:

```rust theme={null}
use incident_io::apis::{Error, incidents_v2_api::IncidentsV2ListError};

match incidents_v2_api::incidents_v2_list(&config, params).await {
    Ok(result) => println!("{} incidents", result.incidents.len()),
    Err(Error::ResponseError(response)) => match response.entity {
        Some(IncidentsV2ListError::Status401(_)) => println!("bad API key"),
        Some(IncidentsV2ListError::Status429(_)) => println!("rate limited"),
        _ => println!("HTTP {}: {}", response.status, response.content),
    },
    Err(other) => println!("request failed: {other}"),
}
```

Enums generated from the schema work the same way. Each has an `Unknown(String)` variant for values your version doesn't know about, and a wildcard arm is required.

## Configuration

Every field on `Configuration` is public, so change what you need:

```rust theme={null}
use std::time::Duration;

let mut config = Configuration::new();
config.bearer_access_token = Some("my-api-key".to_owned());
config.user_agent = Some("my-app/1.0.0".to_owned()); // identify your integration
config.client = reqwest::Client::builder()
    .timeout(Duration::from_secs(30))
    .build()?;
```

There's no default request timeout, which is reqwest's behaviour. Set one unless you have a reason not to.

The client makes a single attempt per request and doesn't retry. When you hit the [rate limit](/api-reference/introduction#rate-limits), the `429` response body tells you when to try again. The [README](https://github.com/incident-io/sdk-rust#retries) shows how to read it.

TLS uses `rustls` by default. To use OpenSSL instead, turn off default features and enable `native-tls`.

## Deprecated endpoints

Endpoints we've deprecated stay available and carry `#[deprecated]`, so rustc warns at the call site. Don't go by the version in the name: some `v2` endpoints are deprecated too.

## Versioning

The SDK is kept up to date with the API automatically. Additions to the API are minor versions. A change that would break your code, like a removed field, is released as a new major version, and its release notes list what changed.

## Resources

<CardGroup cols={2}>
  <Card title="crates.io" icon="rust" href="https://crates.io/crates/incident-io">
    The `incident-io` crate and its versions.
  </Card>

  <Card title="docs.rs" icon="book" href="https://docs.rs/incident-io">
    Every type and function, with their docs.
  </Card>

  <Card title="GitHub" icon="github" href="https://github.com/incident-io/sdk-rust">
    Source, README, and issues for the Rust SDK.
  </Card>

  <Card title="All SDKs" icon="cubes" href="/integrations/sdks">
    Clients for Go, TypeScript, Python, Ruby, PHP, and .NET.
  </Card>
</CardGroup>
