---
title: "Create Graph Edge"
method: POST
path: "/api/v1/graph/edges"
tags: ["graph"]
---

# Create Graph Edge

`POST /api/v1/graph/edges`

## Request

- Base URL: `https://memory.kagura-ai.com` (the document declares no server; this is the origin it was published from)
- URL: `https://memory.kagura-ai.com/api/v1/graph/edges`
- Auth: none declared

Create a user-declared edge between two memories in a context (#1416).

REST twin of the MCP ``create_edge`` tool: both call the shared
``services.edge_service.create_declared_edge`` so the deterministic
declared-duplicate contract (#1321) and the #1403 supersede accept/self-heal
behave identically. The web UI's confirm→create flow for a supersede
suggestion posts here with ``edge_type="supersedes"``; accepting a stored
suggestion clears the ``supersede_candidate`` in the same transaction.

Authorization: mirrors the MCP ``create_edge`` tool and the REST
``remember`` / ``patch`` writers — workspace membership at ``member`` level
or higher (viewers are read-only). Resolution goes through
``resolve_context_for_workspace_read``, which returns a **uniform 404** on
every deny path (context not found, caller not a workspace member, viewer,
private-context non-creator, whitelist/agent-binding miss) so context
existence never leaks across workspace/privacy boundaries (CWE-639 / OWASP
A01). Both endpoints must be live memories in the resolved (workspace,
context) — a missing/out-of-scope/deleted endpoint is a 404, which also
closes the edge write-time invariant the ``/graph`` read paths defend
against.

Status: 201 when a new edge is created; 200 for updated / unchanged; 409
when a differing declared edge already exists (unless ``overwrite=true``).

## Headers

- `authorization` string, nullable

## Request body

- CreateEdgeRequest: Body for ``POST /graph/edges`` (#1416). Mirrors the MCP ``create_edge`` tool's inputs (edge_type default, weight/confidence ranges, overwrite semantics) so the two transports stay contract-consistent. ``context_id`` scopes the write; both endpoints must be live memories in that context (enforced by the route).
  - `context_id` string, uuid, required
  - `source_id` string, uuid, required
  - `target_id` string, uuid, required
  - `edge_type` string
  - `weight` number
  - `confidence` number
  - `overwrite` boolean

## Response `200`

Successful Response

- CreateEdgeResponse: Response for ``POST /graph/edges``. ``operation`` is one of created / updated / unchanged (conflict surfaces as a 409, never a 200 body). ``edge`` is the serialized post-state; ``previous`` is the pre-image when an existing non-protected edge was upserted.
  - `operation` string, required
  - `edge` object, nullable, required
  - `previous` object, nullable

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/kagura-ai/apis/kagura-memory-cloud.md) · [All operations](https://skmtc.dev/kagura-ai/apis/kagura-memory-cloud/llms.txt) · [OpenAPI document](https://skmtc.dev/kagura-ai/apis/kagura-memory-cloud/revisions/aa9df1a21db9?raw)
