> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cognee.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Visualization Payloads

> JSON payload builders behind the HTML visualization, and the HTTP endpoints that expose them

# Visualization payloads

[`visualize_graph()`](/guides/graph-visualization) renders a self-contained HTML page. The
functions on this page return the same data as plain dictionaries instead, so an external UI
or dashboard can render it itself. Both paths run through the same authorized, bounded graph
read and the same `preprocess()` step, so they cannot drift on the data — only on how each
packages it.

<Note>
  These builders are **not** re-exported on the top-level `cognee` module. Import them from
  `cognee.api.v1.visualize`.
</Note>

```python theme={null}
from cognee.api.v1.visualize import (
    visualize_graph_json,
    visualize_semantic_json,
    build_brains_payload,
    get_live_events,
    get_memory_provenance_payload,
)
```

## visualize\_graph\_json()

```python theme={null}
async def visualize_graph_json(
    include_session_events: bool = True,
    session_ids: list = None,
    user: Optional[User] = None,
    dataset: Optional[Union[str, UUID]] = "main_dataset",
    *,
    full: bool = False,
    query: Optional[str] = None,
    seed_node_ids: Optional[List[str]] = None,
    recall_result: Optional[Any] = None,
    neighborhood_depth: int = 2,
    neighborhood_seed_top_k: int = 10,
    max_nodes: int = 500,
) -> dict
```

