Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Validin Python SDK

A Python SDK for the Validin API, designed to enable large-scale monitoring and enrichment workflows.

Requirements

  • Python 3.9+
  • A Validin API key

Installation

pip install validin-sdk
from validin import Client

Configuration

The client requires an API key. The simplest approach is to set environment variables:

export VALIDIN_API_KEY="your-api-key"

Enterprise users must also set their endpoint:

export VALIDIN_BASE_URL="https://your-enterprise-endpoint.example.com"

You can also pass these directly to the client:

from validin import Client

client = Client(api_key="your-api-key", base_url="https://your-enterprise-endpoint.example.com")

If base_url is not provided, the client defaults to https://app.validin.com.

Quick Start

Monitor a DNS TXT record query and add new results to a project:

from validin import Client

client = Client()

results = client.extra_history("anthropic-domain-verification*", lookback=1)
client.add_to_project("YOUR_PROJECT_ID", results.values)

For more advanced workflows, see the examples/ directory.

Core Concepts

Indicators

An Indicator represents a queryable entity: a domain, IP address, hash, or raw string. The SDK automatically infers the type from a string, so you can pass raw strings directly to any client method:

client.dns_history("example.com")       # inferred as domain
client.dns_history("1.1.1.1")           # inferred as IP
client.extra_history("some-txt-value*") # inferred as string (wildcard)

ResultSet

A ResultSet is the container returned by every query method. It provides:

  • Iteration — loop over individual records (for record in results)
  • .keys — deduplicated list of Indicator objects from each record (the domains/IPs represented)
  • .keys_str — string values of .keys
  • .values — deduplicated list of record values
  • .to_rows() — convert all records to a list of dictionaries
  • .aggregate() — flatten nested bulk results into a single deduplicated ResultSet

Records

Each query method returns a ResultSet containing typed record objects. Available record types:

  • DNSRecord
  • CertificateRecord
  • HostResponseRecord
  • ScanRecord
  • EnrichedIndicator (from reputation lookups)
  • AnnotationRecord (nested inside EnrichedIndicator)
  • LookalikeRecord
  • RegistrationRecord
  • YaraMatchRecord
  • Content

Enriched Indicators

An EnrichedIndicator is a subclass of Indicator that carries reputation and annotation data directly on the indicator itself. You encounter enriched indicators in two places:

1. Enrichment lookupsclient.enrich() returns a ResultSet where each record is an EnrichedIndicator with score, verdict, and annotations:

results = client.enrich("example.com")
enriched = results[0]

print(enriched.value)        # "example.com"
print(enriched.score)        # 0
print(enriched.verdict)      # "benign"
print(enriched.annotations)  # tuple of AnnotationRecord objects
print(enriched.to_rows())    # annotations flattened to list of dicts

For bulk enrichment, use .keys to iterate the EnrichedIndicator objects:

results = client.enrich(["example.com", "1.1.1.1", "google.com"])
for enriched in results.keys:
    print(f"{enriched.value}: score={enriched.score}, verdict={enriched.verdict}")
    print(enriched.to_rows())

2. History queries with annotate=True — When you pass annotate=True to dns_history(), extra_history(), host_responses(), or registration_history(), the key and value fields on returned records are upgraded from plain Indicator to EnrichedIndicator when the API provides intel data:

results = client.dns_history("example.com", annotate=True)
for record in results:
    if isinstance(record.value, EnrichedIndicator):
        print(f"{record.value.value} has {len(record.value.annotations)} annotations")
        print(record.value.informational)

Since EnrichedIndicator is a subclass of Indicator, enriched indicators work everywhere a plain indicator does — you can pass them directly to add_to_project(), use them as input to other queries, or access .value and .type as usual.

Bulk Queries and Aggregation

Any method that supports bulk queries can also accept a list of indicators instead of a single value:

results = client.enrich(["example.com", "1.1.1.1", "google.com"])

When you pass a list, the SDK:

  • Rate-limits requests to 5 queries/second
  • Retries transient failures (408, 429, 500, 502, 503, 504) with exponential backoff
  • Silently skips 404 responses

