Skip to content

VecML GraphDB REST API (v0.6)

This document describes the HTTP/JSON interface exposed by the VecML Graph Database RESTful API, including:

  • Endpoint URL
  • Expected Request Body (JSON)
  • Response Format (JSON)
  • Relevant Details or Constraints
  • Example Requests / Responses

All RESTful API calls to the VecML cloud graph database should be sent to: https://graphdb.vecml.com/api. All endpoints use the HTTP POST method and require a JSON body unless otherwise noted. An empty body is rejected with 400 ("error_message": "Request Body Empty"), a body that is not valid JSON with 400 ("error_message": "Invalid JSON"), and a body whose objects and arrays are nested more than 512 levels deep with 400 ({"error_code": "InvalidParameter", "error_message": "request JSON is nested more than 512 levels deep"}).

Compressed requests

Any request body may instead be sent gzip-compressed: send {"compression_type": "gzip", "compressed_request": "<base64 of the gzipped JSON body>"}. The server decompresses compressed_request and handles the result as if it were the request body. If compressed_request is missing or cannot be decoded, the server responds with 400 ("error_message": "failed to decompress").

Rate and request size limit

For resource allocation and server stability, the server enforces a rate limit on the number of API calls per second. If exceeded, the server responds with:

400 Bad Request
Request limit reached, please try again later
Please avoid high-frequency API calls. For example, when inserting multiple entities, please use /batch_create_entity instead of iteratively calling /create_entity.

The size of each request cannot exceed 200MB.

Managing Unique IDs for the graph

Entities and Relationships are identified by UNIQUE string IDs. An entity and relationship can have the same name as they are defined in different namespaces.

Authentication (API key):

VecML RESTful API requests are authenticated through user's API key. The API key can be generated as follows:

  1. Go to https://account.vecml.com/user-api-keys , sign up for a free VecML account.
  2. After registration, you can get an API key by clicking "Create New API Key".
  3. This unique API key will only be seen once at the creation time, so please keep the API key safely. If you need to re-generate an API key, simply delete the previous one and then create a new key.

Pass the key in the user_api_key field of every request body. The server checks the key with the VecML account service (as an API key, a login token, or a temporary API key). An empty or rejected key returns 403 with {"error_code": "InvalidUser", "error_message": "unauthorized"}. A request that omits user_api_key returns 400 ("missing field: user_api_key"). Most endpoints check their required fields before the key, so a request with a missing field returns 400 even when the key is invalid. After a key is accepted, the server process caches it for 300 seconds and does not re-check it during that time, so a key that has been deleted can keep working for up to 5 minutes. Each check with the account service times out (5 seconds to connect, 10 seconds in total); a check that times out counts as a rejection.


An Example Workflow

import requests, json, time

# Configuration
API_KEY = "replace_this_with_your_api_key"
BASE_URL = "https://graphdb.vecml.com/api"
GRAPH_ID  = "cinema_graph"

def post(endpoint: str, payload: dict):
    url  = f"{BASE_URL}/{endpoint}"
    resp = requests.post(url, json=payload, timeout=30)
    print(f"[{resp.status_code}] {endpoint}")
    time.sleep(0.1)
    if not resp.ok:
        raise RuntimeError(resp.text)
    return resp.json() if resp.text else None

try:
  post("remove_graph", {"user_api_key": API_KEY, "graph_id": GRAPH_ID})
except Exception as e:
    # Fallback for any other exception
    print("Something went wrong:", e)
finally:
    pass

# 1️⃣  ─ Create the graph (returns 409 if it already exists; the remove_graph call above clears any earlier copy)
post("create_graph", {"user_api_key": API_KEY, "graph_id": GRAPH_ID})

# 2️⃣  ─ Add entities with attributes
entities = [
    ("entity1", {"name": "Tom Cruise", "type": "Person", "profession": "Actor",    "born": "1962"}),
    ("entity2", {"name": "Emily Blunt", "type": "Person", "profession": "Actor",    "born": "1983"}),
    ("entity3", {"name": "Christopher McQuarrie", "type": "Person", "profession": "Director","born": "1968"}),
    ("entity4", {"name": "Edge of Tomorrow", "type": "Movie",  "year": "2014", "genre": "Sci-Fi"}),
    ("entity5", {"name": "Mission Impossible – Fallout", "type": "Movie", "year": "2018", "genre": "Action"})
]
for eid, attrs in entities:
    post("create_entity", {"user_api_key": API_KEY, "graph_id": GRAPH_ID, "entity_id": eid})
    post("set_entity_attributes", {
        "user_api_key": API_KEY, "graph_id": GRAPH_ID,
        "entity_id": eid, "attributes": attrs
    })

# 3️⃣  ─ Create relationships with attributes
relationships = [
    ("entity1", "acted_in_movie", "entity4"),
    ("entity2", "acted_in_movie", "entity4"),
    ("entity3", "directed_movie", "entity4"),
    ("entity1", "acted_in_1", "entity5"),
    ("entity3", "directed_movie", "entity5")
]

relationships_attributes = [
    ("acted_in_movie", {"type": "acted_in", "media": "movie", "role_type": "on_screen"}),
    ("directed_movie", {"type": "directed", "media": "movie", "role_type": "behind_the_scenes"}),
    ("acted_in_1", {"type": "acted_in", "media": "movie", "role": "main_character", "role_type": "on_screen"})
]

for src, rel, dst in relationships:
    post("create_relationship", {
        "user_api_key": API_KEY, "graph_id": GRAPH_ID,
        "src_entity_id": src, "relationship_id": rel, "dest_entity_id": dst
    })

for rel, attrs in relationships_attributes:
    post("set_relationship_attributes", {
        "user_api_key": API_KEY, "graph_id": GRAPH_ID,
        "relationship_id": rel, "attributes": attrs
    })

# 4️⃣  ─ Build an Entity Attribute Index on the "type" attribute
post("create_entity_index", {
    "user_api_key": API_KEY, "graph_id": GRAPH_ID,
    "attribute_name": "type",
    "index_type":     "Attribute Index"
})

# 5️⃣  ─ Search the index for nodes with type "Person”
search_resp = post("search_entity_index", {
    "user_api_key": API_KEY, "graph_id": GRAPH_ID,
    "attribute_name": "type", "index_type": "Attribute Index",
    "attribute_value": "Person", "top_k": 5
})

print("\n≈≈≈ Search results for 'Person' ≈≈≈")
for idx, eid in enumerate(search_resp["entity_ids"], 1):
    print(f"{idx}. {eid}") # This should print out entity1, entity2, entity3

# 6️⃣  ─ Build a Relationship Attribute Index on the "role_type" attribute
post("create_relationship_index", {
    "user_api_key": API_KEY, "graph_id": GRAPH_ID,
    "attribute_name": "role_type",
    "index_type":     "Attribute Index"
})

# 7️⃣  ─ Search the index for edges with type "on_screen"
search_resp = post("search_relationship_index", {
    "user_api_key": API_KEY, "graph_id": GRAPH_ID,
    "attribute_name": "role_type", "index_type": "Attribute Index",
    "attribute_value": "on_screen", "top_k": 5
})

print("\n≈≈≈ Search results for 'on_screen' ≈≈≈")
for idx, eid in enumerate(search_resp["relationship_ids"], 1):
    print(f"{idx}. {eid}") # This should print out acted_in_movie, acted_in_1

Common Error Responses

Error responses are JSON bodies with error_code and error_message, except where a section says otherwise (a few vector-parsing errors return a plain-text body). In addition to the endpoint-specific failure codes noted throughout this guide, expect these shared responses:

  • 400 Bad Request — Missing fields, fields of the wrong JSON type, an empty or non-JSON body, a body nested more than 512 levels deep, invalid filters, vectors that fail parsing, or a name that the server cannot use (see the shared request checks below). A missing field returns "missing field: <name>", and a field of the wrong type or out of range returns "field with invalid value: <name>".
    Example:
    {
      "error_code": "InvalidParameter",
      "error_message": "missing field: graph_id"
    }
    
  • 403 Forbidden — The user_api_key is empty or is not accepted by the VecML account service.
    {
      "error_code": "InvalidUser",
      "error_message": "unauthorized"
    }
    
  • 404 Not Found — The referenced graph, entity, relationship, index, clustering, or checkpoint does not exist. Each section calls out which resource triggered the 404 when it differs from this general rule.
  • 409 Conflict — A create request attempted to reuse an existing identifier (graph, entity, index, clustering, etc.).
  • 500 Internal Server Error — Unexpected failures inside the service. The JSON body carries the internal error code in error_code; error_message is either a short explanation or the same error code name. An unexpected exception inside the server returns {"error_code": "Unknown", "error_message": "internal server error"}.

Request checks shared by all endpoints (each failure returns 400 with "error_code": "InvalidParameter" unless noted):

  • An integer field must be a JSON integer that fits the field's type: 4.0, 1.5, and true are rejected, as are an integer too large for the field and a negative value for a field that cannot be negative (such as transaction_id). The response is "field with invalid value: <name>".
  • A floating-point field must be a finite JSON number, within the 32-bit float range when the field is a 32-bit float.
  • Names that the server stores as directories (graph_id in /create_graph, the attribute_name of an index, vector names, model_name, and embedding_name) must not be empty, longer than 128 bytes, "." or "..", or contain /, \, or control characters. /create_graph, /remove_model, the create/remove index endpoints, and the requests that set vectors answer such a name with "invalid <field>: <reason>", for example "invalid graph_id: path separators are not allowed" or "invalid vector name: must not be empty". The same graph_id check, with the same 400 answer after the API key check, also runs in /remove_graph, /import_entities, /import_relationships, /entity_index_exists, /relationship_index_exists, /get_all_entity_index, /get_all_relationship_index, /get_all_types_entity_index and /get_all_types_relationship_index. The training and embedding endpoints reject a bad model_name or embedding_name as an invalid parameter of that endpoint (see their sections).
  • A request value whose JSON type the handler did not expect, and that no specific check catches, returns {"error_code": "InvalidParameter", "error_message": "invalid request: <parser message>"}.

When use_job is set to true, the HTTP response will be 202 Accepted with {"error_code": "Success", "job_id": "<id>"}. Poll /get_job_status or /get_job_result to retrieve the eventual payload shown in the Examples. If use_job is omitted, false, or not a JSON boolean, the request runs synchronously, except where a section notes otherwise.

1. User API

1.1 /create_graph

Description

Creates a graph under the specified graph_id for the user. The graph_id becomes the name of the graph's directory, so it must not be empty, longer than 128 bytes, "." or "..", or contain /, \, or control characters.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string"
}

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Response:

  • 400: graph_id cannot be used as a directory name ("error_code": "InvalidParameter", "error_message" is "invalid graph_id: <reason>", for example "invalid graph_id: must not be empty" or "invalid graph_id: path separators are not allowed"). This check runs after the API key check.
  • 409: Graph already exists ({"error_code": "AlreadyExists", "error_message": "AlreadyExists"}).

Example

Request:

POST /create_graph
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph"
}

Response:

{
  "error_code": "Success"
}

1.2 /remove_graph

Description

Removes the graph identified by graph_id for the given user, including all of its data on disk. The server waits for operations already running on this graph to finish, deletes the graph, and then returns 202. When the response arrives, the deletion is complete. Removal is all-or-nothing: if the graph's directory cannot be moved out of the way, the request fails with 500 and the graph stays listed and usable.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string"
}

Response

Success Response (202 Accepted):

{
  "error_code": "Success"
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 400: graph_id cannot be used as a directory name, checked as in /create_graph after the API key check ({"error_code": "InvalidParameter", "error_message": "invalid graph_id: <reason>"}, for example "invalid graph_id: must not be empty"). No graph can have such an ID.
  • 500: The graph's directory could not be moved out of the way ("error_code": "OpenFileFailed"). Nothing is removed.

Example

Request:

POST /remove_graph
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph"
}

Response:

{
  "error_code": "Success"
}

1.3 /get_graphs

Description

Retrieves the list of graph IDs available to the user. The order of graph_ids is not guaranteed. A user with no graphs gets an empty list.

Method

  • POST

Request Body

{
  "user_api_key": "string"
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "graph_ids": ["string", ...]
}

Example

Request:

POST /get_graphs
Content-Type: application/json

{
  "user_api_key": "api_key_123"
}

Response:

{
  "error_code": "Success",
  "graph_ids": ["graph1", "graph2", "graph3"]
}

1.4 /create_checkpoint

Description

Creates a transactional checkpoint for the specified graph. The server returns a transaction_id that can be supplied later to /revert_checkpoint in order to roll the graph back to the saved state. Checkpoint IDs start at 0 and increase by one for each new checkpoint of the graph.

Note

/create_checkpoint and /revert_checkpoint exist only when the server is built with transaction support (USE_TRANSACTION, off by default). On a server built without it, these routes are not registered.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "use_job": false
}
  • use_job (optional, boolean): Run as a background job. The job result (from /get_job_result) includes transaction_id, as the synchronous response does.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "transaction_id": integer
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").

Example

Request:

POST /create_checkpoint
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "transaction_id": 42
}

1.5 /revert_checkpoint

Description

Restores a graph to a previously recorded checkpoint identified by transaction_id. The server rolls back every checkpoint from the newest one down to and including transaction_id, then deletes those checkpoints. After a successful revert, transaction_id and all later checkpoint IDs can no longer be used. Only available when the server is built with transaction support (see /create_checkpoint).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "transaction_id": integer,
  "use_job": false
}
  • transaction_id (required, non-negative integer): Identifier returned by /create_checkpoint.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: transaction_id missing, or not a non-negative JSON integer ("field with invalid value: transaction_id").
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: transaction_id does not match an existing checkpoint ({"error_code": "TransactionNotFound", "error_message": "checkpoint does not exist"}).

Example

Request:

POST /revert_checkpoint
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "transaction_id": 42,
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2. Basic Graph API

2.1 /create_entity

Description

Creates a new entity (node) within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 409: Entity already exists ("error_message": "entity already exists").

Example

Request:

POST /create_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2.2 /remove_entity

Description

Removes an existing entity (node) from the specified graph, together with its attributes, its vectors, its index entries, and every relationship edge that starts or ends at it. Relationship IDs used by those edges, and their attributes, are kept (see /get_all_relationship_ids). The same entity_id can be created again later; it comes back with no attributes or edges.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message": "entity does not exist").

Example

Request:

POST /remove_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2.3 /set_entity_attributes

Description

Sets or updates textual attributes and optional vectors for an entity in the specified graph. Existing attributes or vectors with the same names will be overwritten; attributes and vectors not named in the request are left unchanged. Attributes are written before vectors, so if a vector fails to store, the attributes from the same request have already been saved. The exception is a vector that a linear index on its name cannot take (see below): it is refused before anything is written.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "attributes": { "key1": "value1", ... },
  "vectors": [
    {
      "name": "string",
      "type": "Float32" | "SFloat32",
      "vector_data": [ ... ]
    },
    ...
  ],
  "use_job": false
}
  • attributes (optional): JSON object mapping attribute names to string values. Every value must be a JSON string.
  • vectors (optional): Array of vector objects, each with a name (string, used as a directory name, so it must not be empty, longer than 128 bytes, "." or "..", or contain /, \, or control characters), a type ("Float32" or "SFloat32"), and vector_data. See appendix for more details about vector objects. Vector values are stored as 32-bit floats, so a value that a 32-bit float cannot represent exactly comes back rounded (for example, 2.72 is returned as 2.7200000286102295).

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: Missing user_api_key, graph_id, or entity_id, or vectors is not an array ("field is not a json array: vectors").
  • 400: attributes is not an object, or one of its values is not a string ({"error_code": "InvalidParameter", "error_message": "attributes are invalid"}).
  • 400 (plain-text body): A vectors element is not an object (missing vector field).
  • 400: A vectors element has no name, or its name is not a string ("invalid vector: \"name\" must be present and a string").
  • 400: A vector's type is missing or unsupported, or its vector_data does not match the type ("failed to parse vector"). Float32 values must be finite numbers that fit a 32-bit float; each SFloat32 entry must be an [index, value] pair with a non-negative integer index and such a value.
  • 400: A vector name cannot be used as a directory name: empty, longer than 128 bytes, "." or "..", or containing /, \, or control characters ("error_message" is "invalid vector name: <reason>").
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message": "entity does not exist").
  • 500: The vector was parsed but could not be stored, for example an empty Float32 vector_data ("error_code": "InvalidData").
  • 400: The vector's name has an Integer or Float Linear Index that cannot take the vector (see Index Types): error_code InvalidParameter for an empty vector, or, on an Integer Linear Index, a first value that is fractional or outside the 32-bit integer range; InvalidVectorType for an SFloat32 vector. The error_message is "a vector cannot be stored under its name (see the index on that name)". Nothing from the request is stored.

Example

Request:

POST /set_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "attributes": {
    "color": "red",
    "size": "large",
    "status": "active"
  },
  "vectors": [
    {
      "name": "vector_location",
      "type": "Float32",
      "vector_data": [3.25, -2.5]
    },
    {
      "name": "vector_word",
      "type": "SFloat32",
      "vector_data": [[5, -2.5], [42, 1.25], [69, -3]]
    }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2.4 /remove_entity_attributes

Description

Removes one or more textual attributes and/or vectors from an entity in the specified graph. Every name in attribute_names must exist on the entity, or the request fails with 404. Names in vector_names that the entity does not have are ignored.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "attribute_names": ["key1", "key2", ...],
  "vector_names": ["vec1", "vec2", ...],
  "use_job": false
}
  • attribute_names (optional): Array of attribute keys (strings) to remove.
  • vector_names (optional): Array of vector names (strings) to remove.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: attribute_names or vector_names is not an array of strings.
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message": "entity does not exist").
  • 404: One of attribute_names does not exist on the entity ("error_message": "attribute(s) does not exist").

Example

Request:

POST /remove_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "attribute_names": ["color", "size", "status"],
  "vector_names": ["vector_location", "vector_word"],
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2.5 /get_entity_attributes

Description

Retrieves values of specified textual attributes for an entity in the specified graph. values lists the values in the same order as attribute_names. If any requested attribute is missing, the whole request fails with 404.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "attribute_names": ["key1", "key2", ...],
  "use_job": false
}
  • attribute_names (required): Array of attribute keys (strings) to fetch.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "values": ["value1", "value2", ...]
}

Error Responses:

  • 400: attribute_names missing or not an array of strings.
  • 404: Graph, entity, or attribute(s) does not exist ("error_message" is "graph does not exist", "entity does not exist", or "attribute(s) does not exist").

Example

Request:

POST /get_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "attribute_names": ["color", "size", "status"],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "values": ["red", "large", "active"]
}

2.6 /get_all_entity_attributes

Description

Retrieves all textual attributes (key-value pairs) for an entity in the specified graph. If the entity has no attributes, the synchronous response contains "attributes": null (a background job returns {} instead).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "attributes": {
    "name1": "value1",
    "name2": "value2",
    ...
  }
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message": "entity does not exist").

Example

Request:

POST /get_all_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "attributes": {
    "color": "red",
    "size": "large",
    "status": "active"
  }
}

2.7 /get_entity_vectors

Description

Retrieves the named vectors (dense or sparse) for an entity in the specified graph. vectors lists one object per name, in the same order as vector_names. Every requested name must exist on the entity; otherwise the request fails with 500.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "vector_names": ["string", "string", ...],
  "use_job": false
}
  • vector_names (required): Array of vector names (strings) to fetch.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "string",
      "type": "Float32" | "SFloat32",
      "vector_data": [ /* float list or [ [index, value], ... ] */ ]
    },
    ...
  ]
}

See appendix for more details about vector objects. Vector values are stored as 32-bit floats, so a value that a 32-bit float cannot represent exactly comes back rounded (for example, 2.72 is returned as 2.7200000286102295).

Error Responses:

  • 400: vector_names missing or not an array of strings.
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message" is "<entity_id> does not exist", using the requested ID).
  • 500: A requested vector name does not exist on the entity ({"error_code": "InvalidData", "error_message": "error in parsing vectors"}).

Example

Request:

POST /get_entity_vectors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "vector_names": ["vector_location", "vector_word"],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "vector_location",
      "type": "Float32",
      "vector_data": [3.25, -2.5]
    },
    {
      "name": "vector_word",
      "type": "SFloat32",
      "vector_data": [
        [5, -2.5],
        [42, 1.25],
        [69, -3.0]
      ]
    }
  ]
}

2.8 /get_all_entity_vector_names

Description

Retrieves the list of vector names associated with an entity in the specified graph. The order of names is not guaranteed. An entity with no vectors returns an empty names list.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "use_job": false
}
  • use_job (optional, boolean): If true, the request runs as a background job. If omitted or false, the request runs synchronously and returns the response shown below.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "names": ["vec1", "vec2", ...]
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message": "entity does not exist").

Example

Request:

POST /get_all_entity_vector_names
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity"
}

Response:

{
  "error_code": "Success",
  "names": ["vector_location", "vector_word"]
}

2.9 /get_all_entity_vectors

Description

Retrieves all vectors (dense or sparse) and their data for an entity in the specified graph. Each vector object includes its name; the order of vectors is not guaranteed. An entity with no vectors returns "vectors": [].

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "string",
      "type": "Float32" | "SFloat32",
      "vector_data": [ /* float list or [ [index, value], ... ] */ ]
    },
    ...
  ]
}

See appendix for more details about vector objects. Vector values are stored as 32-bit floats, so a value that a 32-bit float cannot represent exactly comes back rounded (for example, 2.72 is returned as 2.7200000286102295).

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Entity does not exist ("error_message": "entity does not exist").

Example

Request:

POST /get_all_entity_vectors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_id": "entity",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "vector_location",
      "type": "Float32",
      "vector_data": [3.25, -2.5]
    },
    {
      "name": "vector_word",
      "type": "SFloat32",
      "vector_data": [
        [5, -2.5],
        [42, 1.25],
        [69, -3.0]
      ]
    }
  ]
}

2.10 /filter_entity