The graph as a JSON-safe dict, **without** the semantic layout. Authorization, dataset
resolution and the bounded fetch are shared with `visualize_graph()`, so the same arguments
give you exactly the subgraph the HTML page would have shown — including the
[bounded-subgraph defaults](/guides/graph-visualization#additional-information).

### Parameters

<ParamField path="include_session_events" type="bool" default="True">Embed the caller's search and improve events in the payload as `search_events`.</ParamField>
<ParamField path="session_ids" type="list" default="None">Restrict embedded session events to these sessions.</ParamField>
<ParamField path="user" type="Optional[User]" default="None">User context for dataset access. Falls back to the default user.</ParamField>
<ParamField path="dataset" type="Optional[Union[str, UUID]]" default="'main_dataset'">Dataset name or id to read.</ParamField>
<ParamField path="full" type="bool" default="False">Return the entire graph instead of a bounded subgraph.</ParamField>
<ParamField path="query" type="Optional[str]" default="None">Query string whose nearest vector hits seed the subgraph.</ParamField>
<ParamField path="seed_node_ids" type="Optional[List[str]]" default="None">Explicit seed node ids for neighborhood expansion.</ParamField>
<ParamField path="recall_result" type="Optional[Any]" default="None">A `recall()` or search result whose graph provenance seeds the subgraph. Python-only — there is no HTTP equivalent.</ParamField>
<ParamField path="neighborhood_depth" type="int" default="2">*k*-hop expansion depth around the seeds.</ParamField>
<ParamField path="neighborhood_seed_top_k" type="int" default="10">Maximum number of seed nodes.</ParamField>
<ParamField path="max_nodes" type="int" default="500">Hard cap on nodes after expansion.</ParamField>

### Returns

`dict` — every field of the renderer's `PreprocessedGraph` snapshot, plus `search_events`:

| Key                                                                                                 | Contents                                                                                         |
| --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `nodes`, `links`                                                                                    | The graph itself, with per-node render metadata.                                                 |
| `color_maps`                                                                                        | Color assignments, keyed by `type` and `node_set`.                                               |
| `schema_graph`, `schema_data`                                                                       | The type-level view behind the Schema tab.                                                       |
| `memory_map`                                                                                        | The pipeline-structure view behind the Memory tab.                                               |
| `pipeline_stages`, `edge_classes`, `bundles`, `provenance_index`, `has_meaningful_topological_rank` | Derived values the bundled renderer reads directly; a client replacing those modules needs them. |
| `search_events`                                                                                     | The caller's search and improve events, or `[]`.                                                 |

Semantic positions are deliberately absent — see below.

```python theme={null}
payload = await visualize_graph_json(query="natural language processing")
print(len(payload["nodes"]), len(payload["links"]))
```

## visualize\_semantic\_json()

```python theme={null}
async def visualize_semantic_json(
    user: Optional[User] = None,
    dataset: Optional[Union[str, UUID]] = "main_dataset",
    *,
    full: bool = False,
    query: Optional[str] = None,
    seed_node_ids: Optional[List[str]] = None,
    recall_result: Optional[Any] = None,
    neighborhood_depth: int = 2,
    neighborhood_seed_top_k: int = 10,
    max_nodes: int = 500,
) -> dict
```

Semantic positions and clusters for the same subgraph, computed **on demand**. Pass the same
dataset/seed/depth/cap arguments you passed to `visualize_graph_json()` to lay out the same
subgraph.

This is the one call that fetches embeddings and runs the PCA (or UMAP) projection over them,
bounded to `SEMANTIC_NODE_CAP` = 2000 nodes. The HTML render computes the layout on every
render; splitting it out here means a client that never opens a semantic view never pays for
it.

### Returns

`dict` with `semantic_positions` and `semantic_clusters`. Both are `null` together — the
layout is best-effort, so no embeddings resolving *or* the projection failing yields
`{"semantic_positions": null, "semantic_clusters": null}` rather than an error.

## build\_brains\_payload()

```python theme={null}
async def build_brains_payload(
    user: Optional[User] = None,
    max_nodes: int = 500,
) -> dict
```

A small graph preview for **every** dataset the caller may read — their own, their tenant's,
and anything granted to a role they belong to. There is no `dataset` argument: this is the
overview across brains, not one brain.

### Returns

`dict` keyed by dataset id, each value `{"name", "nodes", "links", "node_set_colors"}` — not
the full `visualize_graph_json()` shape, since an overview does not need one dataset's worth
of schema/memory/pipeline detail multiplied by every dataset. `max_nodes` is applied
independently per dataset; there is no larger combined cap.

## get\_live\_events()

```python theme={null}
async def get_live_events(
    dataset_id: UUID,
    since: Optional[datetime] = None,
    user: Optional[User] = None,
) -> Dict[str, Any]
```

The delta of search and improve events since a cursor, for refreshing a timeline without
rebuilding the whole graph payload.

`dataset_id` gates *who* may call this — the same read-permission check every other
visualization entry point runs — not *which* events come back. Session events are collected
per user, matching the `search_events` already embedded in `visualize_graph_json()`. Raises
`PermissionDeniedError` when the dataset does not exist or the caller cannot read it.

### Returns

`{"events": [...], "cursor": <ISO datetime string or None>}`. Omit `since` on the first call
to get everything available, then pass the previous response's `cursor` straight back as the
next `since` — the filter is strict (`>`, not `>=`), so no event is delivered twice. When
nothing new has happened the response echoes back the `since` you sent, or `null` if you sent
none.

## get\_memory\_provenance\_payload()

```python theme={null}
async def get_memory_provenance_payload(
    include_memory: bool = False,
    scope_tenant_ids: Optional[List[Any]] = None,
    scope_user_ids: Optional[List[Any]] = None,
) -> dict
```

The [memory-provenance graph](/guides/memory-provenance) — the ownership and data-flow story
read purely from the relational database — packaged as a dict. Same scoping rules as
[`get_memory_provenance_graph()`](/guides/memory-provenance#scoping-in-multi-tenant-deployments):
in multi-tenant deployments you **must** pass a scope, or the read spans every tenant.

### Returns

`dict` in the same shape `visualize_graph_json()` returns (`nodes`, `links`, `color_maps`,
`schema_graph`, `memory_map`, and the rest) — not the raw `(nodes, edges)` tuple
`get_memory_provenance_graph()` returns.

## Over HTTP

Each builder above has an HTTP endpoint in front of it. `GET /api/v1/visualize/json`,
`GET /api/v1/visualize/semantic` and `GET /api/v1/schema/provenance/json` are JSON siblings of
existing HTML endpoints; `/brains` and `/live-events` have no HTML equivalent.
`POST /api/v1/visualize/multi` remains HTML-only.

| Endpoint                             | Returns                                                                                                                            |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `GET /api/v1/visualize/json`         | `visualize_graph_json()`'s payload. No semantic layout.                                                                            |
| `GET /api/v1/visualize/semantic`     | `semantic_positions` and `semantic_clusters` for the same subgraph.                                                                |
| `GET /api/v1/visualize/brains`       | `build_brains_payload()`'s per-dataset previews. Takes no `dataset_id` — only `max_nodes`.                                         |
| `GET /api/v1/visualize/live-events`  | `{"events": [...], "cursor": ...}` for the caller's session events.                                                                |
| `GET /api/v1/schema/provenance/json` | `get_memory_provenance_payload()`'s payload, always scoped to the authenticated caller's tenant (or user). Takes `include_memory`. |

All of them require authentication. The three that take a `dataset_id` enforce the same read
permission as `GET /api/v1/visualize`; `/brains` takes none and simply returns the datasets
the caller can read.

`/json` and `/semantic` accept the same query params as `GET /api/v1/visualize` —
`dataset_id` (required), `full`, `query`, `seed_node_ids`, `neighborhood_depth`,
`neighborhood_seed_top_k` and `max_nodes` — with the defaults listed above. Pass identical
arguments to both to get a graph and its semantic layout for the same subgraph.

```bash theme={null}
curl "$COGNEE_URL/api/v1/visualize/json?dataset_id=$DATASET_ID&query=natural+language+processing"
```

```json theme={null}
{
  "nodes": [ ... ],
  "links": [ ... ],
  "color_maps": { "type": { ... }, "node_set": { ... } },
  "schema_graph": { "nodes": [ ... ], "links": [ ... ] },
  "memory_map": { ... },
  "search_events": []
}
```

### Errors

JSON error bodies carry a fixed message and never the exception text — full detail is
server-logged instead.

* **403** — `/live-events` only, when the caller lacks read permission on the dataset (or it
  does not exist).
* **409** — the payload could not be built. Note that a semantic layout that cannot be
  computed is **not** an error: `/semantic` answers **200** with both fields `null`, and only
  returns 409 if the underlying graph fetch itself fails.

## See also

* [Graph Visualization](/guides/graph-visualization) — rendering the same data to an interactive HTML file
* [Memory Provenance](/guides/memory-provenance) — the ownership and data-flow projection behind `/schema/provenance`
* [Schema Inventory](/guides/schema-inventory) — a per-type summary of the graph, also available over HTTP
