Skip to contentSkip navigation

Procedures

What WhisperGraph's stored procedures do, how CALL works, and when a procedure beats a hand-written traversal.

Procedures
On this page (9)

Procedures Documentation

WhisperGraph ships stored procedures you call from Cypher with CALL. Each one wraps a multi-step computation — threat scoring, lookalike generation, WHOIS and BGP history, CDN origin discovery, infrastructure identity — into a single call that returns a clean result set instead of a hand-written traversal. They run on the public API at https://graph.whisper.security/api/query, and several have matching tools on the MCP server.

Scores and verdicts are live reads. The value reflects whatever data is loaded at query time, so treat a result as current, not fixed.

The four WhisperGraph procedures and the free metadata calls around them

Calling a procedure

CALL runs a procedure standalone, with YIELD to pick and filter columns, or once per row in the UNWIND ... CALL form. A standalone call with no YIELD returns every column the procedure produces. Full clause syntax is in Syntax & Clauses.

cypher · runnablegraph.whisper.securitySign in to run
CALL whisper.variants("paypal.com")
YIELD variant, method, exists, confidenceLabel
WHERE exists
RETURN variant, method, confidenceLabel
LIMIT 6

The procedures

Four procedures do the heavy lifting, each with its own page. Beyond them, an identity family answers "whose infrastructure is this", and a set of helpers cover naming and lookups.

Read coverage before band. Only known-clean — coverage: known-clean. In coverage, no malicious evidence. licenses the word "clean"; no-data — coverage: no-data. Not in coverage. This is not a verdict — nothing was looked at. means unknown, which is a different thing again; malicious-evidenced — coverage: malicious-evidenced. In coverage, with positive evidence of malice. and ambiguous — coverage: ambiguous. In coverage, and the evidence points both ways. mean there is evidence, whatever the band says. whisper.explain does not return coverage at all. Full contract: Coverage — what we looked at.

Investigation

ProcedureWhat it answersNotes
explain(indicator)Threat verdict for an IP, domain, ASN, or CIDR: score, level, factors[], sources[]Auto-detects the indicator type
whisper.variants(domain)Typosquat and lookalike variants, filtered by default to ones registered in the graphexists: true means registered, not malicious
whisper.history(indicator)WHOIS snapshots for a domain; BGP routing history for an IP, ASN, or prefixWHOIS and routing columns cannot be YIELDed together — one shape per call
whisper.origins(domain)Candidate origin IPs behind a CDN or proxy, ranked by confidencePassive lookup; no packet touches the target

Identity & assessment

ProcedureWhat it answersNotes
whisper.identify(hosts)Whose infrastructure a host is — canonical name, category, roles1 to 256 hosts per call
whisper.assess(hosts)Whether a host is dangerous, qualified by coverageGate on coverage: no-data — coverage: no-data. Not in coverage. This is not a verdict — nothing was looked at. ≠ benign, and malicious-evidenced — coverage: malicious-evidenced. In coverage, with positive evidence of malice. fires at low bands
whisper.walk(host)A bounded structural neighborhood when identify has no direct matchDepth- and budget-bounded

Helpers

ProcedureWhat it answersNotes
PSL functionsRegistrable apex and public-suffix testswhisper.psl.tldPlusOne, whisper.psl.isPublicSuffix
whisper.topAsnsByPrefixCountThe ASNs announcing the most prefixesRanked list
Tor / TLS lookupsWhether an IP runs a Tor relay or emits a known TLS fingerprintwhisper.lookupTorRelay, whisper.lookupTlsFingerprint
whisper.search(token)A bounded, type-aware lookup of an unclassified token — IP, host, ASN, CIDR, prefix, or suffixUse it instead of an unanchored scan
db.labels(), db.relationshipTypes(), db.propertyKeys(), db.schema()The live schemaCheap, and they answer immediately

Every procedure

The tables above are the ones worth learning first. This one is the whole surface, generated from CALL db.procedures() — every procedure the engine registers, whether or not a page has been written about it. Mode is the engine's own: READ answers a question, WRITE changes something and needs a signed-in key.

