Domain graph
Domain graph gives you programmatic access to our coverage view: which ID types are supported in which countries, how those types are validated, and which registries participate in their verification.
To better understand the data model and how it relates to the underlying API, see List supported IDs and List data sources.
Use it to preflight a country or region before running verification, and to drive product choices such as which ID types to request, which checks are registry-backed versus partial versus syntactic-only, and what formats and labels to show in input flows.
The key property of DomainGraph is that it is built for reuse. It has built-in caching and can be serialized and rehydrated for offline mode.
Build once, reuse many times
DomainGraph loads domain data and keeps it cached in-memory. When the cache is fresh, it is reused. When the TTL expires, it refreshes automatically if a client is available.
import { createVerifyVatClient, DomainGraph } from '@verifyvat/sdk'
const client = createVerifyVatClient()
// For demo purposes we use a short TTL.// In production, use a longer cache duration.const graph = new DomainGraph({ client, ttlMs: 60 * 60_000 }) // 1 hourfrom verifyvat_sdk import DomainGraph, VerifyVatClient
client = VerifyVatClient()
# For demo purposes we use a short TTL.# In production, use a longer cache duration.graph = DomainGraph(client=client, ttl_ms=60 * 60_000) # 1 hourPreflight a region
A common flow is to compute a view for one or more regions and then select a specific country for UX or policy decisions.
// continuing from above
const countryViews = await graph.getCountryViews({ region: ['EU', 'EMEA'] }, { shape: 'record' })
const norwayView = 'NO' in countryViews ? countryViews.NO : null# continuing from above
country_views = graph.get_country_views(region=("EU", "EMEA"), shape="dict")
norway_view = country_views.get("NO", None)The country view includes available ID types (types), the subset that is fully registry-backed (full), and the data sources that cover the country (sources).
Picking what to ask for
Once you have a country view, you can pick a preferred ID type using a heuristic that matches your onboarding or compliance policy.
A practical baseline is to prefer a VAT-like type when present, otherwise prefer the first fully-covered type, otherwise fall back to any available type.
// continuing from above
const preferredIdType = norwayView.full.find(t => /(vat|gst|tin)/i.test(t.id)) || norwayView.full[0] || norwayView.types[0] || null# continuing from above
preferred_id_type = next( (t for t in norway_view["full"] if any(x in t["id"] for x in ("vat", "gst", "tin"))), norway_view["full"][0] if norway_view["full"] else (norway_view["types"][0] if norway_view["types"] else None),)This is the kind of selection logic used to drive onboarding requirements, supplier document requests, and country-specific input UX. It is completely up to you how to pick the preferred type, but DomainGraph gives you the tools to make an informed choice.
Offline mode via snapshots
DomainGraph can serialize its cached data and rehydrate later without network calls. This supports offline UX, fast startup, and shipping a precomputed snapshot to a client application.
// continuing from above
const snapshot = graph.toJSON()if (!snapshot) return
// Rehydrate from snapshot; no network calls will be made here.const offline = await DomainGraph.fromData(snapshot).getCountryViews()const offlineView = offline.find(c => c.country === 'NO')# continuing from above
snapshot = graph.to_dict()if not snapshot: raise SystemExit()
# Rehydrate from snapshot; no network calls will be made here.offline = DomainGraph.from_data(snapshot).get_country_views()offline_view = next((c for c in offline if c["country"] == "NO"), None)