# Rust SDK The official Rust client for the Synthient API: IP and domain lookups, account details, real-time feed streams, and Parquet exports. > **Note**: The generated reference for every module, type, and method is on [docs.rs](https://docs.rs/synthient). These pages cover the same surface with examples. The source is at [github.com/synthient/synthient-rust](https://github.com/synthient/synthient-rust), and runnable programs are in its `examples` directory. ## Getting started ### 1. Install ```bash cargo add synthient cargo add tokio --features macros,rt-multi-thread ``` Requires Rust 1.85 or later. The crate is named `synthient`. The client is asynchronous and runs on Tokio, and requests need a runtime with its time driver enabled, which `#[tokio::main]` provides. The newest releases of some dependencies need Rust 1.88. On Rust 1.85 to 1.87, Cargo picks releases your Rust version supports only with its MSRV-aware resolver, which edition 2024 packages use by default. In an edition 2021 package, turn it on in the `[package]` table of Cargo.toml, or in `[workspace]` for a workspace: ```toml [package] resolver = "3" ``` | Feature | Default | Enables | | ------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `rustls` | Yes | TLS through rustls. | | `native-tls` | No | TLS through the platform's native library. | | `grpcschema` | No | The `synthient::grpcschema` module, which fetches the protobuf schema of the Synthient [gRPC API](https://docs.synthient.com/grpc). See [gRPC schema](https://docs.synthient.com/sdks/rust/grpc-schema). | To use the platform's TLS library instead of rustls, turn off the default features: ```bash cargo add synthient --no-default-features --features native-tls ``` The crate re-exports `reqwest`, the HTTP client it is built on, so `synthient::reqwest` can configure the transport without a separate dependency. It also re-exports `StatusCode` for matching error statuses. ### 2. Make your first lookup This program creates a client with the API key in `SYNTHIENT_API_KEY` and looks up one address. Each lookup costs one credit. ```rust use std::net::Ipv4Addr; #[tokio::main] async fn main() -> Result<(), Box> { let client = synthient::Client::new(std::env::var("SYNTHIENT_API_KEY")?)?; let info = client.lookup_ip(Ipv4Addr::new(8, 8, 8, 8)).await?; if let Some(network) = &info.network { println!("{} {}", network.isp, network.r#type); } if let Some(intelligence) = &info.intelligence { println!("{} {:?}", intelligence.risk_score, intelligence.categories); } Ok(()) } ``` `IpInfo::network`, `IpInfo::location`, and `IpInfo::intelligence` are `None` when the API has no data for that section. ### 3. Check your credits `account` returns the account that owns the API key, including its scopes and remaining lookup credits. It costs no credits. ```rust use synthient::Scope; let account = client.account().await?; let scopes: Vec<&str> = account.scopes.iter().map(Scope::as_str).collect(); println!( "{} {} {}", account.email, account.organization.name, scopes.join(", ") ); println!( "{} credits, resetting in {} seconds", account.lookup_quota.credits, account.lookup_quota.resets_in ); ``` ### 4. Handle errors Every fallible method returns `synthient::Result`. A request that fails with a non-success HTTP status returns `Error::Api`, whose `ApiError` holds the status, the problem detail, the request ID, and any `Retry-After` delay. Match on it: ```rust use std::net::Ipv4Addr; use synthient::{Error, StatusCode}; match client.lookup_ip(Ipv4Addr::new(8, 8, 8, 8)).await { Ok(info) => println!("{:?}", info.intelligence), Err(Error::Api(err)) if err.status == StatusCode::PAYMENT_REQUIRED => { eprintln!("out of lookup credits"); } Err(Error::Api(err)) if err.status == StatusCode::TOO_MANY_REQUESTS => { match err.retry_after { Some(retry_after) => eprintln!("rate limited, retry after {retry_after:?}"), None => eprintln!("monthly request budget spent"), } } Err(Error::Api(err)) => { let message = err.detail.or(err.title).unwrap_or_default(); let request_id = err.request_id.unwrap_or_default(); eprintln!("request {request_id} failed: {message}"); } Err(err) => eprintln!("lookup failed: {err}"), } ``` ### 5. Keep going - [Client](https://docs.synthient.com/sdks/rust/client): create and configure the client, and read the metadata of every API response. - [Lookups](https://docs.synthient.com/sdks/rust/lookups): look up IP addresses and domains, and check your account and the API's health. - [Feeds](https://docs.synthient.com/sdks/rust/feeds): stream each feed's real-time events and download its hourly and daily Parquet exports. - [Errors and retries](https://docs.synthient.com/sdks/rust/errors): how failed requests are reported, and which requests are retried. - [Types](https://docs.synthient.com/sdks/rust/types): the fields of every response and event type, and the enumerations they use. - [gRPC schema](https://docs.synthient.com/sdks/rust/grpc-schema): fetch the protobuf schema of the Synthient gRPC API.