Quickstart

Quickstart: your first query in five minutes

InvariantDB records, for each write, what the value is, when it was true (valid time), and when the system recorded it (recorded time). Pick the path that matches what you have:

For a longer walkthrough that covers backdated writes, agent memory, and MCP setup, see the 30-minute onboarding runbook.

Path 1 — AI agent via MCP

InvariantDB runs a Model Context Protocol server for each graph. One configuration entry gives your agent 28 tools: Cypher queries, full-text and vector search, schema and index listing, agent memory (remember, recall, record and replay episodes), documents, belief lineage, property provenance, and compliance procedures.

Clients that support OAuth sign-in

In your MCP client, add a remote (HTTP) MCP server with the URL https://invariantdb.com/graphs/{name}/mcp, replacing {name} with your full graph name. Do not add an Authorization header. When the approval page opens in your browser, paste your gq_ key and approve. See Connect with OAuth sign-in.

Clients configured with a JSON file

Clients that accept an HTTP server with headers in a JSON configuration file can use this block. Replace {name} with your full graph name. The file location and field names differ between clients; check your client’s MCP documentation.

{
  "mcpServers": {
    "invariantdb": {
      "type": "http",
      "url": "https://invariantdb.com/graphs/{name}/mcp",
      "headers": {
        "Authorization": "Bearer gq_paste_your_api_key_here"
      }
    }
  }
}

Restart or reload the client. The invariantdb tools appear in its tool list. The endpoint is https://invariantdb.com/graphs/{name}/mcp (HTTP POST, JSON-RPC 2.0). See the MCP tools reference.

Get an API key

Sign in to the dashboard and create a graph. POST /cloud/me/graphs returns the raw API key exactly once, so copy it immediately.

Example response (fictional values):

{
  "graph_id": "grp_…",
  "name": "a1b2c3_my-graph",
  "requested_name": "my-graph",
  "status": "active",
  "api_key": "gq_…",
  "api_key_id": "…",
  "api_key_prefix": "gq_Xy12a",
  "mcp_config": {
    "mcpServers": {
      "invariantdb": {
        "type": "http",
        "url": "https://…/graphs/a1b2c3_my-graph/mcp",
        "headers": { "Authorization": "Bearer gq_…" }
      }
    }
  },
  "already_existed": false
}

Use the value of name in every request; it includes a tenant prefix. On repeat calls with the same graph name, the response returns "api_key": null and "mcp_config": null. If you lost the original key, create a new one in the dashboard's API keys panel.

First query through your agent

"Show me every employee whose role changed in the last 90 days, with the timestamp the change was recorded versus when it took effect."

The agent writes Cypher, for example MATCH (p:Person) CALL db.propertyHistory(id(p), 'role') YIELD value, validFrom, txnAt RETURN p.name, value, validFrom, txnAt, and replies with the result.

Path 2 — SDK

Create the graph in the dashboard first and use the graph name it shows. The examples use a1b2c3_my-graph (fictional).

Python

pip install "https://sdk.invariantdb.com/python/invariantdb-0.8.0-py3-none-any.whl#sha256=15f7ef0dde4f77cb1c3971dbdf750a9f07ef1f9733ffdc166346ae2b108b65dc"

The Python SDK is not published on PyPI. Install it from this URL; pip checks the downloaded file against the SHA-256 in the URL.

from invariantdb import Client

db = Client("https://invariantdb.com", api_key="gq_...")
graph = "a1b2c3_my-graph"

rows = db.cypher(
    graph=graph,
    query="MATCH (p:Person) WHERE p.role = 'engineer' RETURN p.name, p.startDate",
).rows

# Agent memory in one call. The payload is a JSON string.
db.cypher(graph=graph, query="""
    CALL db.recordEpisode($s, 'observation', $text, '{"topic":"pricing"}')
""", parameters={"s": "conv-abc-123", "text": "User asked about pricing"})

Node

npm install https://sdk.invariantdb.com/node/invariantdb-0.8.0.tgz
import { Client } from 'invariantdb';

const db = new Client({ url: 'https://invariantdb.com', apiKey: process.env.INVARIANTDB_API_KEY });
const result = await db.cypher('a1b2c3_my-graph', 'MATCH (n) RETURN count(n) AS total');
console.log(result.asDicts());

Full SDK reference: SDK reference.

Path 3 — curl against the HTTP API

Graph creation uses a JWT (from the dashboard sign-in flow). Cypher queries use the raw gq_... API key returned by that create call.

KEY="gq_paste_your_api_key_here"
JWT="paste_your_dashboard_jwt_here"

# 1. Create a graph (idempotent; returns the raw api_key once).
#    The response field "name" is the full graph name.
curl -fsS -X POST -H "Authorization: Bearer $JWT" \
    -H "Content-Type: application/json" \
    --data '{"name": "my-graph"}' \
    https://invariantdb.com/cloud/me/graphs

GRAPH="<name from the create response>"

# 2. Run a Cypher query
curl -fsS -X POST -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    --data '{"query": "CREATE (p:Person {name: \"Alice\", role: \"engineer\"}) RETURN p"}' \
    "https://invariantdb.com/graphs/$GRAPH/cypher?format=flat"

# 3. Read it back, with each version of the node
curl -fsS -X POST -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    --data '{"query": "MATCH (p:Person {name: \"Alice\"}) CALL db.history(id(p)) YIELD version, timestamp, properties, validFrom, validTo RETURN version, timestamp, properties, validFrom, validTo"}' \
    "https://invariantdb.com/graphs/$GRAPH/cypher?format=flat"

# 4. Record who made a change (optional)
curl -fsS -X POST -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    --data '{"query": "MATCH (p:Person {name: \"Alice\"}) SET p.role = \"staff engineer\"", "provenance": {"actor": "hr-sync", "reason": "promotion", "confidence": 1.0}}' \
    "https://invariantdb.com/graphs/$GRAPH/cypher?format=flat"

format=flat returns plain JSON values; without it, values are tagged ({"string":"Alice"}). db.history returns timestamp, validFrom, and validTo in nanoseconds since the Unix epoch. From 1.4.2 it also returns kind and principal, the credential that wrote each version.

Read the provenance back with CALL db.propertyProvenance(id(p), 'role'). See Record who made a change for the fields and headers.

Full HTTP API: /openapi.yaml.

Next steps by goal

If you're building…Read
An AI agent that remembersAI memory primitives
An audit trail with a hash-chained historyCompliance dashboard
A research data API key that returns only noised aggregatesFeatures › Private mode
Anything in healthcare / finance / insurance / public sectorRegulated industries
The full feature catalogFeatures

When something doesn't work

Sign up free   Open the console