ProcedureModeWhat it does
db.labelsREADList all node labels with row counts
db.relationshipTypesREADList all relationship types with source/target labels
db.propertyKeysREADList all property keys
db.schemaREADFull schema description (labels + types + counts)
db.schema.visualizationREADSchema graph for visualization
db.schema.nodeTypePropertiesREADPer-node-label property index
db.schema.relTypePropertiesREADPer-relationship-type property index
db.functionsREADList all available Cypher functions (this procedure)
db.proceduresREADList all registered procedures (this procedure)
dbms.componentsREADServer component listing (Neo4j-driver compat) — one row {name='whisper-ng', versions=[<ver>], edition='community'}.
whisper.versionREADServer version + build time — one row {version, buildTime}.
explainREADThreat-assessment explanation for an indicator (IP, hostname, ASN, CIDR)
whisper.explainREADAlias for explain
whisper.explain.bundleREADThreat-assessment as a single {verdict: Map} column (single-shape variant of explain)
whisper.historyREADHistorical WHOIS / BGP data for an indicator (auto-pivot)
whisper.history.whoisREADDomain WHOIS history (type-strict, single-shape)
whisper.history.bgpREADBGP routing history for IP / ASN / prefix (type-strict, single-shape)
whisper.quotaREADWhere the calling key stands right now. Ask the key, never a page.
whisper.variantsREADLookup variants of a hostname/domain
whisper.originsREADDiscover candidate origin IPs behind a CDN, scored by independent evidence
whisper.searchREADBounded analyst search — routes an untyped token to an exact index lookup (IPv4/IPv6/CIDR/ASN/hostname/exact ASN-name), a bounded FST prefix scan…
whisper.lookupTlsFingerprintREADTLS handshake fingerprint lookup — probes all 8 kinds (ja3/ja4/ja4s/ja4h/ja4x/ja4t/ja4tscan/jarm) or accepts a kind:hash composite.
whisper.lookupTorRelayREADTor exit-relay lookup — dual-input (a 40-hex Ed25519 fingerprint OR a single exit IPv4/IPv6 address).
whisper.psl.tldPlusOneREADRegistrable apex (eTLD+1) lookup via the Public Suffix List.
whisper.psl.isPublicSuffixREADTrue if the input matches a Public Suffix List entry.
whisper.psl.affiliationREADPSL submitter-affiliation lookup by private suffix or hostname.
whisper.threatIntel.candidateMultiTenantApexREADTop-K precomputed multi-tenant apex candidates from the threat-intel snapshot.
whisper.threatIntel.candidateSharedHostingIpREADTop-K precomputed shared-hosting IPV4 candidates from the threat-intel snapshot.
whisper.threatIntel.candidateCdnApexREADTop-K precomputed CDN / multi-tenant CA apex candidates from CT + PSL grouping.
whisper.topAsnsByPrefixCountREADTop-N ASNs ordered by announced-prefix count; served O(1) from a precomputed snapshot refreshed at BGP cadence.
whisper.asnCountriesREADASN count per country ((:ASN)-[:HAS_COUNTRY]->(:COUNTRY)); one row {country, asns} ordered by count DESC…
whisper.asnThreatDensityREADPer-ASN threat density — one row {asn, listedIps, announcedIpv4, densityRatio, routedPrefixes…
whisper.bgpDegreeDistributionREADGlobal BGP AS-adjacency degree DISTRIBUTION — one row per (in,out) degree bucket {inDegree, outDegree, asnCount} (all Long)…
whisper.audit.malformedHostnamesREADPer-zone HostnameValidator audit — partitions a bounded CHILD_OF scan into clean/malformed buckets.
whisper.asSetREADIRR as-set MEMBERSHIP lookup (NOT asset management) — one row per member ASN of the named as-set, served from the local IRR snapshot; no upstream call.
whisper.assessREADMaliciousness-verdict surface for a list of hosts — one row per host with {host, label, band, sub_labels[], signals[], coverage…
whisper.assessUrlREADURL-scoped maliciousness-verdict surface for a list of URLs — one row per URL {url, host, path, apex_band, path_band, band, coverage…
whisper.identifyREADHost-first vendor attribution over the GOLD RESOLVES_TO->IPV4->DELEGATED_TO->VENDOR path.
whisper.walkREADStructural-neighborhood fallback for a NOVEL host (whisper.walk(host[, depth[, budget_ms]])).
whisper.resolveREADRead-only DNS resolution for a single host — whisper.resolve(host).
whisper.exportREADRead-only bulk export of the threat corpus by label (malicious, ambiguous — coverage: ambiguous. In coverage, and the evidence points both ways., benign-allowlisted), for classifier distillation.
whisper.watchWRITECreate, list and cancel subscriptions to a query, a verdict or an indicator.
whisper.submitWRITEContribute an observation back — an indicator or a corroboration receipt. It is a write, so it needs a signed-in key.
whisper.agentsWRITEAgent control-plane front door. Disabled unless a deployment turns it on.

Rows generated from CALL db.procedures() YIELD name, signature, description, mode against https://graph.whisper.security, fetched 2026-08-09T21:11:53Z.

When to prefer a procedure over a traversal

Reach for the procedures first. They answer the hardest questions in one call, usually faster and cleaner than a hand-written deep traversal.

  • The logic runs server-side. explain() computes a score from feed count, feed weights, recency, and the threat density of the surrounding network, and hands back the arithmetic in factors[] with the named feeds in sources[]. Reproducing that by walking LISTED_IN edges yourself takes more hops and gives you less evidence.
  • A procedure replaces a slow scan. Where a hand-written query walks the graph itself, a procedure does the same work in one call, which makes it the standard fix for a query that runs long — alongside anchoring the query and adding a LIMIT. See Best Practices.
  • The output is decision-ready. A procedure returns labeled columns you can paste straight into a ticket.

One caveat: BGP routing history over a large network is slow. Keep a LIMIT on whisper.history() calls and expect a longer round trip.

Access

Some of these calls need an API key. Pass it in the X-API-Key header; sign in to get one — there is no card to enter.

Schema introspection

The db.* procedures describe the live schema, so you can confirm a label or edge exists before you anchor on it.

cypher · runnablegraph.whisper.securitySign in to run
CALL db.labels() YIELD label RETURN label ORDER BY label LIMIT 12

db.labels() lists every node label with its count. db.relationshipTypes() lists every edge type with its source and target labels. db.propertyKeys() lists every property name in use. db.schema() returns a structured overview of the whole graph and accepts a format argument ('json', 'markdown', or 'details'); db.schema.nodeTypeProperties() and db.schema.relTypeProperties() list the properties on each label and edge type. The full label, edge, and property model is on the Graph Schema pages.