Description

Filters entities in the specified graph based on a provided JSON filter spec. Every entity in the graph is tested against the filter, and the matching IDs are returned in ascending internal-ID order (the order in which each entity ID was first created).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "entity_filter": { ... },
  "use_job": false
}
  • entity_filter (required): JSON filter spec combining conditions using and, or, not, and leaf operations like match_attribute, less_than, etc. See appendix for more details about filters.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "entity_ids": ["id1", "id2", ...]
}

Error Responses:

  • 400: Missing fields (e.g. "missing field: entity_filter"), or a filter spec the server cannot parse ({"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}). This includes combinators (and, or, xor, not) nested more than 64 levels deep, and a less_than value that is an integer outside the 32-bit signed integer range or a number outside the 32-bit float range.
  • 404: Graph does not exist ("error_message": "graph does not exist").

Example

Request:

POST /filter_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_filter": {
    "and": [
      {
        "match_attribute": {
          "key": "type",
          "values": ["Person"]
        }
      },
      {
        "less_than": {
          "key": "age",
          "value": 30
        }
      },
      {
        "not": {
          "attribute_exists": "inactive"
        }
      }
    ]
  },
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": ["Alice", "Charlie", "Bob"]
}

2.11 /create_relationship

Description

Creates a new relationship (edge) of type relationship_id from src_entity_id to dest_entity_id within the specified graph. Both entities must already exist.

relationship_id names a relationship that can be shared by many edges: the first edge that uses a new relationship_id creates it, and later edges with the same relationship_id reuse it. Attributes and vectors set with /set_relationship_attributes belong to the relationship_id, so every edge that uses it shares them. The server does not check for duplicate edges: calling this endpoint again with the same src_entity_id, relationship_id, and dest_entity_id adds a second identical edge and returns 200.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "src_entity_id": "string",
  "relationship_id": "string",
  "dest_entity_id": "string",
  "use_job": false
}
  • use_job (optional, boolean): If true, the request runs as a background job. If omitted or false, the request runs synchronously and returns the response shown below.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: src_entity_id or dest_entity_id does not exist ("error_message": "entity does not exist").

Example

Request:

POST /create_relationship
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "src_entity_id": "entity1",
  "relationship_id": "parent_of",
  "dest_entity_id": "entity2"
}

Response:

{
  "error_code": "Success"
}

2.12 /remove_relationship

Description

Removes an existing relationship (edge) of type relationship_id from src_entity_id to dest_entity_id within the specified graph. If the same edge was created more than once, one copy is removed per call. The relationship_id itself and its attributes and vectors are kept, even when no edge uses it any more, and it is still listed by /get_all_relationship_ids.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "src_entity_id": "string",
  "relationship_id": "string",
  "dest_entity_id": "string",
  "use_job": false
}
  • use_job (optional, boolean): If true, the request runs as a background job. If omitted or false, the request runs synchronously and returns the response shown below.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: src_entity_id or dest_entity_id is not a known entity ID ("error_message": "entity does not exist").
  • 404: relationship_id is unknown, or no edge src_entity_id → dest_entity_id with this relationship_id exists ("error_message": "relationship does not exist").

Example

Request:

POST /remove_relationship
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "src_entity_id": "entity1",
  "relationship_id": "parent_of",
  "dest_entity_id": "entity2"
}

Response:

{
  "error_code": "Success"
}

2.13 /set_relationship_attributes

Description

Sets or updates textual attributes and optional vectors for a relationship in the specified graph. The relationship_id must already have been created with /create_relationship. The attributes and vectors belong to the relationship_id, so they are shared by every edge that uses it. Existing attributes or vectors with the same names will be overwritten; attributes and vectors not named in the request are left unchanged. Attributes are written before vectors, so if a vector fails to store, the attributes from the same request have already been saved. The exception is a vector that a linear index on its name cannot take (see below): it is refused before anything is written.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "attributes": { "key1": "value1", ... },
  "vectors": [
    {
      "name": "string",
      "type": "Float32" | "SFloat32",
      "vector_data": [ ... ]
    },
    ...
  ],
  "use_job": false
}
  • attributes (optional): JSON object mapping attribute names to string values. Every value must be a JSON string.
  • vectors (optional): Array of vector objects, each with a name (string, used as a directory name, so it must not be empty, longer than 128 bytes, "." or "..", or contain /, \, or control characters), a type ("Float32" or "SFloat32"), and vector_data. See appendix for more details about vector objects. Vector values are stored as 32-bit floats, so a value that a 32-bit float cannot represent exactly comes back rounded (for example, 2.72 is returned as 2.7200000286102295).

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: Missing user_api_key, graph_id, or relationship_id, or vectors is not an array ("field is not a json array: vectors").
  • 400: attributes is not an object, or one of its values is not a string ({"error_code": "InvalidParameter", "error_message": "attributes are invalid"}).
  • 400 (plain-text body): A vectors element is not an object (missing vector field).
  • 400: A vectors element has no name, or its name is not a string ("invalid vector: \"name\" must be present and a string").
  • 400: A vector's type is missing or unsupported, or its vector_data does not match the type ("failed to parse vector"). Float32 values must be finite numbers that fit a 32-bit float; each SFloat32 entry must be an [index, value] pair with a non-negative integer index and such a value.
  • 400: A vector name cannot be used as a directory name: empty, longer than 128 bytes, "." or "..", or containing /, \, or control characters ("error_message" is "invalid vector name: <reason>").
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Relationship does not exist ("error_message": "relationship does not exist").
  • 500: The vector was parsed but could not be stored, for example an empty Float32 vector_data ("error_code": "InvalidData").
  • 400: The vector's name has an Integer or Float Linear Index that cannot take the vector (see Index Types): error_code InvalidParameter for an empty vector, or, on an Integer Linear Index, a first value that is fractional or outside the 32-bit integer range; InvalidVectorType for an SFloat32 vector. The error_message is "a vector cannot be stored under its name (see the index on that name)". Nothing from the request is stored.

Example

Request:

POST /set_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship",
  "attributes": {
    "color": "red",
    "size": "large",
    "status": "active"
  },
  "vectors": [
    {
      "name": "vector_location",
      "type": "Float32",
      "vector_data": [3.25, -2.5]
    },
    {
      "name": "vector_word",
      "type": "SFloat32",
      "vector_data": [[5, -2.5], [42, 1.25], [69, -3]]
    }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2.14 /remove_relationship_attributes

Description

Removes one or more textual attributes and/or vectors from a relationship in the specified graph. Every name in attribute_names must exist on the relationship, or the request fails with 404. Names in vector_names that the relationship does not have are ignored.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "attribute_names": ["key1", "key2", ...],
  "vector_names": ["vec1", "vec2", ...],
  "use_job": false
}
  • attribute_names (optional): Array of attribute names (strings) to remove.
  • vector_names (optional): Array of vector names (strings) to remove.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: attribute_names or vector_names is not an array of strings.
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Relationship does not exist ("error_message": "relationship does not exist").
  • 404: One of attribute_names does not exist on the relationship ("error_message": "attribute(s) does not exist").

Example

Request:

POST /remove_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship",
  "attribute_names": ["color", "size", "status"],
  "vector_names": ["vector_location", "vector_word"],
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

2.15 /get_relationship_attributes

Description

Retrieves values of specified textual attributes for a relationship in the specified graph. values lists the values in the same order as attribute_names. If any requested attribute is missing, the whole request fails with 404.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "attribute_names": ["key1", "key2", ...],
  "use_job": false
}
  • attribute_names (required): Array of attribute names (strings) to fetch.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "values": ["value1", "value2", ...]
}

Error Responses:

  • 400: attribute_names missing or not an array of strings.
  • 404: Graph, relationship, or attribute(s) does not exist ("error_message" is "graph does not exist", "relationship does not exist", or "attribute(s) does not exist").

Example

Request:

POST /get_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship",
  "attribute_names": ["color", "size", "status"],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "values": ["red", "large", "active"]
}

2.16 /get_all_relationship_attributes

Description

Retrieves all textual attributes (key-value pairs) for a relationship in the specified graph. If the relationship has no attributes, the synchronous response contains "attributes": null (a background job returns {} instead).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "attributes": {
    "name1": "value1",
    "name2": "value2",
    ...
  }
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Relationship does not exist ("error_message": "relationship does not exist").

Example

Request:

POST /get_all_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "attributes": {
    "color": "red",
    "size": "large",
    "status": "active"
  }
}

2.17 /get_relationship_vectors

Description

Retrieves the named vectors (dense or sparse) for a relationship in the specified graph. vectors lists one object per name, in the same order as vector_names. Every requested name must exist on the relationship; otherwise the request fails with 500.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "vector_names": ["string", "string", ...],
  "use_job": false
}
  • vector_names (required): Array of vector names (strings) to fetch.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "string",
      "type": "Float32" | "SFloat32",
      "vector_data": [ /* float list or [ [index, value], ... ] */ ]
    },
    ...
  ]
}

See appendix for more details about vector objects. Vector values are stored as 32-bit floats, so a value that a 32-bit float cannot represent exactly comes back rounded (for example, 2.72 is returned as 2.7200000286102295).

Error Responses:

  • 400: vector_names missing or not an array of strings.
  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Relationship does not exist ("error_message" is "<relationship_id> does not exist", using the requested ID).
  • 500: A requested vector name does not exist on the relationship ({"error_code": "InvalidData", "error_message": "error in parsing vectors"}).

Example

Request:

POST /get_relationship_vectors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship",
  "vector_names": ["vector_location", "vector_word"],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "vector_location",
      "type": "Float32",
      "vector_data": [3.25, -2.5]
    },
    {
      "name": "vector_word",
      "type": "SFloat32",
      "vector_data": [
        [5, -2.5],
        [42, 1.25],
        [69, -3.0]
      ]
    }
  ]
}

2.18 /get_all_relationship_vector_names

Description

Retrieves the list of vector names associated with a relationship in the specified graph. The order of names is not guaranteed. A relationship with no vectors returns an empty names list.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "use_job": false
}
  • use_job (optional, boolean): If true, the request runs as a background job. If omitted or false, the request runs synchronously and returns the response shown below.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "names": ["vec1", "vec2", ...]
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Relationship does not exist ("error_message": "relationship does not exist").

Example

Request:

POST /get_all_relationship_vector_names
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship"
}

Response:

{
  "error_code": "Success",
  "names": ["vector_location", "vector_word"]
}

2.19 /get_all_relationship_vectors

Description

Retrieves all vectors (dense or sparse) and their data for a relationship in the specified graph. Each vector object includes its name; the order of vectors is not guaranteed. A relationship with no vectors returns "vectors": [].

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "string",
      "type": "Float32" | "SFloat32",
      "vector_data": [ /* float list or [ [index, value], ... ] */ ]
    },
    ...
  ]
}

See appendix for more details about vector objects. Vector values are stored as 32-bit floats, so a value that a 32-bit float cannot represent exactly comes back rounded (for example, 2.72 is returned as 2.7200000286102295).

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").
  • 404: Relationship does not exist ("error_message": "relationship does not exist").

Example

Request:

POST /get_all_relationship_vectors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_id": "relationship",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "vectors": [
    {
      "name": "vector_location",
      "type": "Float32",
      "vector_data": [3.25, -2.5]
    },
    {
      "name": "vector_word",
      "type": "SFloat32",
      "vector_data": [
        [5, -2.5],
        [42, 1.25],
        [69, -3.0]
      ]
    }
  ]
}

2.20 /filter_relationship

Description

Filters relationships in the specified graph based on a provided JSON filter spec. The filter is tested against each relationship ID (and the attributes set on it with /set_relationship_attributes), not against individual edges. Matching relationship IDs are returned in ascending internal-ID order (the order in which each relationship ID was first created).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationship_filter": { ... },
  "use_job": false
}
  • relationship_filter (required): JSON filter spec combining conditions using and, or, not, and leaf operations like match_attribute, less_than, etc. See appendix for more details about filters.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "relationship_ids": ["id1", "id2", ...]
}

Error Responses:

  • 400: Missing fields (e.g. "missing field: relationship_filter"), or a filter spec the server cannot parse ({"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}). This includes combinators (and, or, xor, not) nested more than 64 levels deep, and a less_than value that is an integer outside the 32-bit signed integer range or a number outside the 32-bit float range.
  • 404: Graph does not exist ("error_message": "graph does not exist").

Example

Request:

POST /filter_relationship
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "relationship_filter": {
    "and": [
      {
        "match_attribute": {
          "key": "type",
          "values": ["Person"]
        }
      },
      {
        "less_than": {
          "key": "age",
          "value": 30
        }
      },
      {
        "not": {
          "attribute_exists": "inactive"
        }
      }
    ]
  },
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "relationship_ids": ["Alice", "Charlie", "Bob"]
}

2.21 /get_all_entity_ids

Description

Returns every entity ID that exists in the graph, in ascending internal-ID order (the order in which each entity ID was first created). The operation can run synchronously or be scheduled as a background job when the graph is large.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "entity_ids": ["node1", "node2", ...]
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").

Example

Request:

POST /get_all_entity_ids
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": ["Alice", "Bob", "Charlie"]
}

2.22 /get_all_relationship_ids

Description

Lists every relationship identifier (relationship_id) in the target graph, once per ID, in ascending internal-ID order (the order in which each ID was first created). This is not a list of edges: an ID shared by several edges appears once, and an ID stays listed after all of its edges are removed. Use /get_all_relationships to list edges.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "relationship_ids": ["rel1", "rel2", ...]
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").

Example

Request:

POST /get_all_relationship_ids
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "relationship_ids": ["r12", "r24", "r34"]
}

2.23 /get_all_relationships

Description

Retrieves every relationship edge as triplets (source, relationship_id, destination). Results follow the same serialization used throughout the API where edge tuples are expressed as [[src, dest], relationship_id]. Edges are grouped by source entity, with source entities in ascending internal-ID order. An edge created more than once appears once per copy.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "relationships": [
    [["Alice", "Bob"], "knows"],
    [["Bob", "Carol"], "reports_to"],
    ...
  ]
}

Error Responses:

  • 404: Graph does not exist ("error_message": "graph does not exist").

Example

Request:

POST /get_all_relationships
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "relationships": [
    [["Alice", "Bob"], "knows"],
    [["Bob", "Carol"], "collaborates_with"]
  ]
}

3. Graph Index API

3.1 /create_entity_index

Description

Creates an index on an entity attribute or vector to accelerate filtering or similarity search within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",       // "Attribute Index", "Fuzzy Attribute Index", "Vector Index", "Integer Linear Index" or "Float Linear Index"
  "dim": integer,               // optional, Vector Index only (default 0)
  "dist_type": "string",        // optional, Vector Index only (default "Euclidean")
  "use_job": false              // optional (default false)
}
  • attribute_name: Name of the attribute (Attribute Index, Fuzzy Attribute Index) or of the vector (Vector Index, Integer Linear Index, Float Linear Index) to index. The index is stored in a directory named after it, so the name must be 1 to 128 characters long, must not contain /, \ or control characters, and must not be . or ... Otherwise the server returns 400 (for example "invalid attribute_name: path separators are not allowed").
  • index_type: Type of index to create. It must be one of the five strings above, spelled exactly. See appendix for more details about index types.
  • dim, dist_type: Optional parameters that only a Vector Index uses. Other index types ignore them. If dim is omitted or 0, the server takes the dimension from the vectors already stored under attribute_name. See appendix for more details about dist_type. An unrecognized dist_type string is rejected with 400 ("field with invalid value: dist_type"). A Vector Index supports only Euclidean, InnerProduct, Cosine and WeightedJaccard; any other recognized dist_type returns 400 ("wrong parameters for the type of index") and no index is created.
  • Existing entities that carry the attribute or vector are indexed when the index is created. If the creation fails, no index is left behind, so the same index can be created later.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: "unknown index type", if index_type is not one of the five supported strings.
  • 400: "wrong parameters for the type of index", for example a Vector Index with no dim when no vectors are stored under attribute_name to take the dimension from, a Vector Index with an unsupported dist_type, or an Integer or Float Linear Index when a vector already stored under attribute_name has a first value the index cannot take (see Index Types). No index is left behind.
  • 400: Invalid attribute_name.
  • 404: Graph does not exist.
  • 409: Index already exists.

Example

Request (Vector Index):

POST /create_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_location",
  "index_type": "Vector Index",
  "dim": 384,
  "dist_type": "Cosine",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Attribute Index):

POST /create_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "size",
  "index_type": "Attribute Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Fuzzy Attribute Index):

POST /create_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "location",
  "index_type": "Fuzzy Attribute Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Integer Linear Index):

POST /create_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Integer Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Float Linear Index):

POST /create_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Float Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

3.2 /remove_entity_index

Description

Removes an existing index on an entity attribute or vector within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",
  "use_job": false
}
  • attribute_name: Name of the attribute or vector indexed. It must satisfy the same name rules as for index creation, otherwise the server returns 400.
  • index_type: Type of index to remove (one of the five index type strings). Only the index of this type on attribute_name is removed; the attribute and vector values stay on the items.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: "unknown index type".
  • 400: Invalid attribute_name.
  • 404: Graph does not exist.
  • 404: Index does not exist.

Example

Request:

POST /remove_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Integer Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

3.3 /entity_index_exists

Description

Checks whether an index exists on an entity attribute or vector within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",
  "use_job": false
}
  • attribute_name: Name of the attribute or vector indexed.
  • index_type: Type of index to check. An unrecognized index_type string is not an error; it returns "exists": false.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "exists": true|false
}

Error Responses:

  • 400: Invalid graph_id ("invalid graph_id: <reason>", same rules as /create_graph).
  • 404: Graph does not exist.

Example

Request:

POST /entity_index_exists
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Integer Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "exists": true
}

3.4 /get_all_entity_index

Description

Retrieves the names (attribute_name) of all attributes and vectors that have at least one index on entities within the specified graph. Each name appears once, even if it has several index types, and the order is not defined.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "indices": ["string", ...]
}

Error Responses:

  • 400: Invalid graph_id ("invalid graph_id: <reason>", same rules as /create_graph).
  • 404: Graph does not exist.

Example

Request:

POST /get_all_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "indices": ["size", "vector_location"]
}

3.5 /get_all_types_entity_index

Description

Retrieves the types of all indices that exist on a given entity attribute or vector within the specified graph. The list is empty if the attribute has no index.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "use_job": false
}
  • attribute_name: Name of the attribute or vector whose index types to list.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "types": ["type1", "type2", ...]
}

Error Responses:

  • 400: Invalid graph_id ("invalid graph_id: <reason>", same rules as /create_graph).
  • 404: Graph does not exist.

Example

Request:

POST /get_all_types_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "name",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "types": ["Attribute Index", "Vector Index"]
}

3.6 /search_entity_index

Description

Performs a search against an entity index by attribute value (exact for an Attribute Index, approximate for a Fuzzy Attribute Index) or by similarity to a provided vector, with optional entity-level filtering.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",
  // Provide exactly one of (depending on index type):
  "attribute_value": "string",      // Attribute Index, Fuzzy Attribute Index
  "vector": { "type": "Float32" | "SFloat32", "vector_data": [ ... ] },  // Vector, Integer Linear, Float Linear Index
  "top_k": integer,                 // optional, default 5
  "similarity_measure": "string",   // optional, default "Euclidean"
  "entity_filter": { ... },  // optional JSON filter spec
  "use_job": false                  // optional (default false)
}
  • attribute_value: String to search for. An Attribute Index returns the entities whose attribute value is exactly this string. A Fuzzy Attribute Index returns the closest entities by n-gram similarity.
  • vector: vector object for similarity search. See appendix for more details about vector objects. A Vector Index requires a dense Float32 query whose dimension equals the index dimension; an SFloat32 query or a different dimension returns 400 ("wrong parameters for the type of index"). The two linear indices compare only the first component.
  • Sending attribute_value to a vector-based index, or vector to an attribute-based index, returns 400 ("wrong parameters for the type of index").
  • top_k: Number of results to return (default 5). It must be an integer from 1 to 2147483647, for every index type; any other value returns 400 ("field with invalid value: top_k (must be an integer from 1 to 2147483647)"). An Attribute Index ignores top_k and returns every exact match.
  • similarity_measure: Only a Fuzzy Attribute Index uses this field, and it scores with Euclidean, Cosine, InnerProduct or BM25. A Vector Index always ranks by the dist_type it was created with, also when a filter is given, the linear indices rank by absolute difference, and an Attribute Index ignores it. See appendix for the accepted strings; an unrecognized string returns 400.
  • entity_filter (optional): JSON spec to filter returned entities. See appendix for more details about filters. The filter is applied by Fuzzy Attribute, Vector and linear indices, but an Attribute Index ignores it. With a linear index, entities rejected by the filter still count toward top_k, so fewer than top_k results can come back. With a Vector Index, the filter is applied during the approximate search, and the server scans the whole index exactly only when that search finds fewer than top_k matches, so filtered results are approximate, like unfiltered ones. A filter the server cannot parse returns 400 with {"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}.
  • JSON vector payloads must use Float32 or SFloat32; other types, or a malformed vector object, are rejected with 400 and a plain-text body field with invalid value: vector.
  • The linear indices compare the query's first component by value. For an Integer Linear Index it must be a whole number within the 32-bit integer range, so [2000] matches integer values imported from CSV. An empty vector_data, an SFloat32 query, or (for an Integer Linear Index) a fractional or out-of-range value returns 400 ("wrong parameters for the type of index").
  • Searching a Vector Index or a linear index that holds no vectors returns 200 with an empty list.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "entity_ids": ["id1", "id2", ...]
}

Error Responses:

  • 400: "must contain either attribute value or vector" or "can not contain both attribute value and vector".
  • 400: "unknown index type".
  • 400: "wrong parameters for the type of index".
  • 400: Missing or invalid fields, including an invalid top_k or filter.
  • 404: Graph does not exist.
  • 404: Index does not exist.

Example

Request (Attribute Index):

