API Reference
The Whisper API in three endpoints: POST /api/query, GET /api/query, and GET /api/query/stats. Start here, then open the page for the endpoint you need.
On this page (5)
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, pagination — and links to a dedicated page for each endpoint with request and response details and ready-to-run code in five languages.
For the one-screen overview, see Whisper API; for the full status-code table, see Errors.
The endpoints
| Endpoint | Use it for |
|---|---|
POST /api/query | The main query endpoint. Send Cypher as JSON, with parameter binding and batch statements. |
GET /api/query | The same query from a URL parameter — for quick checks and browser-pasteable links. |
GET /api/query/stats | Graph-wide node and edge counts, precomputed and cached. |
Authentication
Authentication works the same way on all three endpoints. 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. An unrecognized key does not fail the request — it is treated as no key at all, so a run that returns less than you expected is worth re-checking against the header you actually sent. Sign in to get a key — there is no card to enter.
One header to know about: production sits behind a WAF that rejects some default programmatic user agents with HTTP 403. Send an explicit User-Agent (any descriptive string works) and you will not hit it.
Response envelope
Every successful single-statement response has the same shape, whichever endpoint produced it:
| Field | Type | Description |
|---|---|---|
columns | string[] | Column names in RETURN order. |
rows | object[] | One object per row, keyed by column name. |
statistics.rowCount | number | Number of rows returned. |
statistics.executionTimeMs | number | Server-side execution time. Excludes network latency, so your measured round trip will be larger. |
Prefix a query with EXPLAIN and the envelope carries a single plan column holding the query plan instead of results; the query does not execute. A NodeLookup at the leaf of the plan means your anchor is hitting the index; a label scan there is a warning that the query will be slow. See Syntax & Clauses for the clause details.
Pagination
There is no cursor. Page with a stable ORDER BY and walk SKIP forward: SKIP 0 LIMIT 15, then SKIP 15 LIMIT 15, and so on. Both clauses take a bound parameter as well as a literal — SKIP $offset returns the same rows a literal does — so a client can page without rebuilding the query string each time.
MATCH (sub:HOSTNAME)-[:CHILD_OF]->(:HOSTNAME {name: "google.com"})
RETURN sub.name AS subdomain
ORDER BY sub.name SKIP 0 LIMIT 15
Errors
Errors are RFC 7807-shaped — a type, a title, a status and a detail — and often carry a suggestions array proposing a rewrite. They are sent as Content-Type: application/json, not application/problem+json; so branch on the body's type field rather than on the content-type header. The full status-code table is on Errors.