The returned ResultSet contains one child ResultSet per indicator. To flatten all results into a single deduplicated list, call .aggregate():

results = client.dns_history(["example.com", "google.com", "cloudflare.com"])

# Iterate per-indicator results
for child_result_set in results:
    print(child_result_set.query_key, len(child_result_set))

# Or flatten into one deduplicated set
all_records = results.aggregate()
print(all_records.to_rows())

Available Methods

client.dns_history(indicator)

DNS record history for a domain, IP, or string.

Indicator Type API Route
Domain /api/axon/domain/dns/history/:domain
IP /api/axon/ip/dns/history/:ip
String /api/axon/string/dns/history

Supports bulk queries. Options: limit, first_seen, last_seen, lookback, annotate, wildcard, categories_include, exclude_nx.


client.extra_history(indicator)

Extended DNS record history (TXT, SPF, etc.) for a domain, IP, or string.

Indicator Type API Route
Domain /api/axon/domain/dns/extra/:domain
IP /api/axon/ip/dns/extra/:ip
String /api/axon/string/dns/extra2

Supports bulk queries. Options: limit, first_seen, last_seen, lookback, annotate, wildcard, categories_include, exclude_nx.


client.host_responses(indicator)

HTTP crawl/response history for a domain, IP, hash, or string.

Indicator Type API Route
Domain /api/axon/domain/crawl/history/:domain
IP /api/axon/ip/crawl/history/:ip
Hash /api/axon/hash/crawl/history/:hash
String /api/axon/string/crawl/history

Supports bulk queries. Options: limit, lookback, annotate.


client.enrich(indicator)

Enrich a domain or IP with reputation score, verdict, and annotations. Returns a ResultSet of EnrichedIndicator objects (one per queried indicator), each carrying score, verdict, annotations, and informational fields.

Also available as client.reputation() (alias).

Indicator Type API Route
Domain /api/axon/domain/reputation/quick/:domain
IP /api/axon/ip/reputation/quick/:ip

Supports bulk queries. No additional options.


client.lookalikes(target)

Find newly registered lookalike domains matching a domain or regex pattern.

Target Type API Route
Domain /api/lookalike/domain/:domain
Regex /api/lookalike/regex

Does not support bulk queries. Options: exclude, limit (1–250), lookback (1–90 days), depth (labels, subdomains, fqdns), similarity (0–4, domain targets only).

Regex targets can be passed as a compiled re.Pattern or a slash-delimited string:

client.lookalikes("/^(t-mobile|att|verizon)\.([a-z]{5,6})\.(icu|cc)$/")

client.certificates(indicator)

Historic certificate transparency matches for a domain.

Indicator Type API Route
Domain /api/axon/domain/certificates/:domain

Does not support bulk queries. Options: wildcard, limit (1–20000), first_seen, last_seen, lookback, time_format (unix or iso).


client.ptr_history(indicator)

Historic PTR/hostname records for a domain or IP.

Indicator Type API Route
Domain /api/axon/domain/dns/hostname/:domain
IP /api/axon/ip/dns/hostname/:ip

Supports bulk queries. Options: limit, first_seen, last_seen, lookback, annotate, time_format (unix or iso), and wildcard for domain queries only.


client.start_scan(find)

Start an enterprise live HTTP/S scan and return a ScanJob.

API Route
/api/axon/live/scan/start

Does not support bulk queries. Options: countries, refer, user_agent.


client.get_scan(scan_id)

Fetch live scan status and return a ScanJob.

API Route
/api/axon/live/scan/results/:scan_id

Does not support bulk queries.


client.scan(find)

Convenience wrapper around start_scan(). By default it waits for completion and returns a ResultSet of ScanRecord objects. Pass wait=False to get a ScanJob immediately.

API Route
/api/axon/live/scan/start -> poll results -> crawl

Options: countries, refer, user_agent, wait, poll_interval, timeout.


client.registration_history(indicator)

WHOIS/RDAP registration history for a domain or string.