POST /search_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "Location",
  "index_type": "Attribute Index",
  "attribute_value": "Seattle",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": ["alice", "bob", "charlie", "dana", "evan"]
}

Request (Fuzzy Attribute Index):

POST /search_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "Name",
  "index_type": "Fuzzy Attribute Index",
  "attribute_value": "Tom",
  "top_k": 5,
  "entity_filter": {
    "match_attribute": {
      "key": "Occupation",
      "values": ["Actor"]
    }
  },
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": [
    "Tom Hanks",
    "Tom Cruise",
    "Tom Hardy",
    "Tom Holland",
    "Tom Wilkinson"
  ]
}

Request (Vector Index):

POST /search_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "Location",
  "index_type": "Vector Index",
  "vector": {
    "type": "Float32",
    "vector_data": [47.6061, -122.3328]
  },
  "top_k": 5,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": ["Bellevue", "Tacoma", "Vancouver", "Portland", "Spokane"]
}

Request (Integer Linear Index):

POST /search_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "Birth Year",
  "index_type": "Integer Linear Index",
  "vector": {
    "type": "Float32",
    "vector_data": [2000]
  },
  "top_k": 5,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": ["Alice", "Bob", "Charlie", "Dave", "Edward"]
}

Request (Float Linear Index):

POST /search_entity_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "Test Score",
  "index_type": "Float Linear Index",
  "vector": {
    "type": "Float32",
    "vector_data": [98.3]
  },
  "top_k": 5,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "entity_ids": ["Alice", "Bob", "Charlie", "Dave", "Edward"]
}

3.7 /create_relationship_index

Description

Creates an index on a relationship attribute or vector to accelerate filtering or similarity search within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",       // "Attribute Index", "Fuzzy Attribute Index", "Vector Index", "Integer Linear Index" or "Float Linear Index"
  "dim": integer,               // optional, Vector Index only (default 0)
  "dist_type": "string",        // optional, Vector Index only (default "Euclidean")
  "use_job": false              // optional (default false)
}
  • attribute_name: Name of the attribute (Attribute Index, Fuzzy Attribute Index) or of the vector (Vector Index, Integer Linear Index, Float Linear Index) to index. The index is stored in a directory named after it, so the name must be 1 to 128 characters long, must not contain /, \ or control characters, and must not be . or ... Otherwise the server returns 400 (for example "invalid attribute_name: path separators are not allowed").
  • index_type: Type of index to create. It must be one of the five strings above, spelled exactly. See appendix for more details about index types.
  • dim, dist_type: Optional parameters that only a Vector Index uses. Other index types ignore them. If dim is omitted or 0, the server takes the dimension from the vectors already stored under attribute_name. See appendix for more details about dist_type. An unrecognized dist_type string is rejected with 400 ("field with invalid value: dist_type"). A Vector Index supports only Euclidean, InnerProduct, Cosine and WeightedJaccard; any other recognized dist_type returns 400 ("wrong parameters for the type of index") and no index is created.
  • Existing relationships that carry the attribute or vector are indexed when the index is created. If the creation fails, no index is left behind, so the same index can be created later.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: "unknown index type", if index_type is not one of the five supported strings.
  • 400: "wrong parameters for the type of index", for example a Vector Index with no dim when no vectors are stored under attribute_name to take the dimension from, a Vector Index with an unsupported dist_type, or an Integer or Float Linear Index when a vector already stored under attribute_name has a first value the index cannot take (see Index Types). No index is left behind.
  • 400: Invalid attribute_name.
  • 404: Graph does not exist.
  • 409: Index already exists.

Example

Request (Vector Index):

POST /create_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_location",
  "index_type": "Vector Index",
  "dim": 384,
  "dist_type": "Cosine",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Attribute Index):

POST /create_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "size",
  "index_type": "Attribute Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Fuzzy Attribute Index):

POST /create_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "location",
  "index_type": "Fuzzy Attribute Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Integer Linear Index):

POST /create_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Integer Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Float Linear Index):

POST /create_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Float Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

3.8 /remove_relationship_index

Description

Removes an existing index on a relationship attribute or vector within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",
  "use_job": false
}
  • attribute_name: Name of the attribute or vector indexed. It must satisfy the same name rules as for index creation, otherwise the server returns 400.
  • index_type: Type of index to remove (one of the five index type strings). Only the index of this type on attribute_name is removed; the attribute and vector values stay on the items.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Error Responses:

  • 400: "unknown index type".
  • 400: Invalid attribute_name.
  • 404: Graph does not exist.
  • 404: Index does not exist.

Example

Request:

POST /remove_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Integer Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

3.9 /relationship_index_exists

Description

Checks whether an index exists on a relationship attribute or vector within the specified graph.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",
  "use_job": false
}
  • attribute_name: Name of the attribute or vector indexed.
  • index_type: Type of index to check. An unrecognized index_type string is not an error; it returns "exists": false.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "exists": true|false
}

Error Responses:

  • 400: Invalid graph_id ("invalid graph_id: <reason>", same rules as /create_graph).
  • 404: Graph does not exist.

Example

Request:

POST /relationship_index_exists
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "vector_time",
  "index_type": "Integer Linear Index",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "exists": true
}

3.10 /get_all_relationship_index

Description

Retrieves the names (attribute_name) of all attributes and vectors that have at least one index on relationships within the specified graph. Each name appears once, even if it has several index types, and the order is not defined.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "use_job": false
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "indices": ["string", ...]
}

Error Responses:

  • 400: Invalid graph_id ("invalid graph_id: <reason>", same rules as /create_graph).
  • 404: Graph does not exist.

Example

Request:

POST /get_all_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "indices": ["size", "vector_location"]
}

3.11 /get_all_types_relationship_index

Description

Retrieves the types of all indices that exist on a given relationship attribute or vector within the specified graph. The list is empty if the attribute has no index.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "use_job": false
}
  • attribute_name: Name of the attribute or vector whose index types to list.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "types": ["type1", "type2", ...]
}

Error Responses:

  • 400: Invalid graph_id ("invalid graph_id: <reason>", same rules as /create_graph).
  • 404: Graph does not exist.

Example

Request:

POST /get_all_types_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "name",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "types": ["Attribute Index", "Vector Index"]
}

3.12 /search_relationship_index

Description

Performs a search against a relationship index by attribute value (exact for an Attribute Index, approximate for a Fuzzy Attribute Index) or by similarity to a provided vector, with optional relationship-level filtering.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "attribute_name": "string",
  "index_type": "string",
  // Provide exactly one of (depending on index type):
  "attribute_value": "string",      // Attribute Index, Fuzzy Attribute Index
  "vector": { "type": "Float32" | "SFloat32", "vector_data": [ ... ] },  // Vector, Integer Linear, Float Linear Index
  "top_k": integer,                 // optional, default 5
  "similarity_measure": "string",   // optional, default "Euclidean"
  "relationship_filter": { ... },  // optional JSON filter spec
  "use_job": false                  // optional (default false)
}
  • attribute_value: String to search for. An Attribute Index returns the relationships whose attribute value is exactly this string. A Fuzzy Attribute Index returns the closest relationships by n-gram similarity.
  • vector: vector object for similarity search. See appendix for more details about vector objects. A Vector Index requires a dense Float32 query whose dimension equals the index dimension; an SFloat32 query or a different dimension returns 400 ("wrong parameters for the type of index"). The two linear indices compare only the first component.
  • Sending attribute_value to a vector-based index, or vector to an attribute-based index, returns 400 ("wrong parameters for the type of index").
  • top_k: Number of results to return (default 5). It must be an integer from 1 to 2147483647, for every index type; any other value returns 400 ("field with invalid value: top_k (must be an integer from 1 to 2147483647)"). An Attribute Index ignores top_k and returns every exact match.
  • similarity_measure: Only a Fuzzy Attribute Index uses this field, and it scores with Euclidean, Cosine, InnerProduct or BM25. A Vector Index always ranks by the dist_type it was created with, also when a filter is given, the linear indices rank by absolute difference, and an Attribute Index ignores it. See appendix for the accepted strings; an unrecognized string returns 400.
  • relationship_filter (optional): JSON spec to filter returned relationships. See appendix for more details about filters. The filter is applied by Fuzzy Attribute, Vector and linear indices, but an Attribute Index ignores it. With a linear index, relationships rejected by the filter still count toward top_k, so fewer than top_k results can come back. With a Vector Index, the filter is applied during the approximate search, and the server scans the whole index exactly only when that search finds fewer than top_k matches, so filtered results are approximate, like unfiltered ones. A filter the server cannot parse returns 400 with {"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}.
  • JSON vector payloads must use Float32 or SFloat32; other types, or a malformed vector object, are rejected with 400 and a plain-text body field with invalid value: vector.
  • The linear indices compare the query's first component by value. For an Integer Linear Index it must be a whole number within the 32-bit integer range, so [2000] matches integer values imported from CSV. An empty vector_data, an SFloat32 query, or (for an Integer Linear Index) a fractional or out-of-range value returns 400 ("wrong parameters for the type of index").
  • Searching a Vector Index or a linear index that holds no vectors returns 200 with an empty list.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "relationship_ids": ["id1", "id2", ...]
}

Error Responses:

  • 400: "must contain either attribute value or vector" or "can not contain both attribute value and vector".
  • 400: "unknown index type".
  • 400: "wrong parameters for the type of index".
  • 400: Missing or invalid fields, including an invalid top_k or filter.
  • 404: Graph does not exist.
  • 404: Index does not exist.

Example

Request:

POST /search_relationship_index
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "attribute_name": "Location",
  "index_type": "Fuzzy Attribute Index",
  "attribute_value": "Seattle",
  "top_k": 5,
  "relationship_filter": {
    "or": [
      {
        "match_attribute": {
          "key": "Occupation",
          "values": ["Software Engineer", "Analyst"]
        }
      },
      {
        "less_than": {
          "key": "Age",
          "value": 30
        }
      }
    ]
  },
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "relationship_ids": ["alice", "bob", "charlie", "dana", "evan"]
}

4. Graph Algorithms

Behavior shared by the endpoints in this chapter

  • All endpoints accept POST only. "Node" IDs are entity IDs.
  • use_job (optional, default false): only the JSON boolean true submits a job. The response is then 202 Accepted with {"error_code": "Success", "job_id": "..."}, and the payload shown under Response is read later with /get_job_result. A missing or non-boolean use_job runs the request synchronously. In job mode, request validation errors (400, 403) are still returned immediately, but failures found while running (such as a missing graph or entity) are reported in the job result (error_code, error_message) rather than as HTTP status codes.
  • A missing or wrongly typed field returns 400 with a JSON body, for example {"error_code": "InvalidParameter", "error_message": "missing field: graph_id"}. Integer fields must be JSON integers that fit the field's type: 4.0, 1.5, true or a value out of range returns 400 (field with invalid value: <field>). Number fields must be finite, and a 32-bit float field (such as delta) also rejects values beyond the float range. An integer count that is negative, or 0 where a positive value is required, returns 400 with the plain-text body field with invalid value: <field>.
  • An invalid user_api_key returns 403 (InvalidUser, unauthorized). An unknown graph_id returns 404 with "error_message": "graph does not exist". An unknown node ID returns 404 with "error_message": "entity does not exist" unless an endpoint says otherwise.
  • node_filters / edge_filters: a node or relationship is used only if it satisfies every filter in the array (see Filters). A filter object that cannot be parsed returns 400 with {"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}. This includes a filter nested more than 64 levels deep and a less_than integer outside the 32-bit int range. The check happens before a job is queued, so it also applies with use_job. /find_k_hop applies its filters per hop instead.
  • Edge weights, capacities and node weights are attribute values parsed as numbers. Each endpoint states what happens to a missing, non-numeric or negative value. The value nan counts as non-numeric.
  • Errors not listed for an endpoint return 500 with error_message set to the error code name, for example {"error_code": "InvalidParameter", "error_message": "InvalidParameter"}. A request value of the wrong JSON type that a handler does not check itself returns 400 with "error_message": "invalid request: <parser message>".
  • Distances, weights and scores are returned as 32-bit floats and serialized as JSON doubles, so 0.19 appears as 0.1899999976158142. Values such as 2.0 or 0.25 appear exactly.

4.0 /get_neighbors

Description

Returns the immediate neighbors of src_entity_id. The optional type flag controls directionality. Runs synchronously (there is no use_job).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "src_entity_id": "string",
  "type": 3
}
  • src_entity_id: Entity whose neighbors to return.
  • type (optional, integer): 1 (outbound only), 2 (inbound only), or 3 (both). Defaults to 3 when omitted. The value is used as a bit mask (truncated to 8 bits; bit 1 = outbound, bit 2 = inbound), so 0, or any value with neither bit set, returns an empty list.

Response

{
  "error_code": "Success",
  "neighbors": [
    { "entity_id": "string", "relationship_id": "string" },
    ...
  ]
}

There is one entry per relationship, so an entity linked by several relationships appears several times. With type 3, inbound neighbors are listed before outbound neighbors. An entity with no matching relationships returns "neighbors": [].

Error Responses:

  • 400: src_entity_id missing, or type not an integer.
  • 404: Graph does not exist (graph does not exist).
  • 404: Entity does not exist (entity does not exist).

Example

Request:

POST /get_neighbors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "src_entity_id": "entity1",
  "type": 1
}

Response:

{
  "error_code": "Success",
  "neighbors": [
    { "entity_id": "entity2", "relationship_id": "knows" },
    { "entity_id": "entity3", "relationship_id": "works_with" }
  ]
}

4.1 Shortest Path Algorithms

4.1.1 /find_k_hop

Description

Finds all entities reachable within k hops from src_entity_id with a breadth-first traversal, optionally restricting each hop with entity and relationship predicates. Supports synchronous execution or job submission.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "src_entity_id": "string",
  "type": 1,
  "k": 2,
  "entity_filters": [ { ... } ],
  "relationship_filters": [ { ... } ],
  "use_job": false
}
  • src_entity_id: Starting entity for the hop traversal.
  • type (required, integer): 1 (outbound), 2 (inbound), or 3 (bidirectional). Used as the same bit mask as in /get_neighbors; 0 returns empty results.
  • k (required, integer ≥ 1): Maximum hop count. 0 or a negative value returns 400 with the plain-text body field with invalid value: k.
  • entity_filters / relationship_filters (optional): Per-hop predicate arrays (see Filters). When present and non-empty, each array must contain exactly k filters: entity_filters[i] must be satisfied by every entity reached at hop i + 1, and relationship_filters[i] by every relationship traversed at hop i + 1. An array of any other length returns 400 with "error_message": "Incorrect length for filters".
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "entity_ids": ["id1", "id2", ...],
  "relationships": [
    [["src", "dst"], "relationship_id"],
    ...
  ]
}
  • entity_ids: each reachable entity once, in breadth-first order (by hop count). The source entity is not included.
  • relationships: one entry per entity in entity_ids, giving the relationship through which it was first reached. The pair is [from, to] in traversal direction (from was reached earlier), so with inbound traversal it is the reverse of the stored relationship direction.

Error Responses:

  • 400: Missing field, a filter field that is not an array, a filter array whose length is not k (Incorrect length for filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist) or source entity not found (entity does not exist).

Example

Request:

POST /find_k_hop
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "src_entity_id": "Tom Cruise",
  "type": 1,
  "k": 2,
  "entity_filters": [
    {
      "match_attribute": {
        "key": "type",
        "values": ["Person"]
      }
    },
    { "true": {} }
  ],
  "use_job": false
}

Hop 1 only enters entities whose type is Person; hop 2 accepts any entity.

Response:

{
  "error_code": "Success",
  "entity_ids": ["Emily Blunt", "Edge of Tomorrow"],
  "relationships": [
    [["Tom Cruise", "Emily Blunt"], "friend"],
    [["Emily Blunt", "Edge of Tomorrow"], "acted_in"]
  ]
}

4.1.2 /dijkstra

Description

Runs Dijkstra's single-source shortest path algorithm from one or more source nodes, optionally constraining the graph with attribute filters and returning explicit paths.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_ids": ["string", ...],
  "target_node_ids": ["string", ...],
  "weight_attr_name": "string",
  "is_undirected": false,
  "return_paths": false,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • source_node_ids: Array of one or more starting node IDs (required). With several sources, each distance is measured from the nearest source. An empty array returns 500 (InvalidParameter).
  • target_node_ids (optional): Limit destinations; omit or empty to compute all reachable nodes. The search stops once every target has been settled.
  • weight_attr_name (optional): Relationship attribute holding the edge weight. Omit it to give every edge weight 1 (distances are hop counts). A negative value is treated as 0; a missing or non-numeric value as 1.
  • is_undirected (optional, default false): When false, only outbound relationships are followed; when true, relationships are followed in both directions.
  • return_paths (optional, default false): When true, return edge-by-edge paths.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "distances": [["node_id", 2.0], ...],
  "reachable": [true, ...],
  "paths": [
    [
      [["src", "mid"], "rel_id"],
      [["mid", "dst"], "rel_id"]
    ],
    ...
  ]
}
  • distances: with target_node_ids, one [node_id, distance] entry per target in request order, with -1.0 for an unreachable target. Without targets, one entry for every reached node, including the sources (distance 0.0); the order is breadth-first discovery order when weight_attr_name is omitted and unspecified otherwise.
  • reachable: one boolean per distances entry, in the same order; false marks an unreachable target. Without targets every entry is true, since only reached nodes are listed. Use it rather than testing for -1.0.
  • paths: omitted unless return_paths is true. There is one path per target, in target order, so paths[i] belongs to distances[i]; an unreachable target gets []. Each path lists its edges from the source to the target, as in /astar, /spfa and /delta_stepping. Each edge is [[from, to], relationship_id] in traversal direction. A target that is itself a source has an empty path. Without target_node_ids, paths is [].

Error Responses:

  • 400: source_node_ids missing, source_node_ids / target_node_ids not an array of strings (field with invalid value: source_node_ids), a filter field that is not an array, or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or a source or target ID not found (entity does not exist).
  • 500: Empty source_node_ids.

Example

Request:

POST /dijkstra
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "source_node_ids": ["1"],
  "target_node_ids": ["4"],
  "weight_attr_name": "weight",
  "return_paths": true,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "distances": [["4", 2.0]],
  "reachable": [true],
  "paths": [
    [
      [["1", "3"], "r13"],
      [["3", "4"], "r34"]
    ]
  ]
}

4.1.3 /astar

Description

Computes shortest paths with the A* heuristic algorithm. The heuristic for a node is the smallest Euclidean distance between the node's coordinate vector (coor_attr_name) and the coordinate vector of any target.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_ids": ["string", ...],
  "target_node_ids": ["string", ...],
  "coor_attr_name": "string",
  "weight_attr_name": "string",
  "is_undirected": false,
  "return_paths": false,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • source_node_ids: Array of one or more starting nodes (required). An empty array returns 500 (InvalidParameter).
  • target_node_ids: Array of one or more destination nodes (required). An empty array returns 500 (InvalidParameter). The search stops once every target has been settled.
  • coor_attr_name (required): Name of a dense Float32 entity vector holding the node's coordinates. A node without this vector gets heuristic 0, and if any target lacks it the heuristic is 0 for every node (plain Dijkstra). No error is raised for missing vectors. Where coordinates are present, results are true shortest distances only when the Euclidean distance between coordinates never exceeds the remaining path cost.
  • weight_attr_name (optional): Relationship attribute holding the edge weight; omit for unit weights. A negative value is treated as 0; a missing or non-numeric value as 1.
  • is_undirected (optional, default false): When false, only outbound relationships are followed; when true, both directions.
  • return_paths (optional, default false): When true, include path details in the response.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

Same fields as /dijkstra, with these differences:

  • distances: one entry per target in request order, -1.0 for an unreachable target.
  • reachable: one boolean per distances entry, false for an unreachable target.
  • paths (only when return_paths is true): one path per target in request order, including [] for an unreachable target. Edges are listed from the source to the target.

Error Responses:

  • 400: A required field missing, source_node_ids / target_node_ids not an array of strings, a filter field that is not an array, or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or a source or target ID not found (entity does not exist).
  • 500: Empty source_node_ids or target_node_ids.

Example

Request:

POST /astar
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "source_node_ids": ["1"],
  "target_node_ids": ["4"],
  "coor_attr_name": "pos",
  "weight_attr_name": "weight",
  "return_paths": true,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "distances": [["4", 2.0]],
  "reachable": [true],
  "paths": [
    [
      [["1", "3"], "a13"],
      [["3", "4"], "a34"]
    ]
  ]
}

4.1.4 /spfa

Description

Runs the Shortest Path Faster Algorithm (SPFA, a queue-based Bellman-Ford) from a single source node over outbound relationships only. Unlike the other shortest-path endpoints it accepts negative weights. Optionally returns explicit paths and respects filter predicates.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_id": "string",
  "target_node_ids": ["string", ...],
  "weight_attr_name": "string",
  "return_paths": true,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • source_node_id: Starting node for the traversal.
  • target_node_ids (required): Array of destination nodes. It must be present, but may be empty ([]) to compute all reachable nodes.
  • weight_attr_name (optional): Relationship attribute holding the edge weight; omit for unit weights. Negative values are used as-is; a missing or non-numeric value is treated as 1.
  • return_paths (optional, default false): When true, include path details in the response.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

  • distances: with targets, one [entity_id, distance] entry per target in request order, -1.0 for an unreachable target. With negative weights -1.0 can also be a real distance, so check reachable instead. With target_node_ids: [], one entry for every reached node, including the source (0.0), in unspecified order.
  • reachable: one boolean per distances entry, in the same order; false only for an unreachable target. A node reachable from a negative cycle counts as reachable. With target_node_ids: [] every entry is true.
  • affected_by_negative_cycle: one boolean per distances entry, true for a node reachable from a negative cycle (whose distance is reported as 0.0, see below). All false when no negative cycle is found.
  • paths (only when return_paths is true): one [has_negative_cycle, edges] pair per target in request order, where edges is an array of [["src", "dst"], "rel_id"] listed from the source to the target. An unreachable target gives [false, []]. With target_node_ids: [], paths is [].
  • Negative cycles: a cycle is detected when a node is queued as many times as the graph has entities. The cycle is then taken from the predecessor links, and it and every node reachable from it (over relationships that pass the filters) stop being relaxed, so the request returns promptly. Each such node gets distance 0.0, whether or not return_paths is set; with target_node_ids: [], they are all listed, even those not reached before the cycle was found. Nodes not reachable from a negative cycle get their true shortest distances. Several negative cycles can be found. With return_paths, a target reachable from a cycle gets the path entry [true, <edges>], where <edges> are the edges of the first detected cycle it is reachable from, each [[src, dst], rel_id] in stored direction, listed in traversal order around the cycle (each edge's dst is the next edge's src).

