POST /api/query

The main query endpoint. Send read-only Cypher as JSON, bind parameters, and run batch statements. Request and response reference with code in five languages.

Updated July 2026API Reference

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

HeaderRequiredNotes
Content-Type: application/jsonyesThe body is JSON.
X-API-KeynoAnonymous tier if omitted. Authorization: Bearer <key> / ApiKey <key> also accepted.
User-AgentrecommendedSend an explicit value to avoid a WAF 403.

Request body

FieldTypeRequiredDescription
querystringyesThe Cypher to run. ;-separated statements run as a batch.
parametersobjectnoNamed values for $param placeholders in the query.
timeoutnumbernoPer-query timeout in milliseconds. Clamped to your plan maximum and a global ceiling.

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}
}

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 LIMIT 5",
  "parameters": {"name": "google.com"}
}

Batch statements

;-separated statements in one query string run as a batch. The response is then a results array with one element per statement, each carrying its own result, outcome, and success fields.

Errors

Errors come back as application/problem+json. A depth-exceeded error includes both the actual and allowed depth so a client can downgrade automatically:

{
  "type": "https://whisper.security/errors/query-depth-exceeded",
  "title": "Query Depth Exceeded",
  "status": 400,
  "detail": "Query depth 3 exceeds maximum allowed depth of 2. Reduce traversal hops or upgrade your plan for deeper queries.",
  "actualDepth": 3,
  "maxAllowedDepth": 2
}

The full status-code table, Retry-After behavior, and quota rules are on Errors & Rate Limits. For the GET variant and the stats endpoint, see GET /api/query and GET /api/query/stats.