Strait Docs
SDKs

Official Rust SDK for Strait with async/await, builder pattern, and full API coverage.

The Rust SDK (strait) provides a type-safe, async-first interface with full API coverage across 5 modules.

Installation

Add to your Cargo.toml:

[dependencies]
strait = "0.1"
tokio = { version = "1", features = ["full"] }

Client Creation

use strait::Client;

let client = Client::from_file(None).await?;

See Configuration for strait.json schema and options.

You can specify a custom directory or explicit path:

// Custom directory
let client = Client::from_file(Some(
    strait::ConfigFileOptions::builder()
        .dir("/path/to/project")
        .build()
)).await?;

// Explicit path
let client = Client::from_file(Some(
    strait::ConfigFileOptions::builder()
        .path("/path/to/config.json")
        .build()
)).await?;

From environment variables

// Reads STRAIT_BASE_URL, STRAIT_API_KEY, STRAIT_AUTH_TYPE, STRAIT_TIMEOUT_MS
let client = Client::from_env()?;

Inline with builder

let client = Client::builder()
    .base_url("https://api.strait.dev")
    .api_key("sk_live_...")
    .timeout_ms(5000)
    .build()?;

Client options

OptionDescription
.base_url(url)API base URL (trailing slashes stripped)
.bearer_token(token)Bearer token auth
.api_key(key)API key auth
.run_token(token)Run token auth
.auth(auth)Set auth mode directly
.default_headers(h)Headers sent with every request
.timeout_ms(ms)Timeout in milliseconds (default: 30000)
.http_client(client)Custom reqwest::Client
.middleware(mw)Request/response/error hooks

Calling Operations

Operations are organized into service modules under strait::operations:

use strait::Client;
use strait::operations::Jobs;

let client = Client::from_file(None).await?;
let jobs = Jobs::new(&client);

// List jobs
let list = jobs.list(Some(
    &[("project_id", "proj_1")]
)).await?;

// Create a job
let created = jobs.create(serde_json::json!({
    "name": "Sync Inventory",
    "slug": "sync-inventory",
    "project_id": "proj_1",
    "endpoint_url": "https://worker.example.com/run",
})).await?;

// Trigger a job
let run = jobs.trigger("job_abc", serde_json::json!({
    "payload": { "sku": "ABC-123" },
})).await?;

Available services

Jobs, Runs, Workflows, WorkflowRuns, Deployments, Environments, Secrets, ApiKeys, Webhooks, EventTriggers, EventSources, BatchOperations, Stats, Analytics, LogDrains, SdkRuns, Rbac, JobGroups, Health

Authoring DSL

Defining jobs

use strait::authoring::{self, JobOptions, RunContext};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Payload {
    sku: String,
}

let job = authoring::define_job(JobOptions {
    name: "Sync Inventory",
    slug: "sync-inventory",
    endpoint_url: "https://worker.dev/jobs/sync",
    project_id: "proj_1",
    run: |payload: Payload, ctx: RunContext| async move {
        sync_inventory(&payload.sku).await
    },
})?;

job.register(&client, None).await?;
job.trigger(&client, Payload { sku: "ABC-123".into() }).await?;

Defining workflows

use strait::authoring::{self, WorkflowOptions, Step};

let wf = authoring::define_workflow(WorkflowOptions {
    name: "Order Pipeline",
    slug: "order-pipeline",
    project_id: "proj_1",
    steps: vec![
        Step::job("validate", "job_validate"),
        Step::job("charge", "job_charge").depends_on(&["validate"]),
        Step::approval("review").depends_on(&["charge"]),
    ],
})?;
// DAG is validated at definition time

Composition Helpers

use strait::composition;

// Retry with backoff
let result = composition::with_retry(
    || async { call_api().await },
    composition::RetryOptions { attempts: 5, delay_ms: 100 },
).await?;

// Paginate
let mut stream = composition::paginate(|cursor| async move {
    list_fn(cursor).await
});
while let Some(item) = stream.next().await {
    // process item
}

// Wait for run
let run = composition::wait_for_run(
    |id| async move { get_run(id).await },
    |run| get_status(run),
    "run_123",
    None,
).await?;

FSM State Machines

use strait::fsm;

fsm::can_transition_run(fsm::RunState::Executing, fsm::RunEvent::Complete);  // true
fsm::is_terminal_run_status(fsm::RunState::Completed);                        // true

Middleware

let client = Client::builder()
    .base_url("https://api.strait.dev")
    .api_key("sk_live_...")
    .middleware(strait::Middleware {
        on_request: Some(Box::new(|ctx| {
            println!("{} {}", ctx.method, ctx.url);
        })),
        on_response: Some(Box::new(|ctx| {
            println!("{} {}ms", ctx.status, ctx.duration_ms);
        })),
        on_error: Some(Box::new(|ctx| {
            eprintln!("error: {}", ctx.error);
        })),
    })
    .build()?;

Custom HTTP Client

Pass a custom reqwest::Client to the builder:

let http_client = reqwest::Client::builder()
    .pool_max_idle_per_host(10)
    .connect_timeout(std::time::Duration::from_secs(5))
    .build()?;

let client = Client::builder()
    .base_url("https://api.strait.dev")
    .api_key("sk_live_...")
    .http_client(http_client)
    .build()?;

Error Handling

All errors are typed enums. Use match to handle:

use strait::error::StraitError;

match jobs.get("nonexistent").await {
    Ok(result) => println!("Found: {:?}", result),
    Err(StraitError::NotFound(e)) => println!("Not found: {}", e.message),
    Err(StraitError::RateLimited(e)) => println!("Rate limited: {}", e.message),
    Err(StraitError::Unauthorized(e)) => println!("Auth error: {}", e.message),
    Err(e) => println!("Error: {}", e),
}
Error variantHTTP StatusDescription
StraitError::TransportNetwork failure
StraitError::DecodeJSON decode failure
StraitError::ValidationConfig/input validation
StraitError::Unauthorized401, 403Auth failure
StraitError::NotFound404Resource not found
StraitError::Conflict409Duplicate/conflict
StraitError::RateLimited429Rate limit exceeded
StraitError::ApiotherGeneric HTTP error
StraitError::TimeoutPolling timeout
StraitError::DagValidationInvalid workflow DAG

Crates

Crate/ModuleImportDescription
straituse strait::ClientClient, config, errors, HTTP, middleware
strait::authoringuse strait::authoringdefine_job, define_workflow, steps, DAG validation
strait::compositionuse strait::compositionResult, retry, wait, paginate, deployments
strait::fsmuse strait::fsmRun, workflow, step state machines
strait::operationsuse strait::operationsDomain services for all API endpoints
Was this page helpful?

On this page