Lookups

View as markdown

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, given as a String or an IPAddr.

def lookup_ip: (String | IPAddr ip) -> IPInfo
info = client.lookup_ip("213.149.183.127")

location = info.location
puts "#{location.city}, #{location.country}" if location

info.intelligence&.providers&.each do |provider|
  puts "#{provider.name} (#{provider.type}), last seen #{provider.last_seen}"
end
  • Cost: Each lookup costs one credit, and failed lookups are not billed.
  • Input: An address with a prefix or a zone, or one that IPAddr cannot parse, raises ArgumentError without sending a request. Any other argument type raises TypeError.
  • Errors: Private and reserved addresses raise a 422 APIError.

lookup_ips

Looks up as many as 1000 addresses in one request.

def lookup_ips: (Enumerable[String | IPAddr] ips) -> Array[IPInfo]
results = client.lookup_ips(["8.8.8.8", IPAddr.new("1.1.1.1")])
results.each do |result|
  intelligence = result.intelligence
  if intelligence
    puts "#{result.ip} #{intelligence.risk_score}"
  else
    puts "#{result.ip} no intelligence available"
  end
end
  • Cost: The API bills ceil(n * 0.9) credits for the n distinct addresses it looks up, and bills nothing if the request fails.
  • Results: The API skips private and reserved addresses and collapses duplicates into one result, so there can be fewer results than addresses. Match results by ip, which the API canonicalizes, rather than by position.
  • Input: Any Enumerable of String and IPAddr values works. An empty list returns [] without a request. More than 1000 addresses raises ArgumentError before anything is sent. An element that lookup_ip would reject raises the same error lookup_ip would, with its index in the message. An argument that is not Enumerable, such as a single String, raises TypeError.
  • Errors: A batch with no address the API can look up raises a 422 APIError.

lookup_domain

Returns the honeypot traffic Synthient has observed for a domain.

def lookup_domain: (String domain, ?limit: Integer?) -> DomainInfo
  • Name
    limit
    Type
    Integer?
    Description

    Caps the number of recent events returned, from 1 to 1000. nil uses the API default of 50. A value that is not a positive Integer raises ArgumentError.

domain = client.lookup_domain("example.com", limit: 10)
puts "#{domain.status} #{domain.stats.events_24h}"
domain.recent_events.each do |event|
  puts "#{event.timestamp} #{event.target_subdomain} #{event.port}"
end
  • Cost: Each lookup costs one credit.
  • Input: Encode internationalized names as Punycode. An empty domain, ".", or ".." raises ArgumentError without a request. A domain that is not a String raises TypeError.
  • Results: A domain that has never been observed returns the status 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.

def account: () -> Account
account = client.account
puts "#{account.email} #{account.organization.name} #{account.scopes.join(", ")}"
quota = account.lookup_quota
puts "#{quota.credits} credits, resetting in #{quota.resets_in} seconds"
  • Cost: It costs no credits.

health

Returns nil if the API and its dependencies are healthy.

def health: () -> nil
begin
  client.health
rescue Synthient::APIError => e
  warn "unhealthy: #{e.status}"
end
  • Errors: An unhealthy API raises an APIError with status 503, which is not retried. The API does not check the key, but the edge in front of it answers a malformed key with a 401 APIError.