Additional failure codes:

  • 400: target_node_ids missing or not an array of strings, node_filters / edge_filters not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or the source or a target does not exist (entity does not exist).

Example

Request:

POST /spfa
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "source_node_id": "1",
  "target_node_ids": ["4"],
  "weight_attr_name": "weight",
  "return_paths": true,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "distances": [["4", 6.0]],
  "reachable": [true],
  "affected_by_negative_cycle": [false],
  "paths": [
    [
      false,
      [
        [["1", "2"], "s12"],
        [["2", "3"], "s23"],
        [["3", "4"], "s34"]
      ]
    ]
  ]
}

4.1.5 /delta_stepping

Description

Executes the parallel delta-stepping algorithm for single-source shortest paths. Optional path_node_ids selects the destinations to report and reconstruct paths for.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_id": "string",
  "path_node_ids": ["string", ...],
  "delta": 1.0,
  "weight_attr_name": "string",
  "is_undirected": false,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • source_node_id: Starting node for the traversal.
  • path_node_ids (optional): Nodes to report distances and path reconstructions for.
  • delta (optional, number, default 1.0): Bucket width for the delta-stepping algorithm. Any positive value works, however small. A value <= 0 returns 500 (InvalidParameter).
  • weight_attr_name (optional): Relationship attribute holding the edge weight; omit for unit weights. A negative value is treated as 0; a missing or non-numeric value as 1.
  • is_undirected (optional, default false): When false, only outbound relationships are followed; when true, both directions.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

  • distances: when path_node_ids is non-empty, one [entity_id, distance] entry per path node in request order, -1.0 if unreachable. Otherwise, one entry for every reached node, including the source (0.0), in unspecified order.
  • reachable: one boolean per distances entry, false for an unreachable path node. Without path_node_ids every entry is true.
  • paths: only present when path_node_ids is non-empty. One path per path node in request order, edges listed from the source to the target; [] for an unreachable node or the source itself. Each edge names the relationship whose relaxation gave the node its distance; with parallel relationships, that is the one actually used.

Additional failure codes:

  • 400: path_node_ids not an array of strings, delta not a finite 32-bit float, a filter field that is not an array, or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or the source or a path node does not exist (entity does not exist).
  • 500: delta <= 0.

Example

Request:

POST /delta_stepping
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "source_node_id": "1",
  "path_node_ids": ["4"],
  "delta": 1.0,
  "weight_attr_name": "weight",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "distances": [["4", 2.0]],
  "reachable": [true],
  "paths": [
    [
      [["1", "3"], "d13"],
      [["3", "4"], "d34"]
    ]
  ]
}

4.2 Trees & Connectivity

4.2.1 /prim

Description

Builds a Minimum Spanning Tree using Prim's algorithm over the (optionally filtered) graph. Relationship direction is ignored: every relationship can be used in either direction, so symmetric edges are not needed.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "start_node_ids": ["string", ...],
  "weight_attr_name": "string",
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • start_node_ids (required array, may be empty): One tree is grown from each ID, in the given order, so the result is the minimum spanning forest of the components that contain the start nodes. A start node already covered by an earlier tree, or one that fails node_filters, adds nothing. With a single ID the result is the spanning tree of its component. Pass [] to build a minimum spanning forest over all entities, one tree per component.
  • weight_attr_name (optional): Relationship attribute holding the edge weight; omit for unit weights. Negative values are used as-is; a missing or non-numeric value is treated as 1.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters). If every start node fails node_filters, the result is empty.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "mst_edges": [
    [["u", "v"], "relationship_id"],
    ...
  ],
  "total_weight": 5.0
}
  • mst_edges: edges in the order Prim's algorithm added them, tree by tree. In [u, v], u was already in the tree and v is the node the edge added, which may be the reverse of the stored relationship direction.
  • total_weight: sum of the weights of mst_edges (0.0 for an empty result).

Additional failure codes:

  • 400: start_node_ids missing or not an array of strings, a filter field that is not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or a start node does not exist (entity does not exist).

Example

Request:

POST /prim
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "start_node_ids": [],
  "weight_attr_name": "weight",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "mst_edges": [
    [["1", "2"], "p12"],
    [["2", "3"], "p23"]
  ],
  "total_weight": 5.0
}

4.2.2 /steiner_tree

Description

Computes an approximate Steiner tree connecting source_node_id and terminal_node_ids. The server runs Dijkstra from the source over outbound relationships and returns the union of the shortest paths to the terminals (a shortest-path-tree heuristic). Optional rerouting refines the solution. There are no filter parameters.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_id": "string",
  "terminal_node_ids": ["string", ...],
  "weight_attr_name": "string",
  "apply_rerouting": false,
  "use_job": false
}
  • source_node_id: Root node for the Steiner tree.
  • terminal_node_ids: Non-empty array of terminal nodes to connect. Terminals that cannot be reached from the source are silently left out of the tree.
  • weight_attr_name (optional): Relationship attribute holding the edge weight; omit for unit weights. A negative value is treated as 0; a missing or non-numeric value as 1.
  • apply_rerouting (optional, default false): When true, repeatedly replace a tree node's incoming tree edge with a cheaper inbound relationship from another tree node when that does not create a cycle, then drop branches that lead to no terminal and recompute total_cost.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "tree_edges": [
    [["u", "v"], "relationship_id"],
    ...
  ],
  "total_cost": 2.0
}
  • tree_edges: [[parent, child], relationship_id] entries following the stored relationship direction. Without rerouting they are grouped by terminal, in the order the terminals were reached. After rerouting the order is unspecified.
  • total_cost: sum of the weights of tree_edges.

Additional failure codes:

  • 400: source_node_id or terminal_node_ids missing, or terminal_node_ids not an array of strings.
  • 404: Graph not found (graph does not exist), or the source node or a terminal node does not exist (entity does not exist).
  • 500: Empty terminal_node_ids (InvalidParameter).

Example

Request:

POST /steiner_tree
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "source_node_id": "1",
  "terminal_node_ids": ["3", "4"],
  "weight_attr_name": "weight",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "tree_edges": [
    [["1", "3"], "st13"],
    [["3", "4"], "st34"]
  ],
  "total_cost": 2.0
}

4.3 Flow (Push-Relabel)

4.3.1 /max_flow_push_relabel

Description

Computes the maximal flow from source_node_id to sink_node_id using the push-relabel algorithm over directed relationships. Capacities are read from a relationship attribute, and the resulting flows are written back to another relationship attribute.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_id": "string",
  "sink_node_id": "string",
  "capacity_attr_name": "string",
  "flow_attr_name": "string",
  "use_job": false
}
  • source_node_id: Source node for the flow.
  • sink_node_id: Sink node for the flow. Must differ from source_node_id.
  • capacity_attr_name: Relationship attribute containing capacities. A missing, non-numeric or negative value counts as capacity 0.
  • flow_attr_name (required): Relationship attribute the computed flow is written to. Every relationship that carries a positive flow gets this attribute set to the flow as a decimal string (for example "12.500000"). The written flows form a valid flow: no relationship exceeds its capacity, and at every node other than the source and the sink, the inflow equals the outflow. The flows are written after the computation, under the graph's write lock, as ordinary relationship attribute updates, and are saved like any other write. Relationships with no flow are not modified, so a value left by an earlier run stays in place.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "max_flow_value": 12.5
}

max_flow_value is the value of a maximum flow, that is, the total flow into the sink (0.0 when the sink is unreachable).

Error Responses:

  • 400: A required field missing, or source_node_id equal to sink_node_id (invalid parameter).
  • 404: Graph not found (graph does not exist), or the source or sink node does not exist (entity does not exist).

Example

Request:

POST /max_flow_push_relabel
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "network",
  "source_node_id": "s",
  "sink_node_id": "t",
  "capacity_attr_name": "capacity",
  "flow_attr_name": "flow",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "max_flow_value": 12.5
}

4.4.1 /common_neighbors

Description

Counts (and optionally returns) the intersection of the neighbor sets of all provided node_ids. A node's neighbor set is the distinct entities it has outbound relationships to; with is_undirected, entities with relationships into it are added. Supports attribute filters.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "node_ids": ["string", ...],
  "is_undirected": false,
  "return_nodes": true,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • node_ids: Array of node IDs whose neighbor intersection is computed (one or more; a single node returns its own neighbor set).
  • is_undirected (optional, default false): Also count inbound relationships when true.
  • return_nodes (optional, default true): When true, include common node IDs in the response.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters). node_filters apply to the neighbor entities (not to node_ids); edge_filters to the relationships leading to them.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "num_common": 3,
  "common_nodes": ["3", "4", "5"]
}

common_nodes lists each common neighbor once, in unspecified order. It is omitted when return_nodes is false.

Additional failure codes:

  • 400: node_ids missing, not an array of strings, or empty (invalid parameters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or one of the input nodes does not exist (entity does not exist).

Example

Request:

POST /common_neighbors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "node_ids": ["1", "2"],
  "return_nodes": true,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "num_common": 3,
  "common_nodes": ["3", "4", "5"]
}

4.4.2 /adamic_adar

Description

Computes the Adamic–Adar link prediction score between nodes u and v: the sum, over every common neighbor z of u and v, of 1 / ln(deg(z)). Common neighbors are found as in /common_neighbors, and deg(z) is the number of distinct neighbors of z that pass the same filters. With is_undirected false, z is an out-neighbor of both u and v, and deg(z) counts its distinct in-neighbors (the nodes with a relationship pointing to z). With is_undirected true, it counts its distinct in- and out-neighbors.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "u": "string",
  "v": "string",
  "is_undirected": false,
  "use_log": true,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • u: First node ID.
  • v: Second node ID.
  • is_undirected (optional, default false): Also count inbound relationships when true.
  • use_log (optional, default true): When true, each common neighbor adds 1 / ln(deg(z)), and neighbors with deg(z) <= 1 add nothing. When false, each adds 1 / deg(z) (the resource-allocation index).
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "score": 1.4426950216293335
}

score is 0.0 when u and v have no common neighbor.

Additional failure codes:

  • 400: u or v missing, a filter field that is not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or u or v does not exist (node does not exist).

Example

Request:

POST /adamic_adar
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "u": "1",
  "v": "2",
  "is_undirected": true,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "score": 0.9102392196655273
}

Here u and v share one neighbor, which has three distinct neighbors (1 / ln 3).

4.4.3 /preferential_attachment

Description

Calculates the Preferential Attachment score (deg(u) × deg(v) under filter constraints) for the candidate link (u, v). deg(x) is the number of distinct neighbors of x that pass the filters: out-neighbors only, or out- and in-neighbors when is_undirected is true.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "u": "string",
  "v": "string",
  "is_undirected": false,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • u: First node ID.
  • v: Second node ID.
  • is_undirected (optional, default false): Also count inbound relationships when true.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "score": 4.0
}

Additional failure codes:

  • 400: u or v missing, a filter field that is not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or u or v does not exist (node does not exist).

Example

Request:

POST /preferential_attachment
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "u": "1",
  "v": "2",
  "is_undirected": true,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "score": 4.0
}

4.5 Ranking, Ordering, & Inference

4.5.1 /topsort

Description

Produces a depth-first topological ordering (reverse DFS post-order over outbound relationships) of the nodes reachable from the supplied start nodes in the (filtered) graph. If start_node_ids is empty, every entity is used as a start node, so the whole graph is covered. A cycle does not cause an error: an edge back into the current DFS path is ignored and an order is still returned, which is not topological for the nodes on the cycle. has_cycle in the response tells whether this happened.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "start_node_ids": ["string", ...],
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • start_node_ids (required array, may be empty): Starting nodes for the traversal; [] to cover all entities. Start nodes that fail node_filters are skipped.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "order": ["1", "2", "3"],
  "has_cycle": false
}

Each reached node appears once in order. has_cycle is true when the subgraph reached from the start nodes (all entities for []) through the relationships and nodes that pass the filters contains a cycle; a relationship from a node to itself counts.

Additional failure codes:

  • 400: start_node_ids missing or not an array of strings, a filter field that is not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or a start node does not exist (entity does not exist).

Example

Request:

POST /topsort
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "start_node_ids": ["1"],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "order": ["1", "2", "3"],
  "has_cycle": false
}

4.5.2 /topsort_kahn

Description

Generates a level-by-level topological ordering using Kahn's algorithm over outbound relationships. The server first collects the subgraph reachable from the start nodes (all entities if start_node_ids is empty). The first level holds every node of that subgraph with no incoming relationship from inside the subgraph, and each later level holds the nodes whose last remaining predecessor was in the previous level. Order inside a level is not guaranteed. Cycles do not cause an error: nodes on a cycle or downstream of one never reach in-degree 0, and they are returned together as one extra final level. has_cycle in the response tells whether this happened.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "start_node_ids": ["string", ...],
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • start_node_ids (required array, may be empty): Starting nodes for the traversal; [] to cover all entities. Start nodes that fail node_filters are skipped.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "levels": [["1"], ["2", "3"], ["4"]],
  "has_cycle": false
}

has_cycle is true when the collected subgraph (through the relationships and nodes that pass the filters) contains a cycle, a relationship from a node to itself included. The last level then holds the nodes on or downstream of a cycle.

Additional failure codes:

  • 400: start_node_ids missing or not an array of strings, a filter field that is not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist), or a start node does not exist (entity does not exist).

Example

Request:

POST /topsort_kahn
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "start_node_ids": ["1"],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "levels": [["1"], ["2", "3"], ["4"]],
  "has_cycle": false
}

4.5.3 /dag_longest_path

Description

Computes longest paths within a Directed Acyclic Graph (DAG) using dynamic programming over outbound relationships. The nodes are processed in the /topsort order computed from source_node_ids. If the nodes reached from the sources, through the relationships and nodes that pass the filters, contain a cycle (a relationship from a node to itself included), no longest path exists and the request fails with 400 ("graph has a cycle"). Optional filters limit the nodes and edges considered.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "source_node_ids": ["string", ...],
  "target_node_ids": ["string", ...],
  "weight_attr_name": "string",
  "return_paths": false,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • source_node_ids: Array of one or more starting nodes (required). Each source starts at distance 0. An empty array returns 500 (InvalidParameter).
  • target_node_ids (optional): Limit destinations; omit or empty to compute all reachable nodes.
  • weight_attr_name (optional): Relationship attribute storing numeric weights. Omit it to give every edge weight 1 (longest hop count). Negative values are used as-is; a missing or non-numeric value is treated as 1.
  • return_paths (optional, default false): When true, include path details in the response.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
  • use_job (optional): Run asynchronously as a job.

Response

Same fields as /dijkstra:

  • distances: with targets, one entry per target in request order, -1.0 if unreachable. With negative weights -1.0 can also be a real longest distance, so check reachable instead. Without targets, one entry for every reached node, including the sources, in unspecified order.
  • reachable: one boolean per distances entry, false for an unreachable target. Without targets every entry is true.
  • paths (only when return_paths is true): one path per target in request order, [] for an unreachable target. As in /dijkstra, edges are listed from the source to the target. Without targets, paths is [].

Additional failure codes:

  • 400: source_node_ids missing, source_node_ids / target_node_ids not an array of strings, a filter field that is not an array, or a filter object that cannot be parsed.
  • 400: The reached subgraph has a cycle ({"error_code": "InvalidData", "error_message": "graph has a cycle"}). With use_job, the job fails with the same error_message.
  • 404: Graph not found (graph does not exist), or a source or target does not exist (entity does not exist).
  • 500: Empty source_node_ids.

Example

Request:

POST /dag_longest_path
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "source_node_ids": ["1"],
  "target_node_ids": ["4"],
  "weight_attr_name": "weight",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "distances": [["4", 5.0]],
  "reachable": [true]
}

4.5.4 /pagerank

Description

Evaluates PageRank over the (optionally filtered) graph by power iteration. Supports weighted edges, a node-weight personalization vector, and output scalers. Self-loops are ignored and parallel relationships between the same two nodes are merged (their weights are summed). The rank of a node with no usable outgoing weight (a dangling node) is redistributed according to the personalization vector. Scores are normalized to sum to 1 before the optional scaler is applied.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "damping_factor": 0.85,
  "max_iterations": 100,
  "edge_weight_attr": "string",
  "node_weight_attr": "string",
  "scaler": "string",
  "is_undirected": false,
  "node_filters": [ { ... } ],
  "edge_filters": [ { ... } ],
  "use_job": false
}
  • damping_factor (optional, number, default 0.85): Damping factor. Values outside [0, 1] are clamped into that range.
  • max_iterations (optional, non-negative integer, default 50): Maximum iteration count. 0 runs one iteration. Iteration stops early once the L1 change between iterations is below 1e-10.
  • edge_weight_attr (optional): Relationship attribute for weighted PageRank. A negative value is treated as 0; a missing or non-numeric value as 1. Omit for unweighted PageRank.
  • node_weight_attr (optional): Entity attribute for personalization. Teleport probabilities (and the initial ranks) are proportional to this weight. A negative value is treated as 0; a missing or non-numeric value as 1; if all weights are 0, the uniform distribution is used. Omit for uniform teleportation.
  • scaler (optional, case-insensitive, default none): Transformation applied to the final scores: none, minmax ((x - min) / (max - min), all 0 if every score is equal), max (x / max), mean (x / mean), log (ln(1 + x)), or stdscore / zscore / std ((x - mean) / standard deviation). An unrecognized name applies no scaling and returns no error.
  • is_undirected (optional, default false): Also follow relationships backwards when true.
  • node_filters / edge_filters (optional): JSON predicate arrays (see Filters). Nodes that fail node_filters are removed with their relationships and get no score.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "scores": [["node", 0.25], ...]
}

scores has one [entity_id, score] entry for every entity that passes node_filters, including isolated ones, ordered by internal entity ID (not by score). An empty graph returns "scores": [].

Additional failure codes:

  • 400: A parameter of the wrong type, a negative max_iterations (plain text), a filter field that is not an array (invalid field: node_filters), or a filter object that cannot be parsed.
  • 404: Graph not found (graph does not exist).

Example

Request:

POST /pagerank
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "damping_factor": 0.85,
  "max_iterations": 20,
  "use_job": false
}

Response, for a graph whose only relationships form the cycle 1 → 2 → 3 → 4 → 1:

{
  "error_code": "Success",
  "scores": [
    ["1", 0.25],
    ["2", 0.25],
    ["3", 0.25],
    ["4", 0.25]
  ]
}

4.5.5 /loopy_bp_map

Description

Runs loopy belief propagation (max-sum, discrete MAP inference) on a factor graph encoded in the database. An entity is a variable when its type_attr_name attribute equals variable and a factor when it equals function (case-insensitive); all other entities are ignored. A factor is connected to every variable it has a relationship with, in either direction.

Custom factor potentials are not supported: every factor uses a constant log-potential of 0. With this potential all messages stay uniform, so the current implementation assigns state 0 to every variable.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "type_attr_name": "string",
  "K": 2,
  "max_iterations": 10,
  "damping": 0.2,
  "tol": 1e-6,
  "use_job": false
}
  • type_attr_name: Entity attribute whose value (variable or function) marks variables and factors.
  • K (required, integer from 1 to 1000): Number of discrete states per variable. 0, a negative value or a value above 1000 returns 400 with the plain-text body field with invalid value: K, also with use_job. With K = 1 every variable is assigned 0 without running message passing.
  • max_iterations (optional, non-negative integer, default 100): Maximum iterations to run.
  • damping (optional, number, default 0.5, clamped to [0, 1]): Each new message is (1 - damping) × computed + damping × previous.
  • tol (optional, number, default 1e-6): Iteration stops when the largest change of any message is below tol.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "assignments": {
    "x": 0,
    "y": 0
  }
}

assignments maps each variable's entity ID to its state (an integer in 0 … K - 1). Variables not connected to any factor get 0. If the graph has no variables or no factors (including when no entity has type_attr_name), assignments is {}.

Additional failure codes:

  • 400: A required field missing or of the wrong type, or K / max_iterations out of range (plain text).
  • 404: Graph not found (graph does not exist).

Example

Request:

POST /loopy_bp_map
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "type_attr_name": "type",
  "K": 2,
  "max_iterations": 10,
  "damping": 0.3,
  "tol": 1e-6,
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "assignments": {
    "x": 0,
    "y": 0
  }
}

4.5.6 /loopy_bp_map_continuous

Description

Continuous variant of loopy BP supporting bounded continuous variables and Monte Carlo sampling parameters. Variables and factors are identified exactly as in /loopy_bp_map. Each variable gets num_samples candidate values drawn uniformly at random (with a fixed seed, so results are repeatable) from its bounds, and max-sum messages are computed over these candidates. Factors with two or more variables are evaluated with num_mc_samples Monte Carlo draws per candidate.

