Skip to content

Graph

GET /api/v1/graph/seed

Returns a BFS neighborhood of a seed node up to the requested depth. Used by the dashboard graph view for the initial paint.

If no seed is supplied the tenant’s hub node (highest connection_count, excluding archived nodes) is used automatically.

ParameterTypeDefaultDescription
seedstringID of the seed node. Omit to use the hub node.
depth1 | 2 | 31BFS depth. Higher values return larger neighborhoods.
{
"seed_id": "abc123",
"nodes": [
{
"id": "abc123",
"title": "Node title",
"para_category": "projects",
"para_item_id": "para-456",
"connection_count": 5,
"depth": 0
}
],
"edges": [
{
"source": "abc123",
"target": "def456",
"link_type": "related",
"weight": 0.9
}
],
"frontier_ids": ["def456"],
"meta": {
"node_count": 12,
"edge_count": 15,
"depth": 1
}
}

seed_id is null and all arrays are empty when the tenant has no nodes.

frontier_ids lists nodes at the deepest BFS hop that have additional unloaded neighbours. The dashboard uses these IDs to display the expansion affordance.

depth in each node is 0 for the seed itself and 1–3 for BFS hops.

StatusCondition
400depth is not 1, 2, or 3
401Missing or invalid authentication
404Seed node not found, belongs to another tenant, or is archived
429Rate limit exceeded

GET /api/v1/graph/neighbors/:id

Returns the one-hop neighbours of a single node. Intended for on-demand expansion when the user clicks a frontier node in the graph view.

All returned nodes carry newly_added: true so the client can apply a fade-in animation.

When there are more neighbours than limit the response includes a next_cursor value for retrieving the next page.

ParameterDescription
idID of the node whose neighbours to return.
ParameterTypeDefaultDescription
directionout | in | bothbothWhich link direction to follow.
limit1–20050Maximum number of neighbour nodes to return.
cursorstringPagination cursor from a previous response.

Cursors are opaque to clients. Do not parse or construct them. Internally they are base64url-encoded JSON:

  • direction=out or direction=in: encodes { dir, weight, source_id, target_id }. Results are ordered by weight DESC, source_id ASC, target_id ASC.
  • direction=both: encodes { out?: string, in?: string } — a composite of independent per-direction cursors. Each side pages independently; a side is absent once it is exhausted.

An invalid or expired cursor returns 400. Clients must not carry a cursor across seed changes.

{
"node_id": "abc123",
"nodes": [
{
"id": "def456",
"title": "Neighbor node",
"para_category": null,
"para_item_id": null,
"connection_count": 3,
"newly_added": true
}
],
"edges": [
{
"source": "abc123",
"target": "def456",
"link_type": "related",
"weight": 0.9
}
],
"next_cursor": null
}

next_cursor is null when there are no further pages.

StatusCondition
400Invalid direction, limit out of range, or invalid cursor
401Missing or invalid authentication
404Node not found, belongs to another tenant, or is archived
429Rate limit exceeded