Indicator Type API Route
Domain /api/axon/domain/registration/history/:domain
String /api/axon/string/registration/history2

Supports bulk queries. Options: limit, first_seen, last_seen, lookback, annotate, wildcard, include_fields.


client.yara_matches(project_id, rule_id)

Fetch YARA rule match results from a project. Auto-paginates all results by default.

API Route
/api/project/:project_id/yara/rules/:rule_id/matches

Does not support bulk queries. Options: page, page_size (provide both for manual pagination), include_html, first_seen, last_seen.


client.fetch_content(indicator)

Fetch stored HTML content by body hash.

API Route
/api/axon/hash/content/html/sha1/:hash

Supports bulk queries. Accepts a hash string, Indicator, or HostResponse object with a body_hash.


client.add_to_project(project_id, indicators)

Add indicators to a Validin project.

API Route
/api/project/:project_id/indicators/add

Accepts a single indicator or a list. Options: note, tags.

Examples

Example scripts are in the examples/ directory:

  • **lookalike_monitor.py** — Regex lookalike search for telecom smishing domains, filter by registrar, add to project.
  • **dns_txt_record_monitor.py** — Monitor a DNS TXT record wildcard query and add results to a project.
  • **bulk_indicator_enrichment.py** — Bulk enrichment lookup across multiple indicators.
  • **ingest_yara_matches.py** — Fetch all YARA rule matches for a project and print aggregated results.
  • **sample_host_responses.py** — Bulk host response history with HTML content download.

Error Handling

The SDK raises ApiError for HTTP failures and ValidinError as a base exception class:

from validin import Client
from validin_sdk.errors import ApiError, ValidinError

client = Client()

try:
    results = client.dns_history("example.com")
except ApiError as e:
    print(f"HTTP {e.status_code}: {e.message}")
except ValidinError as e:
    print(f"SDK error: {e}")

API Coverage

The SDK currently covers 24 of 76 API endpoints.

