WorkOS Rust Library
The WorkOS Rust SDK provides async access to the WorkOS API from Rust applications. It uses tokio, ships with a default reqwest HTTP transport, and includes helpers for common WorkOS flows such as AuthKit, SSO, webhooks, sessions, JWKS, PKCE, and Vault local crypto.
Documentation
Installation
Requires Rust 1.88+ (edition 2024). The repository pins this via rust-toolchain.toml, so a fresh checkout will install the matching toolchain automatically when you run any cargo or ./script/ci command under rustup.
By default, the crate enables reqwest with rustls-tls. You can switch TLS backends or provide a custom HTTP transport; see HTTP Transport.
Quick Start
use ;
async
For an API-key-only client with default settings:
let client = new;
Configuration
Client::builder() supports:
| Method | Description |
|---|---|
.api_key(_) |
WorkOS secret key (sk_...), required for authenticated API calls. |
.client_id(_) |
WorkOS Client ID, required for AuthKit, SSO, and JWKS helpers. |
.base_url(_) |
Override the API host. Defaults to https://api.workos.com. |
.timeout(_) |
Per-request timeout. Defaults to 30 seconds. |
.max_retries(_) |
Retry budget for 429 and 5xx responses. Defaults to 3. |
.user_agent(_) |
Override the User-Agent header. |
.transport(_) |
Plug in a custom HttpTransport. |
build() panics if the supplied API key or user-agent contains bytes that aren't valid in an HTTP header. Use .try_build() to surface those failures as Err(workos::Error::Builder(_)) instead — useful when the API key comes from untrusted input.
The client is cheap to clone and can be shared across handlers and tasks.
API Access
API resources are exposed as accessors on Client, for example:
client.organizations;
client.user_management;
client.sso;
client.webhooks;
client.audit_logs;
List endpoints return Page<T> values with data and list_metadata cursors. The crate also exports auto_paginate for stream-based iteration.
Every API call returns Result<_, workos::Error>. The error type includes API errors, transport failures, decode errors, configuration errors, and helper-specific failures. It also provides predicates such as is_unauthorized(), is_not_found(), is_rate_limited(), and is_server_error().
See the crate docs for the full resource list, request and response types, pagination details, and helper APIs.
Forward-compatible enums
Generated enums are #[non_exhaustive] and include an Unknown(String) variant for wire values the SDK doesn't recognize yet — WorkOS can add new enum values server-side without breaking deserialization for older SDK builds. Match defensively:
use ConnectionType;
match connection.r#type
The original wire string is preserved through round-trips: serializing an Unknown("FooBar") re-emits "FooBar" verbatim. Each enum also implements Display, FromStr (infallible), and AsRef<str> for ergonomic conversions.
Per-Request Options
Each generated method has a *_with_options companion that takes a RequestOptions. Use it to pass an idempotency key, additional headers, or a per-request retry policy:
use ;
let opts = new.idempotency_key;
let org = client
.organizations
.create_organization_with_options
.await?;
Replaying a mutating request with the same idempotency key is safe; WorkOS recognises the key on the server side.
Request strategies
For finer-grained control, attach a RequestStrategy to override the client's default retry behavior on a single call:
use ;
// Send exactly once, regardless of `max_retries`:
let opts = new.strategy;
// Make a mutation idempotent and retry-eligible (the key is also sent
// as the `Idempotency-Key` header):
let opts = new
.strategy;
// Custom retry budget with jitter:
let opts = new.strategy;
Variants: Once, Idempotent(key), Retry { max_attempts }, ExponentialBackoff { max_attempts, jitter }.
Errors
API errors carry structured metadata. Always log request_id() when reporting bugs to WorkOS:
match client.organizations.get_organization.await
err.api() returns the full ApiError with the raw response headers and body for advanced debugging.
Sensitive Fields
Fields that hold credentials or tokens — password, client_secret, access_token, refresh_token, token, secret, etc. — are typed as workos::SecretString. Their Debug representation prints "<redacted>", so secrets don't leak through logs, panic messages, or error reports. Read the underlying value with .expose() when you genuinely need it:
let token: &str = session.access_token.expose;
SecretString serializes transparently as a JSON string, so the wire format is unchanged. Constructors that accept a sensitive parameter take impl Into<SecretString> — passing a String or &str works without an explicit conversion.
Retries
The client retries 429 and 5xx responses (plus retryable transport errors) up to max_retries times — default 3 — with exponential backoff and equal-jitter. The Retry-After header is honored when present and supersedes the computed backoff.
To preserve at-most-once semantics for state-changing calls, only safe HTTP methods (GET/HEAD/OPTIONS) and requests carrying an Idempotency-Key are auto-retried. POST/PUT/PATCH/DELETE without an idempotency key are sent exactly once.
// Disable retries entirely for this client:
let client = builder
.api_key
.max_retries
.build;
Pair mutations with an idempotency key (or RequestStrategy::Idempotent) so a redelivered request is processed exactly once on the server.
Auto-Paging
Every list endpoint generates a *_auto_paging companion that returns a futures_util::Stream, advancing the after cursor under the hood:
use TryStreamExt;
use ListOrganizationsParams;
let all: = client
.organizations
.list_organizations_auto_paging
.try_collect
.await?;
For custom paginated flows the crate also re-exports the lower-level auto_paginate(fetch) helper, which drives any (after) -> Result<Page<T>, _> closure to exhaustion.
Helpers
The SDK includes hand-maintained helpers for:
- AuthKit and SSO URL builders, PKCE flows, token exchange, logout, and device authorization.
- Webhook signature verification.
- Sealed session cookies.
- JWKS fetching and URL construction.
- Vault key-value operations and optional local AES-GCM encryption.
- Public PKCE-only clients for browser or mobile flows that must not hold an API key.
HTTP Transport
The default HTTP transport is reqwest, gated behind the default reqwest feature. To use another client, share an existing request pipeline, or support environments such as WASM, disable default features and provide a workos::transport::HttpTransport implementation:
# Cargo.toml
= { = "1", = false }
let transport: SharedTransport = new;
let client = builder
.api_key
.transport
.build;
Supported crate features:
| Feature | Default | Description |
|---|---|---|
reqwest |
yes | Enables the bundled reqwest transport. |
rustls-tls |
yes | Uses rustls for TLS through reqwest. |
native-tls |
no | Uses the platform native TLS stack through reqwest. |
More Information
License
MIT. See LICENSE.txt.