As in /loopy_bp_map, every factor uses a constant log-potential of 0, so each connected variable is assigned its first sampled candidate.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "type_attr_name": "string",
  "bounds": {
    "x": [0.0, 2.0],
    "y": [1.0, 3.0]
  },
  "num_samples": 2,
  "num_mc_samples": 2,
  "max_iterations": 5,
  "damping": 0.2,
  "tol": 1e-6,
  "use_job": false
}
  • type_attr_name: Entity attribute whose value (variable or function) marks variables and factors.
  • bounds (optional object): Map of variable entity IDs to [min, max] bounds. Entries that are not two-number arrays are ignored, and a non-object bounds is ignored. An ID that is not an entity returns 404 (entity does not exist). A variable without bounds samples from [0, 1), and if max <= min the range [min, min + 1) is used.
  • num_samples (optional, integer ≥ 1, default 100): Candidate values per variable.
  • num_mc_samples (optional, integer ≥ 1, default 1000): Monte Carlo draws per candidate when computing a factor-to-variable message.
  • max_iterations (optional, non-negative integer, default 100): Maximum iterations to run.
  • damping (optional, number, default 0.5, clamped to [0, 1]): Damping factor for message updates.
  • tol (optional, number, default 1e-6): Iteration stops when the largest message change is below tol.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "assignments": {
    "x": 1.3423112745133252,
    "y": 2.052764929563048
  }
}

assignments maps variable entity IDs to numbers. A variable not connected to any factor gets the midpoint of its bounds, or is omitted if it has no bounds. If the graph has no variables or no factors, assignments is {}.

Additional failure codes:

  • 400: type_attr_name missing, or a numeric parameter of the wrong type or out of range (plain text for 0 or negative counts).
  • 404: Graph not found (graph does not exist), or a bounds key is not an entity (entity does not exist).

Example

Request:

POST /loopy_bp_map_continuous
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "type_attr_name": "type",
  "bounds": {
    "x": [0.0, 2.0],
    "y": [1.0, 3.0]
  },
  "num_samples": 2,
  "num_mc_samples": 2,
  "max_iterations": 5,
  "damping": 0.2,
  "tol": 1e-6,
  "use_job": false
}

Response, for a graph whose only variables are x and y (created in that order), each connected to a factor:

{
  "error_code": "Success",
  "assignments": {
    "x": 1.3423112745133252,
    "y": 2.052764929563048
  }
}

4.6 Clustering

4.6.1 /create_clustering

Description

Builds a named clustering over the graph using one of the supported algorithms. The server infers the parameter set from the fields you supply, and the algorithm name must belong to that set.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "clustering_name": "string",
  "clustering_algorithm": "string",
  "max_iter": 20,
  "resolution": 1.0,
  "weight_attribute": "edge_weight",
  "objective_function": "modularity",
  "vector_name": "embedding_384",
  "k": 8,
  "dist_type": "Euclidean",
  "use_job": false
}

The schema lists every field; send only the fields of one parameter set (see below).

  • clustering_name: Name for the clustering result.
  • clustering_algorithm: Exact, case-sensitive algorithm name: Strongly Connected Component, Weakly Connected Component, Louvain, Leiden, Label Propagation, K-Means, or K-Means++.
  • max_iter (non-negative integer): Louvain/Leiden: maximum number of aggregation levels. Label Propagation: maximum number of rounds. K-Means: maximum number of iterations (must be ≥ 1; 0 returns 400 invalid clustering parameters). 0 leaves every entity in its own cluster for Louvain, Leiden and Label Propagation.
  • resolution (number): Resolution γ for Louvain/Leiden.
  • weight_attribute (optional): Relationship attribute used as the edge weight by Louvain/Leiden. A missing or non-numeric value is treated as 1; relationships with a weight <= 0 are ignored. Omit it to give every relationship weight 1.
  • objective_function (optional, default modularity): modularity for Louvain; modularity or cpm (Constant Potts Model) for Leiden. Any other value returns 400: clustering algorithm not supported for Louvain, invalid clustering parameters for Leiden.
  • vector_name: Name of the dense entity vector used by K-Means.
  • k (integer ≥ 1): Number of clusters for K-Means. 0 returns 400 with the plain-text body field with invalid value: k.
  • dist_type (optional, default Euclidean): Distance metric for K-Means, using a name from Distance Function. Only Euclidean is supported: any other valid name returns 400 clustering algorithm not supported, and an unknown name returns 400 invalid dist_type.
  • use_job (optional): Run asynchronously as a job.

The parameter set is chosen from the fields present, in this order:

  1. K-Means set, if vector_name or k is present: requires vector_name, k, and max_iter; dist_type is optional. Algorithms: K-Means, K-Means++.
  2. Community set, if resolution, weight_attribute, or objective_function is present: requires max_iter and resolution. Algorithms: Louvain, Leiden.
  3. Label Propagation set, if only max_iter is present. Algorithm: Label Propagation.
  4. Connected components set, if none of these fields is present. Algorithms: Strongly Connected Component, Weakly Connected Component.

An algorithm name outside the chosen set (for example Weakly Connected Component sent with max_iter) returns 400 invalid clustering parameters.

What each algorithm does:

  • Strongly Connected Component: Tarjan's algorithm over outbound relationships. Every entity belongs to exactly one cluster.
  • Weakly Connected Component: breadth-first search ignoring relationship direction. Every entity belongs to exactly one cluster.
  • Louvain: multi-level modularity optimization on the undirected graph (parallel relationships are merged and their weights summed), with resolution γ. Isolated entities stay in singleton clusters.
  • Leiden: like Louvain, with a refinement step that splits each community into connected parts before aggregation. Supports the modularity and cpm objectives; with cpm, the size of a community is its number of entities.
  • Label Propagation: each entity repeatedly adopts the most frequent label among its neighbors (direction ignored, ties broken at random). Stops after max_iter rounds or when no label changes. Entities without neighbors keep their own cluster.
  • K-Means / K-Means++: clusters only the entities that have a dense Float32 vector named vector_name; entities without it are not assigned to any cluster. All these vectors must have the same dimension. K-Means picks k random entities as initial centroids; K-Means++ uses k-means++ seeding. k must not exceed the number of entities that have the vector. Iteration stops after max_iter rounds or when no assignment changes.

The parameter checks above (objective_function, K-Means max_iter and dist_type) are made when the request is received, so they return 400 immediately, also with use_job. A creation that fails later (for example k larger than the number of entities with the vector, or vectors of different dimensions) leaves no clustering behind, and the name can be used again.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "clustering_name": "communities_v1"
}

Additional failure codes:

  • 400: A required field of the chosen parameter set missing or of the wrong type; invalid clustering parameters (unknown algorithm name, a name outside the chosen set, an unknown Leiden objective_function, or invalid K-Means k / max_iter); clustering algorithm not supported (a Louvain objective_function other than modularity, or a non-Euclidean K-Means dist_type); invalid dist_type.
  • 404: Graph does not exist (graph does not exist).
  • 409: Clustering with the same name already exists (clustering already exists).
  • 500: The graph has no entities (InvalidData, for Louvain, Leiden, Label Propagation and K-Means), or the K-Means vectors are not all Float32 with the same dimension (InvalidData).

Example

Request:

POST /create_clustering
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "clustering_name": "communities_v1",
  "clustering_algorithm": "Louvain",
  "max_iter": 25,
  "resolution": 1.0,
  "weight_attribute": "edge_weight",
  "objective_function": "modularity",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "clustering_name": "communities_v1"
}

4.6.2 /get_clustering

Description

Returns the full clustering as an array of clusters, each containing the entity IDs assigned to that cluster. The index of a cluster in clusters is its cluster_id. A K-Means clustering can contain empty clusters ([]).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "clustering_name": "string",
  "use_job": false
}
  • clustering_name: Name of the clustering to fetch.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "clusters": [
    ["entity1", "entity2"],
    ["entity3", "entity4", "entity5"]
  ]
}

Additional failure codes:

  • 404: Graph does not exist (graph does not exist), or the clustering does not exist or has no clusters (clustering does not exist).

Example

Request:

POST /get_clustering
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "clustering_name": "communities_v1",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "clusters": [
    ["movie_1", "movie_2"],
    ["movie_3", "movie_4", "movie_5"]
  ]
}

4.6.3 /get_clustering_cluster

Description

Fetches the members of a single cluster (by numeric cluster_id) from a named clustering. Runs synchronously (there is no use_job).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "clustering_name": "string",
  "cluster_id": 0
}
  • clustering_name: Name of the clustering to query.
  • cluster_id (non-negative integer): Cluster index to return (its index in /get_clustering). A negative value returns 400 with the plain-text body field with invalid value: cluster_id.

Response

{
  "error_code": "Success",
  "cluster_id": 0,
  "entities": ["movie_1", "movie_2"]
}

Additional failure codes:

  • 404: Graph does not exist (graph does not exist).
  • 404: Clustering does not exist, or cluster_id is not less than the number of clusters (clustering or cluster not found).

Example

Request:

POST /get_clustering_cluster
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "clustering_name": "communities_v1",
  "cluster_id": 1
}

Response:

{
  "error_code": "Success",
  "cluster_id": 1,
  "entities": ["movie_3", "movie_4", "movie_5"]
}

4.6.4 /get_clustering_membership

Description

Looks up which cluster a specific entity belongs to within a named clustering. Supports synchronous or asynchronous execution.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "clustering_name": "string",
  "entity_id": "string",
  "use_job": false
}
  • clustering_name: Name of the clustering to query.
  • entity_id: Entity ID to look up.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "cluster_id": 2
}

Additional failure codes:

  • 404: Graph does not exist (graph does not exist).
  • 404: Entity does not exist (entity does not exist).
  • 404: Entity is not assigned to the requested clustering, which is also the response when the clustering does not exist (entity is not assigned to the clustering).

Example

Request:

POST /get_clustering_membership
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "clustering_name": "communities_v1",
  "entity_id": "movie_4",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "cluster_id": 1
}

4.6.5 /delete_clustering

Description

Deletes a previously created clustering and the entities' membership records for it (entities remain untouched). Can run synchronously or as a job.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "clustering_name": "string",
  "use_job": false
}
  • clustering_name: Name of the clustering to delete.
  • use_job (optional): Run asynchronously as a job.

Response

{
  "error_code": "Success",
  "clustering_name": "communities_v1"
}

Additional failure codes:

  • 404: Graph does not exist (graph does not exist), or the clustering does not exist or has no clusters (clustering does not exist).

Example

Request:

POST /delete_clustering
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "clustering_name": "communities_v1",
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "clustering_name": "communities_v1"
}

5. Graph Batch Operations

Note: The items of a batch are processed one at a time, in request order, whether or not the batch is submitted as a job. use_job (boolean, optional, default false) only decides where the batch runs: with "use_job": true the request returns 202 Accepted with {"error_code": "Success", "job_id": "<uuid>"} right away, the whole batch runs as one background job, and its outcome is read with /get_job_status and /get_job_result. A use_job value that is not a JSON boolean is treated as false. The handlers do not enforce a maximum batch size.

Errors shared by every endpoint in this chapter (JSON body {"error_code": "...", "error_message": "..."} unless noted otherwise):

  • 400, Unknown: "Request Body Empty" or "Invalid JSON".
  • 400, InvalidParameter: "request JSON is nested more than 512 levels deep".
  • 400, InvalidParameter: "missing field: <name>", "field with invalid value: <name>" or "field is not a json array: <name>". An array element of the wrong type (for example a number inside entity_ids) gives "field with invalid value" without a field name.
  • 403, InvalidUser: "unauthorized". The API key is checked after the body has been validated. It is also checked when the batch is empty, so an empty batch with a bad key returns 403, not 200.
  • 500: the job could not be queued (only with "use_job": true).

The write endpoints (5.1–5.4 and 5.10–5.13) return only {"error_code": "Success"} when every item succeeds. They do not return per-item results, and a batch is not all-or-nothing: each section states which items are applied when one fails and how the first failure is reported. With "use_job": true a failure makes the job Failed, with the failing item's error code and the same error_message text.

5.1 /batch_create_entity

Description

Creates a batch of entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id"    : "string",
  "entity_ids"  : [
    "string",
    "string",
    ...
  ],
  "use_job": false
}
  • entity_ids (array of strings, required): An empty array returns 200 with {"error_code": "Success"} when the graph exists, and 404 (GraphNotFound) when it does not. If the same ID appears twice, the second occurrence fails with EntityExist.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Every entity in the list is attempted; the ones that can be created are created even when others fail. A failure is reported the same way whether use_job is false or omitted:

  • 404, GraphNotFound: the graph does not exist; the body is {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.
  • Otherwise the first failing entity, in request order, is returned with "error_message": "error when creating entity <entity_id> . reason for error is: <reason>":
  • 409, EntityExist: reason entity already exists.
  • 500, other codes: reason internal server error: <ErrorCode>.

With "use_job": true the job fails with the same error code and message ("graph does not exist" for a missing graph).

Example

Request (All created):

POST /batch_create_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_ids": [
    "John",
    "Alice",
    "Bob",
    "Charlie"
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Graph missing, use_job omitted):

POST /batch_create_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_ids": [
    "John",
    "Alice",
    "Bob",
    "Charlie"
  ]
}

Response (404 Not Found):

{
  "error_code": "GraphNotFound",
  "error_message": "graph does not exist"
}

5.2 /batch_remove_entity

Description

Removes a batch of entities in one request. Removing an entity deletes its attributes, its vectors, its index entries, and every edge into or out of it. The relationship records on those edges (and their attributes and vectors) are not deleted.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id"    : "string",
  "entity_ids"  : [
    "string",
    "string",
    ...
  ],
  "use_job": false
}
  • entity_ids (array of strings, required): An empty array returns 200 with {"error_code": "Success"}.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Entities are removed in request order and processing stops at the first failure: entities before it stay removed and entities after it are not attempted. The failure is returned with "error_code": "Unknown" and "error_message": "error when removing entity <entity_id> . reason for error is: <reason>":

  • 404: reason graph does not exist.
  • 409: reason entity not found.
  • 500: reason internal server error: <ErrorCode>.

With "use_job": true the job fails with the real error code (GraphNotFound, EntityNotFound, ...) and the same message.

Example

Request (All removed):

POST /batch_remove_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_ids": [
    "John",
    "Alice",
    "Bob",
    "Charlie"
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success"
}

Request (Entities missing):

POST /batch_remove_entity
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "entity_ids": [
    "John",
    "Alice",
    "Bob",
    "Charlie"
  ],
  "use_job": false
}

Response (409 Conflict):

{
  "error_code": "Unknown",
  "error_message": "error when removing entity John . reason for error is: entity not found"
}

5.3 /batch_set_entity_attributes

Description

Sets attributes and vectors for multiple entities in one request. Attributes are merged into the entity: a listed attribute overwrites the existing value with the same name, and attributes that are not listed are kept. A vector replaces the entity's existing vector with the same name.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id"    : "string",
  "entities"  : [
    {
      "entity_id": "string",
      "attributes": {
        "string": "string",
        ...
      },
      "vectors": [
        {
          "name": "string",
          "type": "string",
          "vector_data": [ ... ]
        },
        {
          "name": "string",
          "type": "string",
          "vector_data": [ ... ]
        },
        ...
      ]
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success"}.
  • entity_id (string, required).
  • attributes (object, optional): Every value must be a string. Otherwise the whole request is rejected before anything is written, with 400 and {"error_code": "InvalidParameter", "error_message": "attributes are invalid"}.
  • vectors (array, optional): Each element needs name (string) and type: "Float32" with vector_data as an array of finite numbers, or "SFloat32" with vector_data as an array of [index, value] pairs, where index is a non-negative integer and value a finite number. A bad element rejects the whole request with 400 before anything is written:
  • an element that is not an object: plain-text body missing vector field;
  • no string name: InvalidParameter, invalid vector: "name" must be present and a string;
  • a vector that cannot be parsed (unknown type, a non-finite value, a negative or fractional sparse index): InvalidParameter, failed to parse vector;
  • a vector name that is empty, contains /, \ or a control character, is . or .., or is longer than 128 characters: InvalidParameter, invalid vector name: <reason>.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Every item is attempted, and the items that succeed are applied even when others fail. The first failure, in request order, is returned with "error_message": "error when setting entity attributes for <entity_id> . reason for error is: <reason>":

  • 404, GraphNotFound: reason graph does not exist.
  • 404, EntityNotFound: reason entity does not exist.
  • 400, InvalidParameter / InvalidVectorType / InvalidData: reason a vector cannot be stored under its name (see the index on that name), for a vector that a linear index on its name cannot take (see Index Types).
  • 500, other codes: reason internal server error: <ErrorCode>.

Example

Request:

POST /batch_set_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "entities": [
    {
      "entity_id": "node1",
      "attributes": {
        "name": "Alice",
        "age": "30",
        "country": "Canada"
      },
      "vectors": [
        {
          "name": "profile_vec",
          "type": "Float32",
          "vector_data": [0.12, 0.34, 0.56, 0.78]
        },
        {
          "name": "sparse_pref",
          "type": "SFloat32",
          "vector_data": [
            [0, 1.0],
            [3, 2.5]
          ]
        }
      ]
    },
    {
      "entity_id": "node2",
      "attributes": {
        "name": "Bob",
        "age": "25"
      }
    },
    {
      "entity_id": "node3",
      "vectors": [
        {
          "name": "profile_vec",
          "type": "Float32",
          "vector_data": [0.01, 0.02, 0.03]
        }
      ]
    }
  ],
  "use_job": false
}

Response (404 Not Found, when node2 does not exist and the other items succeed; node1 and node3 are still updated):

{
  "error_code": "EntityNotFound",
  "error_message": "error when setting entity attributes for node2 . reason for error is: entity does not exist"
}

5.4 /batch_remove_entity_attributes

Description

Removes previously set string‑valued attributes and/or vectors from multiple entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "entities": [
    {
      "entity_id":       "string",
      "attribute_names": ["string", ...],
      "vector_names":      ["string", ...]
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success"}.
  • entity_id (string, required).
  • attribute_names, vector_names (arrays of strings, optional): An item with neither is a no-op that succeeds. If a listed attribute does not exist, the item fails with AttributeNotFound and its attribute values are left unchanged (index entries of attributes listed before the missing one may already have been dropped). A listed vector name that does not exist is ignored.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Every item is attempted, and the items that succeed are applied even when others fail. The first failure, in request order, is returned with "error_message": "error when removing entity attributes for <entity_id> . reason for error is: <reason>":

  • 404, GraphNotFound: reason graph does not exist.
  • 404, EntityNotFound: reason entity does not exist.
  • 404, AttributeNotFound: reason attribute(s) does not exist.
  • 500, other codes: reason internal server error: <ErrorCode>.

Example

Request (node2 lists no vectors; node3 lists neither attributes nor vectors, which is a no-op):

POST /batch_remove_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "entities": [
    {
      "entity_id":       "node1",
      "attribute_names": ["age","country"],
      "vector_names":      ["profile_vec"]
    },
    {
      "entity_id":       "node2",
      "attribute_names": ["name"]
    },
    {
      "entity_id":  "node3"
    }
  ],
  "use_job": false
}

Response (404 Not Found, when node2 does not exist; node1 and node3 are still processed):

{
  "error_code": "EntityNotFound",
  "error_message": "error when removing entity attributes for node2 . reason for error is: entity does not exist"
}

5.5 /batch_get_entity_attributes

Description

Fetches string‑valued attributes for multiple entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "entities": [
    {
      "entity_id":       "string",
      "attribute_names": ["string", ...]
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.
  • entity_id (string, required) and attribute_names (array of strings, required) in every item.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "entity_id":  "string",
      "error_code": "string",
      "values":      ["string", ...]
    },
    ...
  ]
}
  • results has one entry per requested item, in request order.
  • values is present only when the item's error_code is Success, and follows the order of attribute_names. If any requested attribute is missing, the item's error_code is AttributeNotFound and no values are returned for it.
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.
  • With "use_job": true, /get_job_result returns the same results.

Example

Request:

POST /batch_get_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "entities": [
    { "entity_id": "node1", "attribute_names": ["name","age"] },
    { "entity_id": "node2", "attribute_names": ["country"]   },
    { "entity_id": "nodeX", "attribute_names": ["name"]      }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "node1",
      "error_code": "Success",
      "values": ["Alice", "30"]
    },
    {
      "entity_id": "node2",
      "error_code": "AttributeNotFound"
    },
    {
      "entity_id": "nodeX",
      "error_code": "EntityNotFound"
    }
  ]
}

5.6 /batch_get_all_entity_attributes

Description

Fetches all string‑valued attributes for multiple entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "entities": [
    {
      "entity_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "entity_id":       "string",
      "error_code":      "string",
      "attributes": {
        "string": "string",
        ...
      }
    },
    ...
  ]
}
  • results has one entry per requested item, in request order. attributes is present only when the item's error_code is Success (an entity without attributes gives {}).
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_all_entity_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "entities": [
    {"entity_id": "node1"},
    {"entity_id": "node2"},
    {"entity_id": "nodeX"}
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "node1",
      "error_code": "Success",
      "attributes": {
        "name": "Alice",
        "age": "30",
        "country": "Canada"
      }
    },
    {
      "entity_id": "node2",
      "error_code": "Success",
      "attributes": { "name": "Bob" }
    },
    {
      "entity_id": "nodeX",
      "error_code": "EntityNotFound"
    }
  ]
}

5.7 /batch_get_entity_vectors

Description

Fetches specified vectors for multiple entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "entities": [
    {
      "entity_id": "string",
      "vector_names": ["string", ...]
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.
  • entity_id (string, required) and vector_names (array of strings, required) in every item.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "string",
      "error_code": "string",
      "vectors": [
        {
          "name": "string",
          "type": "Float32" | "SFloat32",
          "vector_data": [ ... ]
        },
        ...
      ]
    },
    ...
  ]
}
  • results has one entry per requested item, in request order. vectors is present only when the item's error_code is Success, and follows the order of vector_names.
  • Only Success and EntityNotFound are reported per item. Any other per-item error fails the whole request with 500 and "error_message": "error when fetching entity vectors for <entity_id> . reason for error is: internal server error: <ErrorCode>".
  • If an existing entity has no vector with a requested name, the whole request fails with 500 and {"error_code": "InvalidData", "error_message": "error in parsing vectors"}.
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_entity_vectors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "entities": [
    { "entity_id": "node1", "vector_names": ["vector_a", "vector_b"] },
    { "entity_id": "node2", "vector_names": ["vector_c"] },
    { "entity_id": "nodeX", "vector_names": ["vector_y"] }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "node1",
      "error_code": "Success",
      "vectors": [
        {
          "name": "vector_a",
          "type": "Float32",
          "vector_data": [0.1, 0.2, 0.3]
        },
        {
          "name": "vector_b",
          "type": "Float32",
          "vector_data": [0.4, 0.5, 0.6]
        }
      ]
    },
    {
      "entity_id": "node2",
      "error_code": "Success",
      "vectors": [
        {
          "name": "vector_c",
          "type": "Float32",
          "vector_data": [0.7, 0.8]
        }
      ]
    },
    {
      "entity_id": "nodeX",
      "error_code": "EntityNotFound"
    }
  ]
}