Status Method Endpoint Summary SDK Method
Bulk
POST /api/axon/bulk/osint/context Bulk OSINT Context
Domain
GET /api/axon/domain/certificates/{domain} Domain Certificates certificates()
GET /api/axon/domain/crawl/history/{domain} Domain Crawl History host_responses()
GET /api/axon/domain/dns/extra/{domain} Domain DNS Extra extra_history()
GET /api/axon/domain/dns/history/{domain} Domain DNS History dns_history()
GET /api/axon/domain/dns/history/{domain}/A Domain DNS History - A
GET /api/axon/domain/dns/history/{domain}/AAAA Domain DNS History - AAAA
GET /api/axon/domain/dns/history/{domain}/NS Domain DNS History - NS
GET /api/axon/domain/dns/history/{domain}/NS_FOR Domain DNS History - NS_FOR
GET /api/axon/domain/dns/hostname/{domain} Domain DNS Hostname ptr_history()
GET /api/axon/domain/osint/history/{domain} Domain OSINT History
GET /api/axon/domain/pivots/{domain} Domain Pivots
GET /api/axon/domain/pivots/{domain}/{category} Domain Pivots - Category
GET /api/axon/domain/registration/history/{domain} Domain Registration History registration_history()
GET /api/axon/domain/registration/live/{domain} Domain Registration Live
GET /api/axon/domain/reputation/quick/{domain} Domain Reputation Quick enrich()
GET /api/axon/domain/subdomains/{domain} Domain Subdomains
GET /api/lookalike/domain/{domain} Lookalike Domain lookalikes()
GET /api/lookalike/regex Lookalike Regex lookalikes()
GET /api/v2/domain/combined/connections/{domain} V2 Domain Combined Connections
Hash
GET /api/axon/hash/content/certificate/sha1/{hash} Hash Content Certificate (SHA1)
GET /api/axon/hash/content/favicon/md5/{hash} Hash Content Favicon (MD5)
GET /api/axon/hash/content/html/sha1/{hash} Hash Content HTML (SHA1) fetch_content()
GET /api/axon/hash/crawl/history/{hash} Hash Crawl History host_responses()
GET /api/axon/hash/pivots/{hash} Hash Pivots
GET /api/axon/hash/pivots/{hash}/{category} Hash Pivots - Category
IP
GET /api/axon/ip/crawl/history/{ip} IP Crawl History host_responses()
GET /api/axon/ip/crawl/history/{ip}/{cidr} IP Crawl History - (CIDR)
GET /api/axon/ip/dns/extra/{ip} IP DNS Extra extra_history()
GET /api/axon/ip/dns/extra/{ip}/{cidr} IP DNS Extra - (CIDR)
GET /api/axon/ip/dns/history/{ip} IP DNS History dns_history()
GET /api/axon/ip/dns/history/{ip}/{cidr} IP DNS History - (CIDR)
GET /api/axon/ip/dns/hostname/{ip} IP DNS Hostname ptr_history()
GET /api/axon/ip/dns/hostname/{ip}/{cidr} IP DNS Hostname - (CIDR)
GET /api/axon/ip/osint/history/{ip} IP OSINT History
GET /api/axon/ip/osint/history/{ip}/{cidr} IP OSINT History - (CIDR)
GET /api/axon/ip/pivots/{ip} IP Pivots
GET /api/axon/ip/pivots/{ip}/{cidr} IP Pivots - (CIDR)
GET /api/axon/ip/pivots2/{ip}/{category} IP Pivots - Category
GET /api/axon/ip/reputation/quick/{ip} IP Reputation Quick enrich()
Projects
GET /api/project/list Project List
GET /api/project/{project_id} Project Details
GET /api/project/{project_id}/alerts/dates Project - List Dates that have Alerts
GET /api/project/{project_id}/alerts/latest Project - Latest Alerts
GET /api/project/{project_id}/alerts/{date} Project - Alerts for Date
GET /api/project/{project_id}/indicators Project - List Indicators
POST /api/project/{project_id}/indicators/add Project - Add Indicators add_to_project()
POST /api/project/{project_id}/indicators/add_note Project - Add Note to Indicators
POST /api/project/{project_id}/indicators/delete Project - Delete Indicators
POST /api/project/{project_id}/indicators/tags/add Project - Add Tags to Indicators
POST /api/project/{project_id}/indicators/tags/delete Project - Delete Tags from Indicators
GET /api/project/{project_id}/scans Project - List Scans
GET /api/project/{project_id}/yara/rules Project - List Yara Rules
GET /api/project/{project_id}/yara/rules/{rule_id}/matches Project - List Matches for YARA rule yara_matches()
Scans
GET /api/axon/live/scan/results/{scan_id} Live Scan Results get_scan()
GET /api/axon/live/scan/results/{scan_id}/crawl Live Scan Results - Crawl scan(), get_scan_crawl_results()
POST /api/axon/live/scan/start Live Scan Start start_scan(), scan()
String
GET /api/axon/string/dns/extra2 String DNS Extra History extra_history()
GET /api/axon/string/dns/history String DNS History dns_history()
GET /api/axon/string/pivots2 String Pivots
GET /api/axon/string/pivots2/{category} String Pivots - Category
GET /api/axon/string/registration/history2 String Registration History registration_history()
GET /api/axon/string/registration/history2/{field} String Registration History - Category
Threats
GET /api/threat/group/{threat_key}/indicators Threat Group - List Indicators
GET /api/threat/group/{threat_key}/reports Threat Group - List Reports
GET /api/threat/group/{threat_key}/summary Threat Group - Summary
GET /api/threat/indicators/recent Recent Threat Indicators
GET /api/threat/names Threat Names
GET /api/threat/reports/recent Recent Threat Reports
Utilities
GET /api/axon/advanced/query Advanced Query
POST /api/axon/submissions/domains Submissions Domains
GET /api/paths Paths
GET /api/ping Ping
GET /api/profile/token Profile Token
GET /api/profile/usage Profile Usage
GET /api/profile/usage/daily Profile Usage Daily

License

MIT

About

A Python SDK that wraps the Validin API

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages