POST /api/query
The main query endpoint: send read-only Cypher as JSON, bind parameters, run batch statements. Reference with code in five languages.
On this page (7)
POST /api/query Documentation
POST /api/query is the main query endpoint. Send a read-only Cypher query as JSON and you get back columns and rows. It is the endpoint every runnable example in these docs goes through, and the one to use for anything real — it carries parameters cleanly, has no URL length limit, and supports batch statements.
Base URL: https://graph.whisper.security. Authentication is shared across the API and covered on the API Reference index.
Request headers
| Header | Required | Notes |
|---|---|---|
Content-Type: application/json | yes | The body is JSON. application/x-www-form-urlencoded is also accepted; see Form-encoded body. |
X-API-Key | no | Your key. Authorization: Bearer <key> / ApiKey <key> are also accepted. Without one the query runs with reduced access. |
User-Agent | recommended | Send a descriptive value that names your client. |
X-Whisper-Client, X-Whisper-Client-Version | no | Name and version of your integration, so support can tell your traffic apart. |
Idempotency-Key | no | Read only by CALL whisper.watch when it creates a watch; see Watches. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
query (alias q) | string | yes | The Cypher to run. Statements separated by a top-level ; run as a batch. |
parameters | object | no | Named values for $param placeholders in the query. The field is parameters, not params. |
timeout | number | no | Milliseconds to allow for this query. A value above what your access allows is lowered, not honored. |
projectionFull | boolean | no | Default false: a whole-node projection (RETURN n, keys(n), properties(n)) omits the reconciled threat-verdict properties and the response carries a projection-verdict-omitted advisory. Set true to include them. |
Call it
curl -s -A "whisper-client/1.0" \
-X POST https://graph.whisper.security/api/query \
-H "Content-Type: application/json" \
-H "X-API-Key: $WHISPER_API_KEY" \
-d '{"query": "MATCH (h:HOSTNAME {name: \"google.com\"})-[:RESOLVES_TO]->(ip:IPV4) RETURN ip.name AS ip LIMIT 5"}'A successful response is the standard envelope:
{
"columns": ["ip"],
"rows": [
{"ip": "142.250.154.100"},
{"ip": "142.250.154.139"},
{"ip": "142.250.191.14"},
{"ip": "142.251.110.100"},
{"ip": "142.251.110.102"}
],
"statistics": {"rowCount": 5, "executionTimeMs": 3}
}
On a cache hit, statistics also carries cached: true and cachedExecutionTimeMs. A response may add advisories or rewrittenQuery; the API Reference describes both.
Parameter binding
The request field is named parameters (not params). Use $name placeholders in the query and pass the values as an object. Parameters keep the query plan cacheable and avoid escaping headaches with quotes inside JSON:
{
"query": "MATCH (h:HOSTNAME {name: $name})-[:RESOLVES_TO]->(ip:IPV4) RETURN ip.name AS ip LIMIT 5",
"parameters": {"name": "google.com"}
}
Send the query string without its parameters object and the API answers 400 query-error with Missing parameter: $name and a missing_parameter suggestion — the placeholder is never treated as a literal.
Batch statements
Statements separated by a top-level ; in one query string run as a batch, in order. The response is then a results array with one element per statement instead of the single envelope:
{
"results": [
{
"result": {"columns": ["a"], "rows": [{"a": 1}], "rowCount": 1, "executionTimeMs": 0, "cacheHit": false},
"outcome": "OK",
"success": true
},
{
"outcome": "PARSE_ERROR",
"errorMessage": "Expected ')' but got 'RETURN' at position 18",
"errorType": "CypherParseException",
"success": false
}
]
}
outcome is one of OK, PARSE_ERROR, EXECUTION_ERROR or DEADLINE_EXCEEDED. A statement that succeeds carries its result; one that fails carries errorMessage and errorType instead, and the batch as a whole still answers 200. Check each element's success, not the HTTP status. Batching is for the JSON body only; the GET and form-encoded variants run a single statement.
Form-encoded body
The same endpoint accepts Content-Type: application/x-www-form-urlencoded. Send the query as q, with optional timeout and projectionFull fields. There is no parameters field in this form; use the JSON body when you need bindings.
curl -s -A "whisper-client/1.0" \
-X POST https://graph.whisper.security/api/query \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-API-Key: $WHISPER_API_KEY" \
--data-urlencode "q=RETURN 1 AS ok"
Errors
A failed request answers with an RFC 7807 problem document instead of the envelope above. Errors describes that body, lists every type slug and status this endpoint returns, and says what to do about each.
For the GET variant and the stats endpoint, see GET /api/query and GET /api/query/stats.