# Lookups Look up IP addresses and domains, and check your account and the API's health. ## lookup\_ip Returns intelligence for an IPv4 or IPv6 address. ```rust pub async fn lookup_ip(&self, ip: impl Into) -> Result ``` ```rust use std::net::IpAddr; let ip: IpAddr = "213.149.183.127".parse()?; let info = client.lookup_ip(ip).await?; if let Some(location) = &info.location { println!("{} {}", location.city, location.country); } if let Some(intelligence) = &info.intelligence { for provider in &intelligence.providers { println!( "{} {} {:?}", provider.name, provider.r#type, provider.last_seen.to_system_time() ); } } ``` - **Cost:** Each lookup costs one credit, and failed lookups are not billed. - **Input:** It accepts anything that converts into `IpAddr`, such as `Ipv4Addr` or `Ipv6Addr`; parse untrusted strings into an `IpAddr` first. - **Errors:** Private and reserved addresses return a 422 `Error::Api`. ## lookup\_ips Looks up as many as 1000 addresses in one request. ```rust pub async fn lookup_ips(&self, ips: &[IpAddr]) -> Result> ``` ```rust let ips = ["8.8.8.8".parse()?, "1.1.1.1".parse()?]; for result in client.lookup_ips(&ips).await? { match &result.intelligence { Some(intelligence) => println!("{} {}", result.ip, intelligence.risk_score), None => println!("{} no intelligence available", result.ip), } } ``` - **Cost:** The API bills `ceil(n * 0.9)` credits for the `n` distinct addresses it looks up, and bills nothing if the account cannot cover the whole batch. - **Results:** Private and reserved addresses are skipped and duplicates collapse into one result, so there can be fewer results than addresses. Match results by `IpInfo::ip` rather than by index. - **Input:** An empty slice returns an empty `Vec` without a request. More than 1000 addresses return `Error::InvalidInput` before anything is sent. - **Errors:** A batch with no address the API can look up returns a 422 `Error::Api`. ## lookup\_domain Returns the honeypot traffic Synthient has observed for a domain. ```rust pub async fn lookup_domain(&self, domain: &str, limit: Option) -> Result ``` ```rust let domain = client.lookup_domain("example.com", Some(10)).await?; println!("{} {}", domain.status, domain.stats.events_24h); for event in &domain.recent_events { println!( "{:?} {} {}", event.timestamp.to_system_time(), event.target_subdomain, event.port ); } ``` - **Cost:** Each lookup costs one credit. - **Input:** `limit` caps the number of recent events returned, from 1 to 1000, and `None` uses the API default of 50. Internationalized names must be sent in Punycode. An empty domain, `"."`, or `".."` returns `Error::InvalidInput` without a request. - **Results:** A domain that has never been observed returns `DomainStatus::Inactive` and zero counts rather than an error. ## Account and health ### account Returns the account that owns the API key, including its scopes and remaining lookup credits. ```rust pub async fn account(&self) -> Result ``` ```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 ); ``` - **Cost:** It costs no credits. ### health Returns `Ok(())` if the API and its dependencies are healthy. ```rust pub async fn health(&self) -> Result<()> ``` ```rust client.health().await?; ``` - **Cost:** It costs no credits. - **Retries:** Like the billed lookups, it is retried only on 429 responses that carry `Retry-After`, so an unhealthy API is reported at once. - **Errors:** An unhealthy API returns a 503 `Error::Api`. The API does not check the key, but a malformed key returns a 401 `Error::Api`.