Skip to main content

A lightweight Python SDK for the Validin API

Project description

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-python-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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

validin_sdk-0.1.0.tar.gz (32.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

validin_sdk-0.1.0-py3-none-any.whl (35.4 kB view details)

Uploaded Python 3

File details

Details for the file validin_sdk-0.1.0.tar.gz.

File metadata

  • Download URL: validin_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 32.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for validin_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 127a80c0f2562f2a4cfd7c1b39eff9c770795bae74239ba1d251bb3e39a472ab
MD5 1cd23adce1db317445ffb266eab01420
BLAKE2b-256 c631a04f89eebb7aa58f9b855097aa72b620aaf518e8dfd969166621bdf18111

See more details on using hashes here.

File details

Details for the file validin_sdk-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: validin_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 35.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for validin_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 10c71277db05f369553876f4c7bea9b8071215f2811f206944de9ce2d62a0d2e
MD5 74658f7a02c1ec591bff73e398869f0f
BLAKE2b-256 a6aeb9ac1a1f921fe4ab20a4cbb7841190b1608611b328e61357312008a0fade

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page