Skip to main content

Rust SDK API Reference

Complete API documentation for the Rust SDK. Generated rustdoc is available on docs.rs.

Replane​

The client. Create it with Replane::builder():

use replane::{ConnectOptions, Replane};

let replane = Replane::builder()
.connect(ConnectOptions::new("https://replane.example.com", "your-sdk-key"))
.await?;

Replane is cheap to clone. Clones share configs and the connection, so you can store it in application state and pass it around freely. The connection closes when the last clone is dropped.

ReplaneBuilder​

MethodDescription
context(context)Context applied to every evaluation; per-call context takes precedence
default_value(name, value)Value used until the server provides one, and if the server lacks the config
defaults(iter)Several defaults at once, as (name, serde_json::Value) pairs
snapshot(snapshot)Configs from another client's snapshot(); take precedence over defaults
build()Creates a client that works in memory until connect is called
connect(options).awaitBuilds the client and connects it
use replane::{Context, Replane};
use serde_json::json;

let replane = Replane::builder()
.context(Context::new().with("region", "eu"))
.default_value("feature-enabled", false)
.default_value("theme", json!({ "darkMode": false, "fontSize": 14 }))
.build();

connect​

Connects to the server and waits until the initial configs arrive. After that the client stays connected in the background, reconnecting with exponential backoff when the connection drops. Must be called within a Tokio runtime.

use std::time::Duration;
use replane::ConnectOptions;

replane
.connect(
ConnectOptions::new("https://replane.example.com", "your-sdk-key")
.connect_timeout(Duration::from_secs(10)),
)
.await?;

ConnectOptions​

OptionDefaultDescription
base_urlrequiredReplane server URL (first argument of ConnectOptions::new)
sdk_keyrequiredSDK key for authentication (second argument)
connect_timeout5sHow long connect waits for the initial configs
request_timeout2sTimeout for establishing each stream request
inactivity_timeout30sReconnect if no events or heartbeats arrive for this long
retry_delay200msInitial reconnect delay, doubled per failure up to 10s
agentreplane-rust-sdk/<ver>User-Agent header
http_clientbuilt-inCustom reqwest::Client; must not set a total request timeout

disconnect / is_connected​

replane.disconnect(); // stop receiving updates; already loaded configs keep working
assert!(!replane.is_connected());

get​

Returns the config value for the client context, with overrides applied, deserialized into any type implementing serde::Deserialize.

let enabled: bool = replane.get("feature-enabled")?;
let limit: u32 = replane.get("rate-limit")?;
let api_url: String = replane.get("api-url")?;

// Raw JSON value
let raw: serde_json::Value = replane.get("theme")?;

Complex types​

use serde::Deserialize;

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ThemeConfig {
dark_mode: bool,
primary_color: String,
font_size: u32,
}

let theme: ThemeConfig = replane.get("theme")?;
println!("Dark mode: {}", theme.dark_mode);

get_with​

Like get, with the given context merged over the client context:

use replane::Context;

let ctx = Context::new()
.with("userId", "user-123")
.with("plan", "premium")
.with("region", "us-east");

let premium_feature: bool = replane.get_with("premium-feature", &ctx)?;

get_or​

Returns the default if the config is missing or can't be deserialized into the requested type. Deserialization failures are logged as a tracing warning.

let timeout_ms: u64 = replane.get_or("timeout-ms", 5000);

Context​

Properties that override rules are evaluated against. Values can be strings, numbers, booleans, or None (null).

use replane::Context;

let mut ctx = Context::new().with("userId", "user-123").with("age", 30);
ctx.insert("beta", true);
ctx.insert("company", None::<&str>);

// From an array of pairs
let ctx = Context::from([("plan", "premium"), ("region", "eu")]);

Each client also gets a random replaneClientId context value (replane::REPLANE_CLIENT_ID_KEY), which can be used for percentage rollouts. A value provided in the client context takes precedence.

with_context​

Returns a client that shares configs and the connection, with extra context merged in. Useful for per-request or per-user clients:

let user_client = replane.with_context(&Context::new().with("userId", "user-123"));
let enabled: bool = user_client.get("new-checkout")?;

subscribe​

Calls the callback whenever a config changes on the server. Returns a Subscription; dropping it unsubscribes.

let subscription = replane.subscribe("feature-flag", |change| {
println!("{} changed to {}", change.name, change.value);
});

// Keep the subscription for the lifetime of the client
subscription.detach();

The callback receives a ConfigChange with the config name and its base value (a serde_json::Value, without overrides applied). It runs on the connection task, so keep it short. Call get or get_with inside it to get the evaluated value for a context.

snapshot​

Returns a serializable copy of the current configs, which can seed another client:

let snapshot = replane.snapshot();
let json = serde_json::to_string(&snapshot)?;

let restored = Replane::builder()
.snapshot(serde_json::from_str(&json)?)
.build();

Errors​

All fallible methods return replane::Result<T>, an alias for Result<T, ReplaneError>:

VariantWhen
NotFoundThe config doesn't exist
DeserializeThe value can't be deserialized into the requested type
Timeoutconnect timed out; includes the last connection error
AuthInvalid or missing SDK key
ForbiddenThe SDK key isn't allowed to access the resource
ServerThe server returned a 5xx response
ClientThe server returned another 4xx response
NetworkA network error from reqwest
ProtocolUnexpected response from the server
InvalidOptionsInvalid connection options, e.g. an empty SDK key
use replane::ReplaneError;

match replane.get::<bool>("my-config") {
Ok(value) => println!("value: {value}"),
Err(ReplaneError::NotFound { name }) => println!("config not found: {name}"),
Err(e) => println!("error [{}]: {e}", e.code()),
}

ReplaneError::code() returns a stable error code shared with the other Replane SDKs, such as not_found or timeout.

Condition operators​

The SDK supports these override operators:

OperatorDescription
equalsExact match
inValue is in list
not_inValue is not in list
less_thanLess than comparison
less_than_or_equalLess than or equal
greater_thanGreater than comparison
greater_than_or_equalGreater than or equal
segmentationPercentage-based bucketing
andAll conditions must match
orAny condition must match
notNegate a condition

Overrides using an operator the SDK doesn't know are skipped instead of failing the whole config.