Base URL: http://127.0.0.1:8080 (default)
Environment:
MORPHEUS_HTTP_ADDR: bind address (default127.0.0.1:8080)MORPHEUS_HTTP_ADMIN_TOKEN: when set, admin endpoints requireAuthorization: Bearer <token>MORPHEUS_HTTP_CORS=permissive: enable permissive CORS
Success response:
{ "data": { ... } }Error response:
{ "code": "...", "message": "..." }The DSL request bodies accept an additive pattern field for Cypher-like graph patterns. Existing
traverse and via fields remain supported, and the server lowers pattern into the same query
and graph execution engine.
Supported inline pattern syntax includes node and edge property maps such as
(root:Person {name: 'Alice'})-[:KNOWS {since: 2020}]->(:Person {active: true}).
The current implementation treats {...} as equality-only property maps with AND semantics across
entries. Supported literal values are strings, numbers, booleans, and null.
Phase-1 support:
query,subgraph,mst,path,paths,activation,similarity, andcontextaccept supported pattern forms.mstconsumes matched rooted paths as a weighted arborescence candidate set.activationspreads activation over the induced matched subgraph.similarityuses matched terminal vertices as the neighborhood for common-neighbor and Jaccard scoring.
User-visible pattern errors:
pattern_parse_errorpattern_bind_error
pattern_capability_error remains defined for unsupported endpoint or feature combinations, but the
current DSL endpoint matrix above does not use it.
Graph DSL requests that accept pattern still keep their endpoint-specific via object in the
request body. When pattern is present, the server derives edges, direction, and max_depth
from the pattern and still uses the remaining via fields for limits, filters, edge inclusion,
weighting, and ranking controls.
Cell, vertex, edge IDs are base58-encoded 16-byte IDs. The server returns base58 strings for IDs.
Graph vertex data and edge body use JSON objects (maps). Cell data accepts a generic HttpValue.
{ "k": "v" }[1, 2, 3]Use {"$type": "...", "value": ...} for non-JSON or specific types.
Examples:
{"$type":"u64","value":123}
{"$type":"id","value":"5QqkMJFr5s7J9wB8Q2kN1J"}
{"$type":"bytes","value":[1,2,3]}
{"$type":"u32[]","value":[1,2,3]}Supported $type values:
i8,i16,i32,i64,u8,u16,u32,u64,f32,f64char,string,bool,naid(base58 string value)bytes,small_bytes(array of byte numbers)map,arraybool[],char[],i8[],i16[],i32[],i64[],u8[],u16[],u32[],u64[],f32[],f64[],pos2d32[],pos2d64[],pos3d32[],pos3d64[],id[],string[],bytes[],small_bytes[]
Notes:
- Untagged numbers are interpreted as
i64,u64, orf64depending on JSON parsing. iddecoding also accepts{ "higher": <u64>, "lower": <u64> }for backward compatibility, but responses return base58 strings.
GET /v1/health
Response:
{ "data": {} }POST /v1/admin/nuke (admin)
- Removes all in-memory data cells across schemas.
- For vertex schemas, removal is performed through graph vertex deletion first (so edge lists are updated correctly).
- Graph edge and non-graph cells are then removed by cell id.
- Schemas are not deleted (
removed_schemasis currently always0).
Response:
{
"data": {
"scanned_schemas": 12,
"removed_vertices": 120,
"removed_cells": 842,
"removed_schemas": 0,
"cleared_cell_index_entries": 962
}
}GET /v1/graph/schemas
GET /v1/graph/schemas/:name
POST /v1/graph/schemas (admin)
Request:
{
"id": 0,
"name": "my_vertex",
"schema_type": "Vertex",
"key_field": null,
"fields": [],
"is_dynamic": true
}Edge schema example:
{
"name": "my_edge",
"schema_type": {
"Edge": {
"edge_type": "Directed",
"has_body": true
}
},
"fields": [],
"is_dynamic": true
}DELETE /v1/graph/schemas/:name (admin)
GET /v1/cell/schemas
GET /v1/cell/schemas/:name
POST /v1/cell/schemas (admin)
Request:
{
"id": 0,
"name": "my_cell",
"key_field": null,
"fields": [],
"is_dynamic": true,
"is_scannable": false
}DELETE /v1/cell/schemas/:name (admin)
POST /v1/graph/vertices (admin)
Request by schema name:
{
"schema_name": "my_vertex",
"data": {}
}Request by schema id:
{
"schema_id": 42,
"data": {},
"id": "5QqkMJFr5s7J9wB8Q2kN1J"
}GET /v1/graph/vertices/:id
DELETE /v1/graph/vertices/:id (admin)
PATCH /v1/graph/vertices/:id (admin)
Request:
{
"data": {
"nickname": "alice",
"score": {"$type": "u64", "value": 42}
}
}POST /v1/graph/edges (admin)
Request:
{
"from_id": "5QqkMJFr5s7J9wB8Q2kN1J",
"to_id": "3Yv8v4Cw1W5Hk9p2LxQw9Q",
"schema_name": "my_edge",
"body": {}
}DELETE /v1/graph/edges (admin)
Request:
{
"from_id": "5QqkMJFr5s7J9wB8Q2kN1J",
"to_id": "3Yv8v4Cw1W5Hk9p2LxQw9Q",
"schema_name": "my_edge",
"cell_id": "2m8JqZfC2MbgQfE7x4oP6R"
}cell_idis optional. If multiple edges matchfrom_id+to_id+ schema, providecell_idto disambiguate.
DELETE /v1/graph/edges/:id (admin)
- Deletes an edge by edge cell id (base58).
- This removes both the edge cell and edge-list references from both endpoint vertices.
GET /v1/graph/vertices/:id/edges?schema=<name-or-id>&direction=outbound|inbound|undirected
POST /v1/query
Request:
{
"schema_name": "my_vertex",
"selection": "(and (= score 1u64) (>= rank 10u64))",
"ordering": "forward",
"order_by_field": "score",
"limit": 50,
"offset": 0
}selectionmust be a single Neb Lisp expression.selectionshould use schema field names directly (for examplescore,rank).orderingsupportsforwardandbackward.order_by_fieldcan be a field name string (for example"score") or a field id number (for example123).
Field name and field id usage:
{
"schema_name": "my_vertex",
"selection": "(and (= score 1u64) (>= rank 10u64))",
"order_by_field": "score"
}{
"schema_id": 42,
"selection": "(and (= score 1u64) (>= rank 10u64))",
"order_by_field": 123456789,
"limit": 50,
"offset": 0
}- Use field names in
selection. - Use a field name string or field id number for
order_by_field. - Use either
schema_nameorschema_idfor schema references.
Response:
{
"data": [
{
"id": "5QqkMJFr5s7J9wB8Q2kN1J",
"header": {},
"data": {}
}
]
}POST /v1/query/explain
Request:
{
"schema_name": "my_vertex",
"selection": "(= score 1u64)",
"order_by_field": "score",
"limit": 100
}Response:
{
"data": {
"disjunction": false,
"impossible": false,
"clauses": [
{
"clause_kind": "range_scan",
"reason": "indexable_eq",
"estimated_rows": 42,
"effective_rows": 42,
"total_cost": 1.0
}
]
}
}These endpoints keep existing /v1/graph/* CRUD APIs unchanged and add Neb-powered graph lookup/traversal.
POST /v1/graph/query/vertices
Request shape is the same as /v1/query and returns matching graph vertices:
{
"schema_name": "my_vertex",
"selection": "(and (= score 1u64) (>= rank 10u64))",
"ordering": "forward",
"order_by_field": "score",
"limit": 50,
"offset": 0
}POST /v1/graph/query/vertices/explain
Request shape is the same as /v1/query/explain.
POST /v1/graph/query/edges
Query edge body cells using the same request shape as /v1/query:
{
"schema_name": "my_edge",
"selection": "(= weight 7u64)",
"order_by_field": "weight",
"limit": 20
}- Edge query currently supports edge schemas with body fields.
- Response includes
cell_id,from_id,to_id,direction,schema_id,edge_type, andbody. directionuses the same wire values as graph DSL edge lists:out,in,none.- For
/v1/graph/query/edges,directionisoutfor directed edges andnonefor undirected edges.
POST /v1/graph/query/traverse
Request:
{
"seed": {
"schema_name": "my_vertex",
"selection": "(= score 1u64)",
"limit": 20
},
"edge_schemas": [
{ "schema_name": "my_edge" }
],
"direction": "outbound",
"max_depth": 2
}seeduses the same lookup shape as/v1/graph/query/vertices.edge_schemasrequires at least one schema ref (schema_nameorschema_id).directionsupportsoutbound,inbound, andundirected.max_depthdefaults to1when omitted.- Traversal runs in two stages: Neb lookup for seed IDs first, then graph BFS expansion from those seeds.
- Duplicate discovered vertices are de-duplicated before vertex materialization in the final response.
edges[*].from_id/to_iddescribe the edge itself rather than the traversal step.edges[*].directionreports how traversal reached that edge:out,in, ornone.edges[*].cell_idis the base58 edge cell ID for body-backed edges andnullfor bodyless edges.
Response:
{
"data": {
"seed_ids": ["5QqkMJFr5s7J9wB8Q2kN1J"],
"vertices": [],
"edges": [
{
"cell_id": "3Yv8v4Cw1W5Hk9p2LxQw9Q",
"from_id": "5QqkMJFr5s7J9wB8Q2kN1J",
"to_id": "2m8JqZfC2MbgQfE7x4oP6R",
"direction": "out",
"schema_id": 77,
"edge_type": "Directed"
}
]
}
}GET /v1/graph/query/path/from/:source_id/to/:dest_id
Find a bounded BFS path between two vertex IDs (base58).
Query parameters:
edge_schema_ids(repeatable) - numeric edge schema IDs to traverseedge_schema_id(optional) - single numeric edge schema IDedge_schema_names(repeatable) - edge schema names to traverseedge_schema_name(optional) - single edge schema namedirection(optional) -outbound(default),inbound, orundirectedmax_depth(optional) - defaults to5max_visited(optional) - defaults to100000
Example:
GET /v1/graph/query/path/from/5QqkMJFr5s7J9wB8Q2kN1J/to/2m8JqZfC2MbgQfE7x4oP6R?edge_schema_names=my_edge&direction=outbound&max_depth=6Response:
{
"data": {
"found": true,
"path": [
"5QqkMJFr5s7J9wB8Q2kN1J",
"3Yv8v4Cw1W5Hk9p2LxQw9Q",
"2m8JqZfC2MbgQfE7x4oP6R"
],
"visited": 42
}
}POST /v1/graph/query/path
Advanced path query with richer filters.
Request:
{
"source_id": "5QqkMJFr5s7J9wB8Q2kN1J",
"dest_id": "2m8JqZfC2MbgQfE7x4oP6R",
"edge_schema_ids": [77],
"edge_schema_names": ["my_edge"],
"direction": "outbound",
"max_depth": 6,
"max_visited": 200000,
"type_list_id": "3Yv8v4Cw1W5Hk9p2LxQw9Q",
"vertex_filter": "(= status \"active\")",
"edge_filter": "(> weight 0.5f64)"
}Notes:
source_id,dest_id, andtype_list_idare base58-encoded IDs.vertex_filterandedge_filterare Lisp expressions parsed by Dovahkiin.edge_schema_idsandedge_schema_namescan be mixed.
Response shape is the same as the GET path endpoint:
{
"data": {
"found": true,
"path": ["...", "..."],
"visited": 42
}
}All cell CRUD endpoints require admin token when MORPHEUS_HTTP_ADMIN_TOKEN is set.
GET /v1/cells/:id
POST /v1/cells/:id
PUT /v1/cells/:id
DELETE /v1/cells/:id
Request (POST/PUT):
{
"schema_id": 123,
"data": {}
}These map to graph schema reads:
GET /v1/schemasGET /v1/schemas/:name