Skip to content
HTTP API
Skip navigation
HTTP API
View as Markdown

API Reference

The Whisper API in three endpoints — POST /api/query, GET /api/query, GET /api/query/stats. Start here, then open the one you need.

Published Last updated

In this section

On this page (4)

API Reference Documentation

The Whisper query API is three HTTP endpoints on https://graph.whisper.security. This page covers what they share — authentication, the response envelope, advisories — and links to a dedicated page for each endpoint with request and response details and ready-to-run code in five languages.

The endpoints

EndpointUse it for
POST /api/queryThe main query endpoint. Send Cypher as JSON, with parameter binding and batch statements. A form-encoded body is accepted too.
GET /api/queryThe same query from a URL parameter — for quick checks and browser-pasteable links.
GET /api/query/statsGraph-wide node and edge counts, the threat-intel summary, and the freshness and coverage of every computed layer. No key needed.

Authentication

Authentication works the same way on both query endpoints; the stats endpoint needs no key. Some queries run without a key; the deeper cross-layer traversals and the full procedure set need one. Pass it in the X-API-Key header; Authorization: Bearer <key> and Authorization: ApiKey <key> are also accepted. Sign in to get a key — there is no card to enter.

A missing, mistyped or unrecognized key does not fail the request. The API runs the query with reduced access and answers 200, so when a result is thinner than you expected, check the key before you debug the query. Confirm it was accepted with CALL whisper.quota(): the isAnonymous row must be false.

Response envelope

Every successful single-statement response has the same shape, whichever endpoint produced it:

FieldTypeDescription
columnsstring[]Column names in RETURN order.
rowsobject[]One object per row, keyed by column name.
statistics.rowCountnumberNumber of rows returned.
statistics.executionTimeMsnumberServer-side execution time. Excludes network latency, so your measured round trip will be larger.
statistics.cachedbooleanPresent only when the answer came from the result cache.
statistics.cachedExecutionTimeMsnumberPresent only on a cache hit: how long the original computation took.
rewrittenQuerystringPresent only when the engine rewrote your query to current label or edge names before running it. Update your query to the text it holds.
advisoriesobject[]Present only when the engine has a non-fatal note about how it interpreted the query. See Advisories.

A ;-separated batch returns a results array instead of this envelope; POST /api/query shows that shape.

Advisories

An advisory is a note on a successful response: the query ran, but the engine interpreted something in a way you should know about. Each entry carries a kind slug, a human-readable message, and, where a value was substituted, queried (what you asked for) and resolved (what was applied). Branch on kind; the message is written for a person and may change.

kindWhen you see itWhat to do
null-pagination-paramA parameter bound to SKIP or LIMIT resolved to null, so the clause was applied as SKIP 0 or as no limit at all.Pass a numeric value.
skip-past-cardinalitySKIP moved past the last row, so the page is empty.You have reached the end; stop paging.
projection-verdict-omittedA whole-node projection (RETURN n, keys(n), properties(n)) left out the reconciled threat-verdict properties.Send "projectionFull": true, or project the properties you need by name.
enrich-semanticswhisper.enrich() ran. The note explains its columns: owner is a network attribution, not a threat attribution, and rows are de-duplicated by name.Join results back to your input by name, never by position.
whois-parent-foldA WHOIS lookup on a subdomain was answered from its registrable parent domain; queried and resolved show both names.Read the record as the parent's.
schema-drift-rewriteThe query named a label or edge type by an older name and was rewritten; rewrittenQuery holds the text that ran.Update your query to the current names.
vdp-plane-emptyA computed layer the query relies on holds no data right now.Do not read an empty result from it as a clean absence. Check the layer's coverage in GET /api/query/stats and retry later.
vdp-anchor-emptyThe computed layer holds nothing for your anchor right now.Same as above: an absence here means "not available", not "none".
origins-all-candidates-withheldwhisper.origins() found candidate origin addresses but withheld every one of them.Read the message for the reason before drawing a conclusion.
explain-verdict-axis-unavailable, explain-score-unavailablePart of a verdict could not be computed for this call.Treat the missing part as unknown, not as clean; retry later.
advisories-truncatedMore advisories were produced than were returned.Fix the ones you can see and run again.