SDKs
Rust
Idiomatic Rust patterns for the Thunderbit Open API
Use reqwest + serde + tokio. Async by default; pair with futures::stream::iter for fan-out.
Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tokio = { version = "1", features = ["full"] }Configure
use reqwest::Client;
use serde_json::json;
const API: &str = "https://openapi.thunderbit.com/openapi/v1";
fn client() -> Client {
Client::builder()
.timeout(std::time::Duration::from_secs(60))
.build()
.unwrap()
}
fn auth() -> String {
format!("Bearer {}", std::env::var("THUNDERBIT_API_KEY").unwrap())
}Distill a page
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let res: serde_json::Value = client()
.post(format!("{API}/distill"))
.header("Authorization", auth())
.json(&json!({ "url": "https://thunderbit.com/playground" }))
.send()
.await?
.error_for_status()?
.json()
.await?;
println!("{}", res["data"]["markdown"]);
Ok(())
}Extract structured data
let res: serde_json::Value = client()
.post(format!("{API}/extract"))
.header("Authorization", auth())
.json(&json!({
"url": "https://example.com/product/iphone-15-pro",
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"price": { "type": "number" }
},
"required": ["name", "price"]
}
}))
.send().await?.error_for_status()?.json().await?;Batch fan-out
For high-concurrency single-URL distill (rather than the batch endpoint), use a bounded JoinSet:
use tokio::task::JoinSet;
let mut set = JoinSet::new();
for url in urls {
let c = client();
set.spawn(async move {
c.post(format!("{API}/distill"))
.header("Authorization", auth())
.json(&json!({ "url": url }))
.send().await?.error_for_status()?
.json::<serde_json::Value>().await
});
}
while let Some(res) = set.join_next().await { /* … */ }For 10+ URLs, prefer /batch/distill over fan-out — see Batch Job Lifecycle.
An official Rust SDK is in development — check back soon.