Skip to content

Latest commit

 

History

History
526 lines (421 loc) · 11.7 KB

File metadata and controls

526 lines (421 loc) · 11.7 KB

Morpheus HTTP API

Base URL: http://127.0.0.1:8080 (default)

Environment:

  • MORPHEUS_HTTP_ADDR: bind address (default 127.0.0.1:8080)
  • MORPHEUS_HTTP_ADMIN_TOKEN: when set, admin endpoints require Authorization: Bearer <token>
  • MORPHEUS_HTTP_CORS=permissive: enable permissive CORS

Response and Errors

Success response:

{ "data": { ... } }

Error response:

{ "code": "...", "message": "..." }

Pattern Clause

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, and context accept supported pattern forms.
  • mst consumes matched rooted paths as a weighted arborescence candidate set.
  • activation spreads activation over the induced matched subgraph.
  • similarity uses matched terminal vertices as the neighborhood for common-neighbor and Jaccard scoring.

User-visible pattern errors:

  • pattern_parse_error
  • pattern_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.

ID Format

Cell, vertex, edge IDs are base58-encoded 16-byte IDs. The server returns base58 strings for IDs.

Data Encoding

Graph vertex data and edge body use JSON objects (maps). Cell data accepts a generic HttpValue.

Map

{ "k": "v" }

Array

[1, 2, 3]

Typed Values

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, f64
  • char, string, bool, na
  • id (base58 string value)
  • bytes, small_bytes (array of byte numbers)
  • map, array
  • bool[], 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, or f64 depending on JSON parsing.
  • id decoding also accepts { "higher": <u64>, "lower": <u64> } for backward compatibility, but responses return base58 strings.

Health

GET /v1/health

Response:

{ "data": {} }

Admin Maintenance

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_schemas is currently always 0).

Response:

{
  "data": {
    "scanned_schemas": 12,
    "removed_vertices": 120,
    "removed_cells": 842,
    "removed_schemas": 0,
    "cleared_cell_index_entries": 962
  }
}

Graph Schemas (Morpheus)

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)

Cell Schemas (Neb)

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)

Graph Operations

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_id is optional. If multiple edges match from_id + to_id + schema, provide cell_id to 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

Query Operations

POST /v1/query

Request:

{
  "schema_name": "my_vertex",
  "selection": "(and (= score 1u64) (>= rank 10u64))",
  "ordering": "forward",
  "order_by_field": "score",
  "limit": 50,
  "offset": 0
}
  • selection must be a single Neb Lisp expression.
  • selection should use schema field names directly (for example score, rank).
  • ordering supports forward and backward.
  • order_by_field can be a field name string (for example "score") or a field id number (for example 123).

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_name or schema_id for 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
      }
    ]
  }
}

Graph Query Operations

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, and body.
  • direction uses the same wire values as graph DSL edge lists: out, in, none.
  • For /v1/graph/query/edges, direction is out for directed edges and none for 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
}
  • seed uses the same lookup shape as /v1/graph/query/vertices.
  • edge_schemas requires at least one schema ref (schema_name or schema_id).
  • direction supports outbound, inbound, and undirected.
  • max_depth defaults to 1 when 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_id describe the edge itself rather than the traversal step.
  • edges[*].direction reports how traversal reached that edge: out, in, or none.
  • edges[*].cell_id is the base58 edge cell ID for body-backed edges and null for 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 traverse
  • edge_schema_id (optional) - single numeric edge schema ID
  • edge_schema_names (repeatable) - edge schema names to traverse
  • edge_schema_name (optional) - single edge schema name
  • direction (optional) - outbound (default), inbound, or undirected
  • max_depth (optional) - defaults to 5
  • max_visited (optional) - defaults to 100000

Example:

GET /v1/graph/query/path/from/5QqkMJFr5s7J9wB8Q2kN1J/to/2m8JqZfC2MbgQfE7x4oP6R?edge_schema_names=my_edge&direction=outbound&max_depth=6

Response:

{
  "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, and type_list_id are base58-encoded IDs.
  • vertex_filter and edge_filter are Lisp expressions parsed by Dovahkiin.
  • edge_schema_ids and edge_schema_names can be mixed.

Response shape is the same as the GET path endpoint:

{
  "data": {
    "found": true,
    "path": ["...", "..."],
    "visited": 42
  }
}

Cell CRUD

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": {}
}

Legacy Schema Endpoints

These map to graph schema reads:

  • GET /v1/schemas
  • GET /v1/schemas/:name