5.8 /batch_get_all_entity_vector_names

Description

Fetches all vector names (keys) for multiple entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "entities": [
    {
      "entity_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "string",
      "error_code": "string",
      "names": ["string", ...]
    },
    ...
  ]
}
  • results has one entry per requested item, in request order. names is present only when the item's error_code is Success ([] for an entity without vectors); the order of the names is not guaranteed.
  • Only Success and EntityNotFound are reported per item. Any other per-item error fails the whole request with 500 and "error_message": "error when fetching entity vector names for <entity_id> . reason for error is: internal server error: <ErrorCode>".
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_all_entity_vector_names
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "entities": [
    { "entity_id": "node1" },
    { "entity_id": "node2" },
    { "entity_id": "nodeX" }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "node1",
      "error_code": "Success",
      "names": ["profile_vec", "sparse_pref"]
    },
    {
      "entity_id": "node2",
      "error_code": "Success",
      "names": []
    },
    {
      "entity_id": "nodeX",
      "error_code": "EntityNotFound"
    }
  ]
}

5.9 /batch_get_all_entity_vectors

Description

Fetches all vectors (dense and sparse) for multiple entities in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "entities": [
    {
      "entity_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • entities (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "node1",
      "error_code": "Success",
      "vectors": [
        {
          "name":        "string",
          "type":        "string",
          "vector_data": [ ... ]
        },
        {
          "name":        "string",
          "type":        "string",
          "vector_data": [ ... ]
        }
      ]
    },
    {
      "entity_id": "node2",
      "error_code": "Success",
      "vectors": []
    },
    {
      "entity_id": "nodeX",
      "error_code": "EntityNotFound"
    }
  ]
}
  • results has one entry per requested item, in request order. vectors is present only when the item's error_code is Success ([] for an entity without vectors).
  • Only Success and EntityNotFound are reported per item. Any other per-item error fails the whole request with 500 and "error_message": "error when fetching entity vectors for <entity_id> . reason for error is: internal server error: <ErrorCode>".
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "entities": [
    { "entity_id": "node1" },
    { "entity_id": "node2" },
    { "entity_id": "nodeX" }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "entity_id": "node1",
      "error_code": "Success",
      "vectors": [
        {
          "name": "profile_vec",
          "type": "Float32",
          "vector_data": [0.12, 0.34, 0.56, 0.78]
        },
        {
          "name": "sparse_pref",
          "type": "SFloat32",
          "vector_data": [
            [0, 1.0],
            [3, 2.5]
          ]
        }
      ]
    },
    {
      "entity_id": "node2",
      "error_code": "Success",
      "vectors": []
    },
    {
      "entity_id": "nodeX",
      "error_code": "EntityNotFound"
    }
  ]
}

5.10 /batch_create_relationship

Description

Creates multiple relationships in one request. Each item adds an edge from src_entity_id to dest_entity_id labelled relationship_id. Reusing a relationship_id that already exists is not rejected: another edge with that ID is added (repeating the same triple adds a duplicate edge).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationships": [
    {
      "src_entity_id": "string",
      "relationship_id": "string",
      "dest_entity_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): Every item needs the three string fields. An empty array returns 200 with {"error_code": "Success"}.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Every item is attempted, and the relationships that can be created are created even when others fail. The first failure, in request order, is returned with "error_message": "error when creating relationship <relationship_id> . reason for error is: <reason>":

  • 404, GraphNotFound: reason graph does not exist.
  • 404, EntityNotFound: reason entity does not exist.
  • 500, other codes: reason internal server error: <ErrorCode>.

A relationship_id that already exists is not an error: the edge is added under that id and the item succeeds (the handler has a 409 RelationshipExist branch, but the server never produces that code here).

Example

Request:

POST /batch_create_relationship
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "relationships": [
    {
      "src_entity_id": "nd1",
      "relationship_id": "rel1",
      "dest_entity_id": "nd2"
    },
    {
      "src_entity_id": "nd2",
      "relationship_id": "rel2",
      "dest_entity_id": "nd3"
    },
    {
      "src_entity_id": "nd3",
      "relationship_id": "rel3",
      "dest_entity_id": "nd4"
    }
  ],
  "use_job": false
}

Response (404 Not Found, when nd4 does not exist; rel1 and rel2 are still created):

{
  "error_code": "EntityNotFound",
  "error_message": "error when creating relationship rel3 . reason for error is: entity does not exist"
}

5.11 /batch_remove_relationship

Description

Removes multiple relationships in one request. Each item removes the edge from src_entity_id to dest_entity_id labelled relationship_id. The relationship record itself is kept: its attributes and vectors can still be read by relationship_id.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "relationships": [
    {
      "src_entity_id": "string",
      "relationship_id": "string",
      "dest_entity_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): Every item needs the three string fields. An empty array returns 200 with {"error_code": "Success"}.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Relationships are removed in request order and processing stops at the first failure: items before it stay removed and items after it are not attempted. The failure is returned with "error_message": "error when removing relationship <relationship_id> . reason for error is: <reason>":

  • 404, GraphNotFound: reason graph does not exist.
  • 404, EntityNotFound: reason entity does not exist.
  • 404, RelationshipNotFound: reason relationship does not exist.
  • 500, other codes: reason internal server error: <ErrorCode>.

Example

Request:

POST /batch_remove_relationship
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "relationships": [
    {
      "src_entity_id": "nd1",
      "relationship_id": "rel1",
      "dest_entity_id": "nd2"
    },
    {
      "src_entity_id": "nd2",
      "relationship_id": "rel2",
      "dest_entity_id": "nd3"
    },
    {
      "src_entity_id": "nd3",
      "relationship_id": "rel3",
      "dest_entity_id": "nd4"
    }
  ],
  "use_job": false
}

Response (404 Not Found, when there is no rel3 edge from nd3 to nd4; rel1 and rel2 are still removed):

{
  "error_code": "RelationshipNotFound",
  "error_message": "error when removing relationship rel3 . reason for error is: relationship does not exist"
}

5.12 /batch_set_relationship_attributes

Description

Sets attributes and vectors for multiple relationships in one request. Attributes are merged and vectors replace same-name vectors, as in /batch_set_entity_attributes.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id"    : "string",
  "relationships"  : [
    {
      "relationship_id": "string",
      "attributes": {
        "string": "string",
        ...
      },
      "vectors": [
        {
          "name": "string",
          "type": "Float32" | "SFloat32",
          "vector_data": [ ... ]
        }
      ]
    },
    ...
  ],
  "use_job": false
}
  • Field rules and request validation errors are the same as for /batch_set_entity_attributes, with relationships and relationship_id in place of entities and entity_id.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Every item is attempted, and the items that succeed are applied even when others fail. The first failure, in request order, is returned with "error_message": "error when setting relationship attributes for <relationship_id> . reason for error is: <reason>":

  • 404, GraphNotFound: reason graph does not exist.
  • 404, RelationshipNotFound: reason relationship does not exist.
  • 400, InvalidParameter / InvalidVectorType / InvalidData: reason a vector cannot be stored under its name (see the index on that name), for a vector that a linear index on its name cannot take (see Index Types).
  • 500, other codes: reason internal server error: <ErrorCode>.

Example

Request:

POST /batch_set_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "relationships": [
    {
      "relationship_id": "node1",
      "attributes": {
        "name": "Alice",
        "age": "30",
        "country": "Canada"
      },
      "vectors": [
        {
          "name": "profile_vec",
          "type": "Float32",
          "vector_data": [0.12, 0.34, 0.56, 0.78]
        },
        {
          "name": "sparse_pref",
          "type": "SFloat32",
          "vector_data": [
            [0, 1.0],
            [3, 2.5]
          ]
        }
      ]
    },
    {
      "relationship_id": "node2",
      "attributes": {
        "name": "Bob",
        "age": "25"
      }
    },
    {
      "relationship_id": "node3",
      "vectors": [
        {
          "name": "profile_vec",
          "type": "Float32",
          "vector_data": [0.01, 0.02, 0.03]
        }
      ]
    }
  ],
  "use_job": false
}

Response (404 Not Found, when node2 does not exist and the other items succeed):

{
  "error_code": "RelationshipNotFound",
  "error_message": "error when setting relationship attributes for node2 . reason for error is: relationship does not exist"
}

5.13 /batch_remove_relationship_attributes

Description

Removes previously set string‑valued attributes and/or vectors from multiple relationships in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "relationships": [
    {
      "relationship_id":       "string",
      "attribute_names": ["string", ...],
      "vector_names":      ["string", ...]
    },
    ...
  ],
  "use_job": false
}
  • Field rules are the same as for /batch_remove_entity_attributes: attribute_names and vector_names are optional, a missing attribute fails the item with AttributeNotFound, a missing vector name is ignored, and an empty relationships array returns 200 with {"error_code": "Success"}.

Response

Success Response (200 OK):

{
  "error_code": "Success"
}

Every item is attempted, and the items that succeed are applied even when others fail. The first failure, in request order, is returned with "error_message": "error when removing relationship attributes for <relationship_id> . reason for error is: <reason>":

  • 404, GraphNotFound: reason graph does not exist.
  • 404, RelationshipNotFound: reason relationship does not exist.
  • 404, AttributeNotFound: reason attribute(s) does not exist.
  • 500, other codes: reason internal server error: <ErrorCode>.

Example

Request (node2 lists no vectors; node3 lists neither attributes nor vectors, which is a no-op):

POST /batch_remove_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "relationships": [
    {
      "relationship_id":       "node1",
      "attribute_names": ["age","country"],
      "vector_names": ["profile_vec"]
    },
    {
      "relationship_id":       "node2",
      "attribute_names": ["name"]
    },
    {
      "relationship_id":  "node3"
    }
  ],
  "use_job": false
}

Response (404 Not Found, when node2 does not exist):

{
  "error_code": "RelationshipNotFound",
  "error_message": "error when removing relationship attributes for node2 . reason for error is: relationship does not exist"
}

5.14 /batch_get_relationship_attributes

Description

Fetches string‑valued attributes for multiple relationships in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "relationships": [
    {
      "relationship_id":       "string",
      "attribute_names": ["string", ...]
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.
  • relationship_id (string, required) and attribute_names (array of strings, required) in every item.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id":  "string",
      "error_code": "string",
      "values":      ["string", ...]
    },
    ...
  ]
}
  • results has one entry per requested item, in request order. values is present only when the item's error_code is Success, in the order of attribute_names; if any requested attribute is missing the item's error_code is AttributeNotFound and no values are returned.
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "relationships": [
    { "relationship_id": "node1", "attribute_names": ["name","age"] },
    { "relationship_id": "node2", "attribute_names": ["country"]   },
    { "relationship_id": "nodeX", "attribute_names": ["name"]      }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id": "node1",
      "error_code": "Success",
      "values": ["Alice", "30"]
    },
    {
      "relationship_id": "node2",
      "error_code": "AttributeNotFound"
    },
    {
      "relationship_id": "nodeX",
      "error_code": "RelationshipNotFound"
    }
  ]
}

5.15 /batch_get_all_relationship_attributes

Description

Fetches all string‑valued attributes for multiple relationships in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "relationships": [
    {
      "relationship_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id":"string",
      "error_code":     "string",
      "attributes": {
        "string": "string",
        ...
      }
    },
    ...
  ]
}
  • results has one entry per requested item, in request order. attributes is present only when the item's error_code is Success ({} for a relationship without attributes).
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_all_relationship_attributes
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "relationships": [
    {"relationship_id": "node1"},
    {"relationship_id": "node2"},
    {"relationship_id": "nodeX"}
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id": "node1",
      "error_code":        "Success",
      "attributes": {
        "name": "Alice",
        "age": "30",
        "country": "Canada"
      }
    },
    {
      "relationship_id": "node2",
      "error_code":        "Success",
      "attributes": { "name": "Bob" }
    },
    {
      "relationship_id": "nodeX",
      "error_code": "RelationshipNotFound"
    }
  ]
}

5.16 /batch_get_relationship_vectors

Description

Fetches specified vectors for multiple relationships in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "relationships": [
    {
      "relationship_id": "string",
      "vector_names": ["string", ...]
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.
  • relationship_id (string, required) and vector_names (array of strings, required) in every item.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
      {
        "relationship_id": "string",
        "error_code": "string",
        "vectors": [
          {
            "name": "string",
            "type": "Float32" | "SFloat32",
            "vector_data": [ ... ]
          },
          ...
        ]
      },
    ...
  ]
}
  • results has one entry per requested item, in request order. vectors is present only when the item's error_code is Success, in the order of vector_names.
  • Only Success and RelationshipNotFound are reported per item. Any other per-item error fails the whole request with 500 and "error_message": "error when fetching relationship vectors for <relationship_id> . reason for error is: internal server error: <ErrorCode>".
  • If an existing relationship has no vector with a requested name, the whole request fails with 500 and {"error_code": "InvalidData", "error_message": "error in parsing vectors"}.
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_relationship_vectors
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "relationships": [
    { "relationship_id": "node1", "vector_names": ["vector_a", "vector_b"] },
    { "relationship_id": "node2", "vector_names": ["vector_c"] },
    { "relationship_id": "nodeX", "vector_names": ["vector_y"] }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
      {
        "relationship_id": "node1",
        "error_code": "Success",
        "vectors": [
          {
            "name": "vector_a",
            "type": "Float32",
            "vector_data": [0.1, 0.2, 0.3]
          },
          {
            "name": "vector_b",
            "type": "Float32",
            "vector_data": [0.4, 0.5, 0.6]
          }
        ]
      },
      {
        "relationship_id": "node2",
        "error_code": "Success",
        "vectors": [
          {
            "name": "vector_c",
            "type": "Float32",
            "vector_data": [0.7, 0.8]
          }
        ]
      },
    {
      "relationship_id": "nodeX",
      "error_code": "RelationshipNotFound"
    }
  ]
}

5.17 /batch_get_all_relationship_vector_names

Description

Fetches all vector names (keys) for multiple relationships in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "relationships": [
    {
      "relationship_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id": "string",
      "error_code": "string",
      "names": ["string", ...]
    },
    ...
  ]
}
  • results has one entry per requested item, in request order. names is present only when the item's error_code is Success ([] for a relationship without vectors); the order of the names is not guaranteed.
  • Only Success and RelationshipNotFound are reported per item. Any other per-item error fails the whole request with 500 and "error_message": "error when fetching relationship vector names for <relationship_id> . reason for error is: internal server error: <ErrorCode>".
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

POST /batch_get_all_relationship_vector_names
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id":     "graph_ABC",
  "relationships": [
    { "relationship_id": "node1" },
    { "relationship_id": "node2" },
    { "relationship_id": "nodeX" }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id": "node1",
      "error_code": "Success",
      "names": ["profile_vec", "sparse_pref"]
    },
    {
      "relationship_id": "node2",
      "error_code": "Success",
      "names": []
    },
    {
      "relationship_id": "nodeX",
      "error_code": "RelationshipNotFound"
    }
  ]
}

5.18 /batch_get_all_relationship_vectors

Description

Fetches all vectors (dense and sparse) for multiple relationships in one request.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id":     "string",
  "relationships": [
    {
      "relationship_id": "string"
    },
    ...
  ],
  "use_job": false
}
  • relationships (array, required): An empty array returns 200 with {"error_code": "Success", "results": []}.

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id": "node1",
      "error_code": "Success",
      "vectors": [
        {
          "name":        "string",
          "type":        "string",
          "vector_data": [ ... ]
        },
        {
          "name":        "string",
          "type":        "string",
          "vector_data": [ ... ]
        }
      ]
    },
    {
      "relationship_id": "node2",
      "error_code": "Success",
      "vectors": []
    },
    {
      "relationship_id": "nodeX",
      "error_code": "RelationshipNotFound"
    }
  ]
}
  • results has one entry per requested item, in request order. vectors is present only when the item's error_code is Success ([] for a relationship without vectors).
  • Only Success and RelationshipNotFound are reported per item. Any other per-item error fails the whole request with 500 and "error_message": "error when fetching relationship vectors for <relationship_id> . reason for error is: internal server error: <ErrorCode>".
  • If the graph does not exist the request fails with 404 and {"error_code": "GraphNotFound", "error_message": "graph does not exist"}.

Example

Request:

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "relationships": [
    { "relationship_id": "node1" },
    { "relationship_id": "node2" },
    { "relationship_id": "nodeX" }
  ],
  "use_job": false
}

Response:

{
  "error_code": "Success",
  "results": [
    {
      "relationship_id": "node1",
      "error_code": "Success",
      "vectors": [
        {
          "name": "profile_vec",
          "type": "Float32",
          "vector_data": [0.12, 0.34, 0.56, 0.78]
        },
        {
          "name": "sparse_pref",
          "type": "SFloat32",
          "vector_data": [
            [0, 1.0],
            [3, 2.5]
          ]
        }
      ]
    },
    {
      "relationship_id": "node2",
      "error_code": "Success",
      "vectors": []
    },
    {
      "relationship_id": "nodeX",
      "error_code": "RelationshipNotFound"
    }
  ]
}

5.19 /batch_search_entity_index

Description

Executes multiple /search_entity_index queries in a single request. Each query can perform either exact attribute matching or vector similarity search and may include its own filter.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "batch_queries": [
    {
      "attribute_name": "string",
      "index_type": "string",
      // Provide exactly one of the following:
      "attribute_value": "string",
      "vector": { "type": "Float32", "vector_data": [ ... ] },
      "top_k": 5,
      "similarity_measure": "Cosine",
      "entity_filter": { ... }
    },
    ...
  ],
  "use_job": false
}
  • batch_queries (array, required): Ordered list of searches. An empty array returns 200 with {"error_code": "Success", "results": []}. For vector indices supply the vector object under vector; for attribute indices supply attribute_value (a string).
  • attribute_name, index_type (strings, required): index_type is one of "Vector Index", "Attribute Index", "Fuzzy Attribute Index", "Integer Linear Index", "Float Linear Index"; another value gives the query UnknownIndexType.
  • top_k (integer from 1 to 2147483647, optional, default 5), similarity_measure (string, optional, default "Euclidean"; one of Euclidean, InnerProduct, Cosine, Custom, Hamming, WeightedJaccard, WeightedContainment, BM25), and entity_filter (filter object, optional) are per-query overrides.

Response

{
  "error_code": "Success",
  "results": [
    {
      "attribute_name": "string",
      "index_type": "string",
      "entity_ids": ["string", ...],
      "error_code": "Success"
    },
    ...
  ]
}
  • The results array aligns with batch_queries order. Each entry echoes the query metadata and includes the per-query error_code (for example IndexNotFound, UnknownIndexType, InvalidParameter); entity_ids is [] for a query that failed. Each query behaves like the same query sent to /search_entity_index: for example, a query on a Vector Index whose vector is not dense Float32 gets InvalidParameter, and a query on an empty Vector Index gets Success with [].
  • With "use_job": true, /get_job_result returns the same results.

Error Responses:

  • 400: A query omitted both attribute_value and vector ("must contain either attribute value or vector") or provided both ("can not contain both attribute value and vector"); unsupported similarity_measure ("field with invalid value: similarity_measure"); a top_k that is not an integer from 1 to 2147483647 ("field with invalid value: top_k (must be an integer from 1 to 2147483647)"); missing attribute_name/index_type. These bodies are JSON.
  • 400, plain-text body field with invalid value: vector: the vector object could not be parsed.
  • 400, {"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}: entity_filter could not be parsed, or nests more than 64 levels of and/or/xor/not.
  • 404, {"error_code": "GraphNotFound", "error_message": "graph does not exist"}: the graph does not exist and the batch has at most one attribute query and at most one vector query. With more queries than that, a missing graph returns 500 with {"error_code": "Unknown", "error_message": "unexpected empty batch result"} instead.

Example

Request:

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "batch_queries": [
    {
      "attribute_name": "name",
      "index_type": "Attribute Index",
      "attribute_value": "Seattle"
    },
    {
      "attribute_name": "vector_location",
      "index_type": "Vector Index",
      "vector": {
        "type": "Float32",
        "vector_data": [47.6061, -122.3328]
      },
      "top_k": 3
    }
  ],
  "use_job": false
}

Example Response (200 OK)

Response:

{
  "error_code": "Success",
  "results": [
    {
      "attribute_name": "name",
      "index_type": "Attribute Index",
      "entity_ids": ["seattle_office", "seattle_hq"],
      "error_code": "Success"
    },
    {
      "attribute_name": "vector_location",
      "index_type": "Vector Index",
      "entity_ids": ["seattle_hq", "bellevue_branch", "tacoma_branch"],
      "error_code": "Success"
    }
  ]
}

5.20 /batch_search_relationship_index

Description

Vectorised equivalent of /search_relationship_index that evaluates several relationship-index queries in one call.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "batch_queries": [
    {
      "attribute_name": "string",
      "index_type": "string",
      // Provide exactly one of the following:
      "attribute_value": "string",
      "vector": { "type": "Float32", "vector_data": [ ... ] },
      "top_k": 5,
      "similarity_measure": "Cosine",
      "relationship_filter": { ... }
    },
    ...
  ],
  "use_job": false
}
  • Query fields, defaults and validation mirror /batch_search_entity_index, with relationship_filter applying the predicate at query time.

Response

{
  "error_code": "Success",
  "results": [
    {
      "attribute_name": "string",
      "index_type": "string",
      "relationship_ids": ["string", ...],
      "error_code": "Success"
    },
    ...
  ]
}

Error Responses:

  • 400: Missing or conflicting attribute_value/vector in a query, or another invalid query field, as for /batch_search_entity_index.
  • 400, {"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}: relationship_filter could not be parsed.
  • 404 or 500 when the graph does not exist, as for /batch_search_entity_index.

Example

Request:

{
  "user_api_key": "api_key_123",
  "graph_id": "graph_ABC",
  "batch_queries": [
    {
      "attribute_name": "type",
      "index_type": "Attribute Index",
      "attribute_value": "acted_in"
    },
    {
      "attribute_name": "vector_direction",
      "index_type": "Vector Index",
      "vector": {
        "type": "Float32",
        "vector_data": [0.01, 0.9, -0.2]
      },
      "relationship_filter": {
        "match_attribute": {
          "key": "status",
          "values": ["active"]
        }
      }
    }
  ],
  "use_job": false
}

Example Response (200 OK)

Response:

{
  "error_code": "Success",
  "results": [
    {
      "attribute_name": "type",
      "index_type": "Attribute Index",
      "relationship_ids": ["r101", "r203"],
      "error_code": "Success"
    },
    {
      "attribute_name": "vector_direction",
      "index_type": "Vector Index",
      "relationship_ids": ["r305", "r402"],
      "error_code": "Success"
    }
  ]
}

5.21 /import_entities

Description

Bulk-ingests entities from a CSV or JSON source. Provide format to select the parser and either a url (supports http://, https://, and file://) or inline file_data. Set use_job to queue the import as a background job.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "format": "csv",
  "url": "https://example.com/entities.csv",
  "headers": ["entity_id", "name", "vector_a"],
  "is_vector": [false, false, true],
  "use_job": true
}
  • format (required): "csv" or "json".
  • url or file_data: Location or literal contents of the file. url is used when present. The graph must exist: a missing graph returns 404 before anything is read or downloaded. The file is read before the job is queued, so download and file errors are returned directly even with use_job.
  • http:// or https://: the server downloads the file. Only public addresses are allowed: a URL (or a redirect, at most 10 are followed) that resolves to a loopback, private, link-local or other non-public address is rejected with 400. Downloads larger than 512 MiB (536870912 bytes) are rejected with 413.
  • file://<path>: a file in the graph's .files directory on the server. <path> must be a relative path without .. components, and the file (after resolving symlinks) must lie inside that directory; otherwise the request is rejected with 400. An absolute path such as file:///data/x.csv is rejected.
  • headers (CSV, array of strings, optional): Column names. The first column is the entity ID (its name is not checked); the other column names become attribute or vector names and must not be empty. The name of a vector column becomes a vector name and must follow the vector name rules of /batch_set_entity_attributes (400, "invalid vector name: <reason>"). If headers is omitted, the first line of the file is read as the header row. If it is given, the file must not contain a header row.
  • is_vector (CSV, array of booleans, optional): Which columns hold vectors; it must have one entry per header, and the first entry must be false. If it is omitted, the next line of the file is read as comma-separated 0/1 flags.
  • CSV rows: Attribute cells may be double-quoted (\" escapes a quote inside quotes); empty cells are stored as empty-string attributes. Vector cells are [1.0, 2.0] (dense) or [(0, 1.0), (3, 2.5)] (sparse), optionally in double quotes; a vector whose values contain no ., e or E is stored as an integer vector (Int32, or SInt32 when sparse). Rows that cannot be parsed (wrong column count, unterminated quote, invalid vector, an integer value outside the 32-bit signed range, a float value that overflows, empty ID) are not imported and are listed in invalid_rows.
  • JSON format: file_data must be a JSON object keyed by entity_id, each value an object with optional "attributes" (string map) and "vectors" (array of vector objects with name, type, vector_data). Entities are processed in key-sorted order.
  • use_job (optional): When true, return a job_id and process asynchronously.

Response

When use_job is true (202 Accepted):

{
  "error_code": "Success",
  "job_id": "string"
}

When use_job is false, the request completes synchronously and returns per-entity outcomes (200 OK). A CSV import:

{
  "error_code": "Success",
  "entity_ids": ["id1", "id2", "id3"],
  "create_ecs": ["Success", "Success", "EntityExist"],
  "set_ecs": ["Success", "Success", "Success"],
  "invalid_rows": [
    {"row": 4, "error": "invalid vector in column 'vector_a'"}
  ]
}
  • entity_ids: Every entity that was processed (CSV: in file order; JSON: in key order). Rows listed in invalid_rows are not included.
  • create_ecs: Result of creating each entity, aligned with entity_ids.
  • set_ecs: Result of setting each entity's attributes and vectors, aligned with entity_ids. Import is an upsert: importing an existing ID updates that entity (EntityExist in create_ecs, Success in set_ecs). CSV rows with nothing to set (only the ID column) get EmptyParameter. With CSV, a row whose create fails with any code other than EntityExist is not written, and its set_ecs repeats the create code. With JSON the set is attempted whatever the create result; entries with nothing to set get Success. A JSON entry with an unknown key or a non-string attribute value gets ParseError in both lists, and one whose vectors cannot be parsed or have an invalid name gets InvalidParameter in both; such entries are not created.
  • invalid_rows (CSV only): The rows that were not imported, as {"row": <line number in the file, counting from 1>, "error": <reason>}. The reason is "malformed value in column '<header>'", "invalid vector in column '<header>'" or "empty entity id". The array is [] when every row parsed. JSON imports do not return this field.

When use_job is true, the same payload is available in /get_job_result.

Error Responses (during request submission):

  • 400: Missing format, or neither url nor file_data ("missing field: file_data").
  • 400, {"error_code": "InvalidParameter", "error_message": "invalid graph_id: <reason>"}: graph_id breaks the /create_graph naming rules. Nothing is read or downloaded.
  • 404, {"error_code": "GraphNotFound", "error_message": "graph does not exist"}: the graph does not exist. Nothing is read or downloaded.
  • 400, InvalidParameter: URL scheme other than http://, https://, file:// ("Invalid url"); an http(s) URL that reaches a non-public address ("Invalid url: imports may only download from public addresses"); a file:// path that is empty, absolute, contains .. or a control character, or resolves outside the graph's .files directory ("invalid url: <reason>").
  • 400, InvalidFile: the file cannot be read ("Unable to open file", "Unable to determine file size", "Failed to read file").
  • 413, InvalidParameter: the download is larger than 512 MiB ("Import file exceeds the maximum download size of 536870912 bytes").
  • 502: Remote file could not be downloaded ({"error_code": "Unknown", "error_message": "Failed to download file: <reason>"}).

Parse errors are returned with 400 when use_job is false, and make the job fail with the same error_code and error_message when use_job is true: unsupported format (NotImplemented, "format not supported"), malformed headers or flags (InvalidParameter: "invalid csv header", "empty csv header", "header is empty", "invalid is_vector format", "invalid value for is_vector", "headers and is_vector have different sizes", "id column is labelled as vector", "unexpected eof", "invalid vector name: <reason>"), or invalid JSON ("Invalid JSON").

Per-entity failures (for example an existing ID) surface in create_ecs and set_ecs, and unparsable CSV rows in invalid_rows.

Example

Request:

POST /import_entities
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "format": "csv",
  "url": "https://data.example.com/entities.csv",
  "use_job": true
}

Response:

{
  "error_code": "Success",
  "job_id": "8b0c5f8e-3c1a-4c7e-9f61-2d4b7a9e1c33"
}

5.22 /import_relationships

Description

Imports relationships from CSV or JSON. Provide format and either a url or inline file_data. Set use_job to run asynchronously.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "format": "csv",
  "url": "file://relationships.csv",
  "headers": ["src_entity_id", "relationship_id", "dest_entity_id", "weight"],
  "is_vector": [false, false, false, false],
  "use_job": true
}
  • format (required): "csv" or "json".
  • url or file_data: Source CSV/JSON contents. url is handled as for /import_entities: http:// or https:// from a public address (at most 512 MiB), or file://<relative path> inside the graph's .files directory. A missing graph returns 404 before anything is read or downloaded. For CSV, omit headers/is_vector to parse them from the file. Columns 1–3 are the source entity ID, relationship ID and destination entity ID, in that order, and must not be vectors; the remaining columns become attributes or vectors (a vector column's header must be a valid vector name, as for /import_entities). CSV rows are parsed as for /import_entities; rows that cannot be parsed, or that have an empty ID cell, are not imported and are listed in invalid_rows.
  • headers (CSV): Override parsed headers. There must be at least three headers and the first three must not be empty (their names are not checked). If headers is given, the file must not contain a header row.
  • is_vector (CSV): Override parsed flags; one entry per header, and the first three entries must be false. If it is omitted, the next line of the file is read as 0/1 flags.
  • JSON format: Provide an array (or an object with a relationships array) of objects each containing src_entity_id, relationship_id, dest_entity_id, optional "attributes" (string map), and optional "vectors" (vector objects).
  • use_job (optional): When true, return a job_id and process asynchronously.

Response

When use_job is true (202 Accepted):

{
  "error_code": "Success",
  "job_id": "string"
}

When use_job is false, the response lists per-relationship create/set outcomes (200 OK). A CSV import:

{
  "error_code": "Success",
  "relationship_ids": ["rel1", "rel2", "rel_bad1"],
  "create_ecs": ["Success", "Success", "EntityNotFound"],
  "set_ecs": ["Success", "Success", "EntityNotFound"],
  "invalid_rows": []
}
  • relationship_ids: Every relationship that was processed, in input order (a JSON entry without a string relationship_id appears as "").
  • create_ecs: Result of creating each relationship, aligned with relationship_ids.
  • set_ecs: Result of setting each relationship's attributes and vectors, aligned with relationship_ids. Import is an upsert: a row whose relationship_id already exists creates its edge with Success and its attributes are updated. CSV rows with nothing to set get EmptyParameter. With CSV, a row whose create fails with any other code (for example EntityNotFound when the source or destination entity is missing) is not written, and its set_ecs repeats the create code. With JSON the set is attempted whatever the create result; entries with nothing to set get Success. A JSON entry with a missing or non-string ID field, non-string attributes, or vectors that cannot be parsed or have an invalid name gets ParseError in both lists and is not created.
  • invalid_rows (CSV only): The rows that were not imported, as for /import_entities. The reason is "malformed value in column '<header>'", "invalid vector in column '<header>'" or "empty source, relationship or destination id". JSON imports do not return this field.

When use_job is true, the same payload is available in /get_job_result.

Error Responses:

  • 400: Missing format, or neither url nor file_data; unsupported URI scheme ("Invalid url"), a non-public http(s) address, or a file:// path outside the graph's .files directory (InvalidParameter, messages as for /import_entities); file cannot be read (InvalidFile).
  • 400, {"error_code": "InvalidParameter", "error_message": "invalid graph_id: <reason>"}: graph_id breaks the /create_graph naming rules. Nothing is read or downloaded.
  • 404, {"error_code": "GraphNotFound", "error_message": "graph does not exist"}: the graph does not exist. Nothing is read or downloaded.
  • 413, InvalidParameter: the download is larger than 512 MiB.
  • 502: Remote file could not be downloaded ({"error_code": "Unknown", "error_message": "Failed to download file: <reason>"}).
  • 400 (or a failed job when use_job is true): unsupported format (InvalidParameter, "format not supported"), invalid or incomplete header ("relationship csv requires src, id, dest", "relationship csv id columns cannot have empty headers", "headers and is_vector have different sizes", "src/relationship/dest columns cannot be vectors", "invalid vector name: <reason>", or the CSV header/flag errors listed for /import_entities), invalid JSON ("Invalid JSON"), or JSON that is neither an array nor an object with a relationships array ("invalid json format").

Per-relationship failures surface in create_ecs and set_ecs, and unparsable CSV rows in invalid_rows.

Example

Request:

POST /import_relationships
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "format": "csv",
  "url": "https://data.example.com/relationships.csv",
  "use_job": true
}

Response:

{
  "error_code": "Success",
  "job_id": "1f9cb0f7-5d2e-4a8b-b3c4-7e6f0a1d2b39"
}

6. Node Embedding Algorithms

6.1 /remove_model

Description

Deletes a stored embedding model by name for the authenticated user, together with its files on the server. Models belong to the user, not to a graph. This is needed before retraining with the same name: /sage_train, /gcn_train and /attention_train fail with ModelNameExist when model_name is already in use. This endpoint does not accept use_job. model_name must be 1 to 128 characters long, must not contain /, \ or control characters, and must not be . or ..; otherwise the server returns 400 (for example "invalid model_name: must not be empty"). Removal is all-or-nothing: if it fails, the model stays listed and usable.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "model_name": "string"
}

Response

{
  "error_code": "Success",
  "model_name": "string"
}

Error Responses:

  • 400: Invalid model_name.
  • 404: "model does not exist".

Example

Request:

POST /remove_model
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "model_name": "sage_model"
}

Response:

{
  "error_code": "Success",
  "model_name": "sage_model"
}

6.2 /node2vec

Description

Runs the Node2Vec algorithm to generate node embeddings. Biased random walks are sampled with parameters p and q, then a skip-gram style model trains vectors of dimension emb_dim. Embeddings are stored on each node as a Float32 vector of length emb_dim named embedding_name. All Node2Vec parameters are configurable; computation runs with a fixed thread count managed by the server (not configurable).

All fields except use_job are required; the values shown below are examples, not defaults. The server rejects p or q ≤ 0, walk_len, num_walks, emb_dim, window_size or num_epochs ≤ 0, walk_len or num_walks > 1000, emb_dim > 4096, negative_samples < 0, and learning_rate ≤ 0 with 400 ("invalid node2vec parameters"), also when use_job is true. An embedding_name that is empty, longer than 128 characters, contains /, \ or control characters, or is . or .. also gives "invalid node2vec parameters" (with use_job, the job fails with InvalidParameter).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "p": 1.0,
  "q": 1.0,
  "walk_len": 40,
  "num_walks": 10,
  "emb_dim": 128,
  "window_size": 10,
  "negative_samples": 5,
  "num_epochs": 5,
  "learning_rate": 0.01,
  "embedding_name": "node2vec",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "embedding_name": "node2vec"
}

Error Responses:

  • 400: Missing field, or "invalid node2vec parameters".
  • 404: Graph does not exist.

Example

Request:

POST /node2vec
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "p": 1.0,
  "q": 1.0,
  "walk_len": 40,
  "num_walks": 10,
  "emb_dim": 64,
  "window_size": 10,
  "negative_samples": 5,
  "num_epochs": 5,
  "learning_rate": 0.01,
  "embedding_name": "node2vec",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.3 /fastrp

Description

Runs the Fast Random Projection (FastRP) algorithm to generate node embeddings. Iterative random projections are weighted by iteration_weights to balance hop influence. Embeddings are stored on each node as a Float32 vector of length embedding_dim named embedding_name. Computation uses an internal offload batch size (not exposed as a parameter) and runs with a fixed thread count managed by the server (not configurable).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "embedding_dim": 64,
  "iteration_weights": [0.0, 1.0, 1.0],
  "normalization_strength": 0.0,   // optional, default 0.0
  "node_self_influence": 0.0,      // optional, default 0.0
  "random_seed": -1,               // optional, default -1
  "embedding_name": "fastrp",
  "use_job": false
}
  • embedding_dim, iteration_weights and embedding_name are required (the values above are examples). embedding_dim must be an integer from 1 to 4096, iteration_weights must be a non-empty array of numbers, and normalization_strength must be between -1 and 1. Otherwise the server returns 400 ("invalid fastrp parameters"), also when use_job is true. An invalid embedding_name (same rules as for /node2vec) also gives "invalid fastrp parameters".

Response

{
  "error_code": "Success",
  "embedding_name": "fastrp"
}

Error Responses:

  • 400: Missing field, or "invalid fastrp parameters".
  • 404: Graph does not exist.

Example

Request:

POST /fastrp
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "embedding_dim": 32,
  "iteration_weights": [0.0, 1.0, 1.0],
  "embedding_name": "custom_fastrp",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.4 /hashgnn

Description

Runs the HashGNN algorithm to generate node embeddings. Embeddings are stored on each node as a Float32 vector named embedding_name. When output_dim > 0 the vector is a dense projection of length output_dim; otherwise it has length embedding_dim and holds only 0/1 values. Optionally, feature_attribute names an entity vector whose values are binarized and used as initial features; if no entity has that vector, random initialization is used. Computation runs with a fixed thread count managed by the server (not configurable).

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "iterations": 5,
  "embedding_density": 4,
  "embedding_dim": 128,
  "neighbor_influence": 1.0,    // optional, default 1.0
  "random_seed": -1,            // optional, default -1 (random seed for each run)
  "embedding_name": "hashgnn",
  "output_dim": -1,             // optional, default -1
  "initial_density": 3,         // optional, default 3
  "feature_attribute": "",      // optional, default ""
  "use_job": false
}
  • iterations, embedding_density, embedding_dim and embedding_name are required (the values above are examples). iterations must be from 1 to 1000, embedding_density and embedding_dim from 1 to 4096, output_dim and initial_density at most 4096, and neighbor_influence must be ≥ 0. Otherwise the server returns 400 ("invalid hashgnn parameters"), also when use_job is true. An invalid embedding_name (same rules as for /node2vec) also gives "invalid hashgnn parameters".

Response

{
  "error_code": "Success",
  "embedding_name": "hashgnn"
}

Error Responses:

  • 400: Missing field, or "invalid hashgnn parameters".
  • 404: Graph does not exist.

Example

Request:

POST /hashgnn
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "iterations": 3,
  "embedding_density": 4,
  "embedding_dim": 64,
  "neighbor_influence": 1.0,
  "embedding_name": "custom_hashgnn",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.5 /sage_train

Description

Runs the GraphSAGE algorithm to generate node embeddings and saves the trained model as model_name. Training writes the embeddings to every node as a Float32 vector of length embedding_dimension named embedding_name. This endpoint is only available in server builds with LibTorch; other builds return 400 ("graphsage not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "iterations": 100,
  "batch_size": 32,
  "embedding_dimension": 128,
  "feature_properties": [],
  "learning_rate": 0.01,
  "sample_sizes": [25, 10],
  "aggregator": "mean",
  "negative_sample_weight": 1,
  "penalty_l2": 0.0001,
  "tolerance": 1e-6,
  "epochs": 10,
  "max_iterations": 1000,
  "activation_function": "relu",
  "random_seed": 42,
  "embedding_name": "sage_embedding",
  "is_multi_label": false,
  "projected_feature_dimension": 0,
  "neighbor_influence": 1.0,
  "search_depth": 2,
  "dropout_rate": 0.5,
  "use_residual": true,
  "include_self": true,
  "device": "cpu",
  "use_job": false
}
  • Only model_name is required. Every other field is optional, and the values above are the defaults.
  • feature_properties: names of entity vectors that are concatenated as input features. Every entity must give the same total width. When it is empty, embedding_dimension random features are used.
  • projected_feature_dimension: width of the hidden layers, that is, of every layer except the last. 0 (default) means embedding_dimension. It does not need to match the width of feature_properties; the input width is taken from the features.
  • aggregator: "mean" (default) or "pool". "lstm" is accepted but runs the mean aggregator. Any other string returns 400 ("aggregator must be one of: mean, pool, lstm").
  • activation_function: "relu" (default), "sigmoid", "tanh" or "none". Any other string returns 400 ("activation_function must be one of: relu, sigmoid, tanh, none").
  • include_self: when true (default), a node's own features are averaged (mean) or max-pooled (pool) together with its neighbours' features. When false, the node's own features and the aggregated neighbour features go through separate weights. use_residual (default true) adds a residual connection to each layer.
  • random_seed: seeds all of training's randomness, so the same request on the same graph reproduces a run.
  • sample_sizes sets the number of layers and the neighbors sampled per layer. Each epoch is one training step over all nodes. iterations, batch_size, tolerance, max_iterations, is_multi_label, neighbor_influence and search_depth are accepted but currently have no effect.
  • Range limits: embedding_dimension 1 to 4096, projected_feature_dimension 0 to 4096, epochs 0 to 100000, negative_sample_weight 0 to 100, and 1 to 10 sample_sizes entries, each 1 to 1000. A value outside its range returns 400 with a message such as "embedding_dimension must be in [1, 4096]", also when use_job is true.
  • model_name and a non-empty embedding_name must be 1 to 128 characters long, must not contain /, \ or control characters, and must not be . or ... Otherwise the server returns 400 ("invalid sage_train parameters"); with use_job, the job fails with InvalidParameter.
  • device (optional, default "cpu"): "cpu", "cuda", "cuda:N" or "auto" (case-insensitive). Any other value returns 400 ("device must be one of: cpu, cuda, cuda:N, auto"). If the requested CUDA device is not available, training runs on the CPU. If the GPU runs out of memory, training is retried once on the CPU. A job result also reports trained_on (for example "cpu" or "cuda:0").
  • Training fails if model_name already exists for this user (500, error_code "ModelNameExist"); remove the old model with /remove_model first.

Response

{
  "error_code": "Success",
  "embedding_name": "sage_embedding"
}

Error Responses:

  • 400: Invalid field type, invalid device, unknown aggregator or activation_function, a value out of range, or "invalid sage_train parameters".
  • 404: Graph does not exist.
  • 500: ModelNameExist, or a training failure such as TrainFailed.

Example

Request:

POST /sage_train
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "sage_model",
  "embedding_dimension": 16,
  "epochs": 1,
  "batch_size": 8,
  "sample_sizes": [5, 5],
  "aggregator": "mean",
  "activation_function": "relu",
  "embedding_name": "custom_sage",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.6 /sage_infer

Description

Runs GraphSAGE inference from a previously trained model on the current graph. Embeddings are written to every node under the embedding_name saved with the model. Inference always runs on the CPU. If the model was trained without feature_properties, inference regenerates the random features from the saved random_seed, so on an unchanged graph it reproduces the training embeddings (for models trained by the current server version). Requires a LibTorch build (otherwise 400, "graphsage not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "model_name": "sage_model"
}

Error Responses:

  • 404: "graph does not exist".
  • 404: "model not found".

Example

Request:

POST /sage_infer
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "sage_model",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.7 /gcn_train

Description

Runs the GCN algorithm to generate node embeddings and saves the trained model as model_name. Training writes the embeddings to every node as a Float32 vector of length embedding_dimension named embedding_name. Requires a LibTorch build (otherwise 400, "gcn not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "iterations": 100,
  "batch_size": 32,
  "embedding_dimension": 128,
  "feature_properties": [],
  "learning_rate": 0.01,
  "dropout_rate": 0.5,
  "negative_sample_weight": 1,
  "penalty_l2": 0.0001,
  "tolerance": 1e-6,
  "epochs": 100,
  "max_iterations": 1000,
  "activation_function": "relu",
  "num_threads": 0,
  "random_seed": 42,
  "embedding_name": "gcn_embedding",
  "is_multi_label": false,
  "projected_feature_dimension": 0,
  "normalize_features": true,
  "self_loops": true,
  "use_sparse_adjacency": true,
  "use_supervised": false,
  "label_attribute": "label",
  "num_classes": 2,
  "supervised_loss_weight": 1.0,
  "reconstruction_loss_weight": 1.0,
  "device": "cpu",
  "use_job": false
}
  • Only model_name is required. Every other field is optional, and the values above are the defaults.
  • epochs: number of full-graph training steps.
  • feature_properties: names of entity vectors used as input features. When it is empty, random features are used. When it is set, projected_feature_dimension must be > 0, otherwise the server returns 400 ("projected_feature_dimension required with feature_properties"). projected_feature_dimension > 0 adds a hidden layer of that width. activation_function and dropout_rate only affect that hidden layer.
  • activation_function: "relu" (default), "sigmoid", "tanh" or "none". Any other string falls back to "relu".
  • num_threads: 0 keeps the server's LibTorch thread count. A positive value sets the LibTorch thread count while this training runs; the previous count is restored afterwards. It must be at most the number of CPU cores.
  • random_seed: seeds the weight initialization, the random features and dropout, so the same request on the same graph reproduces a run.
  • Range limits: embedding_dimension 1 to 4096, projected_feature_dimension 0 to 4096, epochs 0 to 100000, num_classes 1 to 4096, and num_threads 0 to the number of CPU cores. A value outside its range returns 400 with a message such as "num_threads must be in [0, 8]", also when use_job is true.
  • model_name and a non-empty embedding_name must be 1 to 128 characters long, must not contain /, \ or control characters, and must not be . or ... Otherwise the server returns 400 ("invalid gcn_train parameters"); with use_job, the job fails with InvalidParameter.
  • On a graph with no entities, training fails with 500 (NotEnoughData).
  • use_supervised: also trains a classifier on the string attribute label_attribute. If every label is an integer, it is used as the class index. Otherwise the distinct label strings are sorted and numbered from 0. Every class index must be in [0, num_classes), otherwise the server returns 400 ("invalid gcn_train parameters"). If no entity has the label, training fails with 500 (InvalidData). batch_size only limits how many labelled nodes are sampled for the supervised loss.
  • iterations, tolerance, max_iterations and is_multi_label are accepted but currently have no effect.
  • device (optional, default "cpu"): "cpu", "cuda", "cuda:N" or "auto" (case-insensitive). Any other value returns 400 ("device must be one of: cpu, cuda, cuda:N, auto"). If the requested CUDA device is not available, training runs on the CPU. If the GPU runs out of memory, training is retried once on the CPU. A job result also reports trained_on (for example "cpu" or "cuda:0").
  • Training fails if model_name already exists for this user (500, error_code "ModelNameExist"); remove the old model with /remove_model first.

Response

{
  "error_code": "Success",
  "embedding_name": "gcn_embedding"
}

Error Responses:

  • 400: Invalid field, invalid device, a value out of range, or "invalid gcn_train parameters".
  • 404: Graph does not exist.
  • 500: ModelNameExist, NotEnoughData, or another training failure.

Example

Request:

POST /gcn_train
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "gcn_model",
  "embedding_dimension": 16,
  "epochs": 1,
  "batch_size": 8,
  "activation_function": "relu",
  "embedding_name": "custom_gcn",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.8 /gcn_infer

Description

Runs GCN inference from a previously trained model on the current graph. Embeddings are written to every node under the embedding_name saved with the model. Inference always runs on the CPU. If the model was trained without feature_properties, it reuses the random features saved at training time and fails with 500 (InvalidData) unless the graph's entities are exactly the same as at training time. Requires a LibTorch build (otherwise 400, "gcn not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "model_name": "gcn_model"
}

Error Responses:

  • 404: "graph does not exist".
  • 404: "model not found".

Example

Request:

POST /gcn_infer
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "gcn_model",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.9 /gcn_predict

Description

Runs GCN prediction from a supervised model (trained with use_supervised: true) and returns a predicted class index (integer) for every entity in the graph. Predictions are not written to the graph. If the training labels were not all integers, the indices follow the sorted order of the label strings, and that mapping is not returned. By default, prediction keys are internal numeric entity IDs serialized as strings. With use_entity_ids: true they are the entity IDs instead. Requires a LibTorch build (otherwise 400, "gcn not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "use_entity_ids": false,     // optional, default false
  "use_job": false
}

Response

{
  "error_code": "Success",
  "model_name": "gcn_model",
  "predictions": {
    "123": 0,
    "456": 1
  }
}

Error Responses:

  • 400: "invalid gcn_predict parameters", if the model was not trained with use_supervised: true.
  • 404: "graph does not exist".
  • 404: "model not found".

Example

Request:

POST /gcn_predict
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "gcn_model",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.10 /attention_train

Description

Runs the Graph Attention Network (GAT) training routine and saves the trained model as model_name. When task_type is unsupervised, training writes embeddings to each node as a Float32 vector named embedding_name. Its length is the last entry of hidden_dims. Supervised training does not write embeddings; /attention_infer does. Requires a LibTorch build (otherwise 400, "attention not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "epochs": 10,
  "embedding_dimension": 128,
  "learning_rate": 0.001,
  "penalty_l2": 0.0001,
  "dropout_rate": 0.0,
  "train_split": 0.8,
  "num_heads": 8,
  "hidden_dims": [128, 64],
  "attention_dropout": 0.0,
  "negative_slope": 0.2,
  "task_type": "classification",
  "target_attribute": "",
  "feature_attribute": "",
  "num_classes": 2,
  "embedding_name": "gat_embedding",
  "random_seed": 42,
  "model_path": "gat_model.pt",
  "device": "cpu",
  "use_job": false
}
  • Only model_name is required. Every other field is optional, and the values above are the defaults.
  • task_type: "classification" (default), "regression" or "unsupervised". Any other string falls back to "classification". If target_attribute is empty, training is always unsupervised, whatever task_type says.
  • target_attribute: the attribute to predict. Classification uses its distinct values as classes, and num_classes is ignored. Regression parses the values as numbers.
  • feature_attribute: name of an entity vector used as input features. Entities without it get random features. All feature vectors must have the same dimension, otherwise the server returns 400 ("invalid attention_train parameters").
  • random_seed: seeds the random features, the train/validation split, the weight initialization and dropout, so the same request on the same graph reproduces a run.
  • Range limits: embedding_dimension 1 to 4096, epochs 0 to 100000, num_heads 1 to 64, at most 16 hidden_dims entries, each 1 to 4096, and train_split from 0 to 1. A value outside its range returns 400 with a message such as "train_split must be in [0, 1]", also when use_job is true.
  • model_name and a non-empty embedding_name must be 1 to 128 characters long, must not contain /, \ or control characters, and must not be . or ... Otherwise the server returns 400 ("invalid attention_train parameters"); with use_job, the job fails with InvalidParameter.
  • model_path is accepted but has no effect; the model is stored under model_name.
  • device (optional, default "cpu"): "cpu", "cuda", "cuda:N" or "auto" (case-insensitive). Any other value returns 400 ("device must be one of: cpu, cuda, cuda:N, auto"). If the requested CUDA device is not available, training runs on the CPU. If the GPU runs out of memory, training is retried once on the CPU. A job result also reports trained_on (for example "cpu" or "cuda:0").
  • Training fails if model_name already exists for this user (500, error_code "ModelNameExist"); remove the old model with /remove_model first.

Response

{
  "error_code": "Success",
  "embedding_name": "gat_embedding"
}

After supervised training, the response also contains train_loss and validation_loss (numbers). For classification it also has train_accuracy and validation_accuracy; for regression it has train_r2 and validation_r2.

Error Responses:

  • 400: Invalid field, invalid device, a value out of range, or "invalid attention_train parameters".
  • 404: Graph does not exist.
  • 500: ModelNameExist, or a training failure.

Example

Request:

POST /attention_train
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "gat_model",
  "epochs": 1,
  "embedding_dimension": 16,
  "hidden_dims": [16, 16],
  "task_type": "unsupervised",
  "embedding_name": "custom_gat",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.11 /attention_infer

Description

Runs GAT inference from a previously trained model on the current graph. For every task type, it writes embeddings (length = last entry of hidden_dims) to every node under the embedding_name saved with the model. Inference always runs on the CPU. A supervised model keeps the classes it was trained with; the graph's current labels are not read. Requires a LibTorch build (otherwise 400, "attention not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "use_job": false
}

Response

{
  "error_code": "Success",
  "model_name": "gat_model"
}

Error Responses:

  • 404: "graph does not exist".
  • 404: "model not found".

Example

Request:

POST /attention_infer
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "gat_model",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

6.12 /attention_predict

Description

Runs GAT prediction for every entity in the current graph and returns per-entity outputs as strings. Nothing is written to the graph. The format of a value depends on the model's task type:

  • classification: the predicted class label, for example "class_a". Labels are the ones seen at training time, even if the graph's labels have changed since;
  • regression: the predicted number with six decimals, for example "3.140000";
  • unsupervised: the embedding, serialized as "[v1,v2,...]", for example "[0.123457,-0.5,1e-05]".

By default, prediction keys are internal numeric entity IDs serialized as strings. With use_entity_ids: true they are the entity IDs instead. Requires a LibTorch build (otherwise 400, "attention not supported in this build").

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "graph_id": "string",
  "model_name": "string",
  "use_entity_ids": false,     // optional, default false
  "use_job": false
}

Response

{
  "error_code": "Success",
  "model_name": "gat_model",
  "predictions": {
    "123": "class_a",
    "456": "class_b"
  }
}

Error Responses:

  • 404: "graph does not exist".
  • 404: "model not found".

Example

Request:

POST /attention_predict
Content-Type: application/json

{
  "user_api_key": "api_key_123",
  "graph_id": "graph",
  "model_name": "gat_model",
  "use_job": true
}

Response when enqueued as a job (HTTP 202 Accepted):

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

7. Server Job API

To support long-running or resource-intensive operations without requiring clients to maintain a persistent connection, most API endpoints offer asynchronous job execution. When you enable this feature, your request will be processed in the background, and you can poll for its completion using the job API.

To submit an API call as a job, add these parameters to your request body:

{
  "use_job": true
}
  • use_job: Set to true to process the operation asynchronously. The field is optional. If it is missing, false, or not a JSON boolean (for example the string "true"), the request runs synchronously.

The index and node-embedding endpoints in this guide validate request fields before queuing the job, so a missing or invalid field still returns its error immediately. Some checks run only inside the job, so the job fails instead: for example an unsupported Vector Index dist_type, a query vector of the wrong dimension, or an invalid model_name or embedding_name for the node-embedding endpoints. When a request is submitted as a job, the server responds with HTTP 202 Accepted and the job identifier, a random UUID:

{
  "error_code": "Success",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

Jobs are kept in server memory and can only be read with the same user_api_key that submitted them. A finished job (Success or Failed) is deleted about one hour after it finishes, and after that it is reported as not found. Jobs do not survive a server restart.

Note: Not all endpoints support asynchronous job execution. The following endpoints do not support jobs and must be called synchronously; they ignore use_job:

  • All job management endpoints: /get_job_status, /get_job_result
  • Graph management: /create_graph, /remove_graph, /get_graphs, /init_graph, /offload_graph, /flush_graph
  • Model management: /remove_model
  • /get_neighbors and /get_clustering_cluster

Import pipelines (/import_entities, /import_relationships) accept use_job; when enabled, the server enqueues the import work and returns a job_id.


The following API endpoints are used to monitor and manage jobs:

7.1 /get_job_status

Description

Retrieves the current status of a job specified by job_id.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "job_id": "string"
}

Response

Success Response (200 OK):

{
  "error_code": "Success",
  "status": "Pending" | "InProgress" | "Success" | "Failed" | "Unknown"
}
  • Pending: queued, not started.
  • InProgress: running.
  • Success / Failed: finished. Failed also covers jobs whose operation returned an error (for example, the graph did not exist). Use /get_job_result to read the error.

Error Responses:

  • 403: The job belongs to another user ({"error_code": "InvalidUser", "error_message": "unauthorized"}).
  • 404: Job not found ({"error_code": "JobNotFound", "error_message": "job not found"}), including a finished job that has already been deleted. This is the same answer as /get_job_result.

Example

Request:

POST /get_job_status
Content-Type: application/json

{
  "user_api_key": "API_KEY",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

Response:

{
  "error_code": "Success",
  "status": "Success"
}

7.2 /get_job_result

Description

Retrieves the result of a finished job specified by job_id. If the job is still pending or running, the response says that the result is not yet available.

Method

  • POST

Request Body

{
  "user_api_key": "string",
  "job_id": "string"
}

Response

  • Success Response (200 OK): Returned for every finished job, including failed ones. The body holds the result fields of the original API call (format depends on the endpoint you invoked with use_job=true), plus error_code. For a failed job, error_code is the failure code (for example "GraphNotFound"), and error_message explains it. Check error_code, not the HTTP status.

  • Accepted Response (202 Accepted): Indicates that the job is pending or running and the result is not yet available.

  • Error Responses:

  • 403: The job belongs to another user.

  • 404: Job not found ({"error_code": "JobNotFound", "error_message": "job not found"}), including a finished job that has already been deleted.

Example

Request:

POST /get_job_result
Content-Type: application/json

{
  "user_api_key": "API_KEY",
  "job_id": "3f2b6c1e-8d4a-4b7e-9c2d-5a1f0e6b7c3d"
}

Response (when completed, HTTP 200):

{
  "error_code": "Success",
  "entity_ids": ["Alice", "Bob", "Charlie"]
}

Response (when failed, HTTP 200):

{
  "error_code": "GraphNotFound",
  "error_message": "graph does not exist"
}

Response (when still pending or running, HTTP 202):

{
  "error_code": "Success",
  "error_message": "job still running"
}

Appendix

The appendix contains several notes about how the Graph API works.

Filters

The VecML GraphDB REST API supports expressive, composable JSON predicates to filter entities (or relationships). Filters test attributes only, not vectors.

Overall Structure

A filter is a JSON object representing either:

  • A logical combinator (and, or, xor, not) whose value is one or more sub-predicates, or
  • A leaf operation that tests a single property.

A filter the server cannot parse (unknown operator, wrong value types, or a value that is not an object) is rejected with HTTP 400 and {"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}. Combinators may be nested at most 64 levels deep; a deeper filter is rejected the same way.

Example

{
  "and": [
    {
      "match_attribute": {
        "key": "status",
        "values": ["active"]
      }
    },
    {
      "less_than": {
        "key": "age",
        "value": 18
      }
    }
  ]
}

Logical Combinators

Operator Syntax Description
AND {"and":[<pred>,<pred>,…]} True if all sub-predicates are true.
OR {"or":[<pred>,<pred>,…]} True if any sub-predicate is true.
XOR {"xor":[<pred>,<pred>,…]} True if an odd number of sub-predicates are true (for two sub-predicates, exactly one).
NOT {"not":<pred>} True if the sub-predicate is false.

Leaf Operations

All attribute values are stored as strings. A leaf that tests a missing attribute evaluates to false.

Operation Syntax Description
match_attribute {"match_attribute":{"key":"<attr>","values":["v1","v2",…]}} <attr> equals any listed value (exact string comparison; values must be strings).
attribute_exists {"attribute_exists":"<attr>"} Entity has attribute <attr>.
attribute_is_integer {"attribute_is_integer":"<attr>"} <attr> starts with an integer. A leading integer is enough, so "3.5" also matches.
attribute_is_float {"attribute_is_float":"<attr>"} <attr> starts with a number. Integers match too.
less_than {"less_than":{"key":"<attr>","value":<num or string>}} <attr> < value. A JSON integer value compares <attr> as an integer, a JSON float compares it as a float, and a JSON string compares lexicographically. An integer value outside the 32-bit range makes the filter invalid. Values that cannot be parsed do not match.
true {"true":{}} Always true.
false {"false":{}} Always false.

vectors

JSON endpoints accept two vector encodings, each represented as an object with type and vector_data:

  • Dense float vectors – type: "Float32" – vector_data: an array of 32-bit floating-point values

  • Sparse float vectors – type: "SFloat32" – vector_data: an array of [index, value] pairs, where value is a 32-bit float. The vector's dimension is the largest index plus one.

Some endpoints also require or return a "name" attribute alongside the two fields above. When importing from CSV, a vector whose values are all integer literals is stored as an integer (Int32) vector, but JSON payloads must use the two types above. Any other type is rejected.

Examples

Dense float vector (with name):

{
  "name": "vector_location",
  "type": "Float32",
  "vector_data": [0.12, 0.83, 0.44]
}

Sparse float vector (with name):

{
  "name": "vector_word",
  "type": "SFloat32",
  "vector_data": [
    [3, 0.7],
    [42, 1.9]
  ]
}

Distance Function

dist_type (when creating a Vector Index) and similarity_measure (when searching a Fuzzy Attribute Index) accept the following strings. They are case-sensitive, and any other string is rejected with 400 ("field with invalid value: dist_type" or "field with invalid value: similarity_measure"). Smaller values mean closer matches.

  • Euclidean (default)
    Standard L₂‐norm (ℓ₂) distance:

$$ d_{\text{Euclidean}}(\mathbf x, \mathbf y) \;=\; \sqrt{\sum_{i}(x_i - y_i)^2} $$

  • Cosine
    Negative cosine similarity.

  • InnerProduct
    Negative inner product (−x·y). For normalized vectors, this equals the negative cosine similarity.

  • Hamming
    For binary‐encoded/sparse‐packed vectors, counts the number of differing bits.

  • WeightedJaccard / WeightedContainment
    Negative weighted Jaccard/containment similarity.

  • BM25
    BM25 relevance score, used by inverted (sparse) indices such as the Fuzzy Attribute Index.

  • Custom
    Reserved for custom distance functions (index-specific).

Note:

  1. Only a Vector Index uses dist_type, which is fixed when the index is created and is used for every search on the index, filtered or not. A Vector Index supports only Euclidean, InnerProduct, Cosine and WeightedJaccard; creating one with another dist_type fails with 400 ("wrong parameters for the type of index"). Only a Fuzzy Attribute Index uses similarity_measure at search time, and it scores with Euclidean, Cosine, InnerProduct and BM25. All other index types ignore these fields.
  2. If you do not explicitly pass dist_type or similarity_measure, the API defaults to Euclidean.
  3. In code, these are defined under enum class DistanceFunctionType { Euclidean, NegativeInnerProduct, NegativeCosineSimilarity, Custom, Hamming, NegativeWeightedJaccard, NegativeWeightedContainment, BM25 }. The API strings InnerProduct, Cosine, WeightedJaccard and WeightedContainment map to the Negative… members.

Index Types

The following index types are supported by the GraphInterface API. The index_type field must use these exact strings:

  • Attribute Index
    Finds all entities (or relationships) whose attribute value exactly equals the query term. A search returns every match; it ignores top_k, similarity_measure and the filter.

  • Fuzzy Attribute Index
    Performs approximate string matching on attribute values. Each value is turned into an n-gram sparse vector, and the closest entities (or relationships) to the query term are returned, scored with similarity_measure.

  • Vector Index
    An approximate nearest‐neighbor (HNSW) index over the dense vectors stored under the vector name, for example Float32 vectors. When creating a Vector Index, you supply:

  • dim – dimensionality of the vectors (optional; if it is omitted or 0, it is taken from the stored vectors)

  • dist_type – distance metric to use: Euclidean, InnerProduct, Cosine or WeightedJaccard (see Distance Function)

A search needs a dense Float32 query of the index's dimension. A filtered search is approximate too: the server scans the index exactly only when the approximate search finds fewer than top_k matches.

  • Integer Linear Index
    Indexes only the first component of each vector, read according to the stored vector's type: an Int32 (or UInt8) value is used as is, and a Float32 value is accepted only if it is a whole number within the 32-bit integer range. A search returns the items whose value is closest to the query's first component (absolute difference). This is useful for scalar values imported from CSV as integers. A JSON query uses a Float32 vector, whose first component is compared by value and must be a whole number within the 32-bit integer range (see /search_entity_index).

  • Float Linear Index
    Same as Integer Linear Index, but the first component is taken as a 32-bit float: any finite value of a Float32, Int32 or UInt8 vector is accepted, and any finite query value is accepted. Distances are the exact absolute difference, fractions included, so values closer than 1 are ranked by how close they are. Use it for Float32-typed vectors.

A vector that a linear index cannot take is refused with InvalidParameter: an empty vector, a NaN or infinite value, or, on an Integer Linear Index, a fractional or out-of-range value. A sparse or bit vector (such as SFloat32) is refused with InvalidVectorType. The check applies to every vector stored under a name that has a linear index: /set_entity_attributes, /set_relationship_attributes and their batch and import forms report the error for that item and do not store its vector or attributes. Creating a linear index when such a vector is already stored fails with 400 ("wrong parameters for the type of index"), and no index is left behind.