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
/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:
- Go to https://account.vecml.com/user-api-keys , sign up for a free VecML account.
- After registration, you can get an API key by clicking "Create New API Key".
- 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_keyis 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_messageis 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, andtrueare rejected, as are an integer too large for the field and a negative value for a field that cannot be negative (such astransaction_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_idin/create_graph, theattribute_nameof an index, vector names,model_name, andembedding_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 samegraph_idcheck, with the same400answer 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_indexand/get_all_types_relationship_index. The training and embedding endpoints reject a badmodel_nameorembedding_nameas 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_idcannot 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_idcannot be used as a directory name, checked as in/create_graphafter 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) includestransaction_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_idmissing, 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_iddoes 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), atype("Float32"or"SFloat32"), andvector_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.72is returned as2.7200000286102295).
Response
Success Response (200 OK):
{
"error_code": "Success"
}
Error Responses:
400: Missinguser_api_key,graph_id, orentity_id, orvectorsis not an array ("field is not a json array: vectors").400:attributesis not an object, or one of its values is not a string ({"error_code": "InvalidParameter", "error_message": "attributes are invalid"}).400(plain-text body): Avectorselement is not an object (missing vector field).400: Avectorselement has noname, or itsnameis not a string ("invalid vector: \"name\" must be present and a string").400: A vector'stypeis missing or unsupported, or itsvector_datadoes not match the type ("failed to parse vector").Float32values must be finite numbers that fit a 32-bit float; eachSFloat32entry must be an[index, value]pair with a non-negative integerindexand such avalue.400: A vectornamecannot 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 emptyFloat32vector_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_codeInvalidParameterfor an empty vector, or, on an Integer Linear Index, a first value that is fractional or outside the 32-bit integer range;InvalidVectorTypefor anSFloat32vector. Theerror_messageis"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_namesorvector_namesis 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 ofattribute_namesdoes 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_namesmissing 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_namesmissing 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 orfalse, 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 likematch_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 aless_thanvaluethat 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 orfalse, 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_idordest_entity_iddoes 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 orfalse, 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_idordest_entity_idis not a known entity ID ("error_message": "entity does not exist").404:relationship_idis unknown, or no edgesrc_entity_id→dest_entity_idwith thisrelationship_idexists ("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), atype("Float32"or"SFloat32"), andvector_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.72is returned as2.7200000286102295).
Response
Success Response (200 OK):
{
"error_code": "Success"
}
Error Responses:
400: Missinguser_api_key,graph_id, orrelationship_id, orvectorsis not an array ("field is not a json array: vectors").400:attributesis not an object, or one of its values is not a string ({"error_code": "InvalidParameter", "error_message": "attributes are invalid"}).400(plain-text body): Avectorselement is not an object (missing vector field).400: Avectorselement has noname, or itsnameis not a string ("invalid vector: \"name\" must be present and a string").400: A vector'stypeis missing or unsupported, or itsvector_datadoes not match the type ("failed to parse vector").Float32values must be finite numbers that fit a 32-bit float; eachSFloat32entry must be an[index, value]pair with a non-negative integerindexand such avalue.400: A vectornamecannot 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 emptyFloat32vector_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_codeInvalidParameterfor an empty vector, or, on an Integer Linear Index, a first value that is fractional or outside the 32-bit integer range;InvalidVectorTypefor anSFloat32vector. Theerror_messageis"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_namesorvector_namesis 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 ofattribute_namesdoes 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_namesmissing 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_namesmissing 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 orfalse, 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 likematch_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 aless_thanvaluethat 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 returns400(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
dimis omitted or0, the server takes the dimension from the vectors already stored underattribute_name. See appendix for more details about dist_type. An unrecognizeddist_typestring is rejected with400("field with invalid value: dist_type"). A Vector Index supports onlyEuclidean,InnerProduct,CosineandWeightedJaccard; any other recognizeddist_typereturns400("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", ifindex_typeis not one of the five supported strings.400:"wrong parameters for the type of index", for example a Vector Index with nodimwhen no vectors are stored underattribute_nameto take the dimension from, a Vector Index with an unsupporteddist_type, or an Integer or Float Linear Index when a vector already stored underattribute_namehas a first value the index cannot take (see Index Types). No index is left behind.400: Invalidattribute_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_nameis 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: Invalidattribute_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_typestring is not an error; it returns"exists": false.
Response
Success Response (200 OK):
{
"error_code": "Success",
"exists": true|false
}
Error Responses:
400: Invalidgraph_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: Invalidgraph_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: Invalidgraph_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
Float32query whose dimension equals the index dimension; anSFloat32query or a different dimension returns400("wrong parameters for the type of index"). The two linear indices compare only the first component. - Sending
attribute_valueto a vector-based index, orvectorto an attribute-based index, returns400("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 ignorestop_kand returns every exact match. - similarity_measure: Only a Fuzzy Attribute Index uses this field, and it scores with
Euclidean,Cosine,InnerProductorBM25. A Vector Index always ranks by thedist_typeit 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 returns400. - 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 thantop_kresults 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 thantop_kmatches, so filtered results are approximate, like unfiltered ones. A filter the server cannot parse returns400with{"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}. - JSON vector payloads must use
Float32orSFloat32; other types, or a malformed vector object, are rejected with400and a plain-text bodyfield 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 emptyvector_data, anSFloat32query, or (for an Integer Linear Index) a fractional or out-of-range value returns400("wrong parameters for the type of index"). - Searching a Vector Index or a linear index that holds no vectors returns
200with 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 invalidtop_kor 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 returns400(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
dimis omitted or0, the server takes the dimension from the vectors already stored underattribute_name. See appendix for more details about dist_type. An unrecognizeddist_typestring is rejected with400("field with invalid value: dist_type"). A Vector Index supports onlyEuclidean,InnerProduct,CosineandWeightedJaccard; any other recognizeddist_typereturns400("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", ifindex_typeis not one of the five supported strings.400:"wrong parameters for the type of index", for example a Vector Index with nodimwhen no vectors are stored underattribute_nameto take the dimension from, a Vector Index with an unsupporteddist_type, or an Integer or Float Linear Index when a vector already stored underattribute_namehas a first value the index cannot take (see Index Types). No index is left behind.400: Invalidattribute_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_nameis 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: Invalidattribute_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_typestring is not an error; it returns"exists": false.
Response
Success Response (200 OK):
{
"error_code": "Success",
"exists": true|false
}
Error Responses:
400: Invalidgraph_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: Invalidgraph_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: Invalidgraph_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
Float32query whose dimension equals the index dimension; anSFloat32query or a different dimension returns400("wrong parameters for the type of index"). The two linear indices compare only the first component. - Sending
attribute_valueto a vector-based index, orvectorto an attribute-based index, returns400("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 ignorestop_kand returns every exact match. - similarity_measure: Only a Fuzzy Attribute Index uses this field, and it scores with
Euclidean,Cosine,InnerProductorBM25. A Vector Index always ranks by thedist_typeit 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 returns400. - 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 thantop_kresults 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 thantop_kmatches, so filtered results are approximate, like unfiltered ones. A filter the server cannot parse returns400with{"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}. - JSON vector payloads must use
Float32orSFloat32; other types, or a malformed vector object, are rejected with400and a plain-text bodyfield 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 emptyvector_data, anSFloat32query, or (for an Integer Linear Index) a fractional or out-of-range value returns400("wrong parameters for the type of index"). - Searching a Vector Index or a linear index that holds no vectors returns
200with 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 invalidtop_kor 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, defaultfalse): only the JSON booleantruesubmits a job. The response is then202 Acceptedwith{"error_code": "Success", "job_id": "..."}, and the payload shown under Response is read later with/get_job_result. A missing or non-booleanuse_jobruns 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
400with 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,trueor a value out of range returns400(field with invalid value: <field>). Number fields must be finite, and a 32-bit float field (such asdelta) also rejects values beyond the float range. An integer count that is negative, or0where a positive value is required, returns400with the plain-text bodyfield with invalid value: <field>. - An invalid
user_api_keyreturns403(InvalidUser,unauthorized). An unknowngraph_idreturns404with"error_message": "graph does not exist". An unknown node ID returns404with"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 returns400with{"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}. This includes a filter nested more than 64 levels deep and aless_thaninteger outside the 32-bitintrange. The check happens before a job is queued, so it also applies withuse_job./find_k_hopapplies 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
nancounts as non-numeric. - Errors not listed for an endpoint return
500witherror_messageset 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 returns400with"error_message": "invalid request: <parser message>". - Distances, weights and scores are returned as 32-bit floats and serialized as JSON doubles, so
0.19appears as0.1899999976158142. Values such as2.0or0.25appear 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), or3(both). Defaults to3when omitted. The value is used as a bit mask (truncated to 8 bits; bit1= outbound, bit2= inbound), so0, 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_idmissing, ortypenot 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), or3(bidirectional). Used as the same bit mask as in/get_neighbors;0returns empty results. - k (required, integer ≥ 1): Maximum hop count.
0or a negative value returns400with the plain-text bodyfield 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
kfilters:entity_filters[i]must be satisfied by every entity reached at hopi + 1, andrelationship_filters[i]by every relationship traversed at hopi + 1. An array of any other length returns400with"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 inentity_ids, giving the relationship through which it was first reached. The pair is[from, to]in traversal direction (fromwas 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 notk(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 as0; a missing or non-numeric value as1. - is_undirected (optional, default
false): Whenfalse, only outbound relationships are followed; whentrue, relationships are followed in both directions. - return_paths (optional, default
false): Whentrue, 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: withtarget_node_ids, one[node_id, distance]entry per target in request order, with-1.0for an unreachable target. Without targets, one entry for every reached node, including the sources (distance0.0); the order is breadth-first discovery order whenweight_attr_nameis omitted and unspecified otherwise.reachable: one boolean perdistancesentry, in the same order;falsemarks an unreachable target. Without targets every entry istrue, since only reached nodes are listed. Use it rather than testing for-1.0.paths: omitted unlessreturn_pathsistrue. There is one path per target, in target order, sopaths[i]belongs todistances[i]; an unreachable target gets[]. Each path lists its edges from the source to the target, as in/astar,/spfaand/delta_stepping. Each edge is[[from, to], relationship_id]in traversal direction. A target that is itself a source has an empty path. Withouttarget_node_ids,pathsis[].
Error Responses:
400:source_node_idsmissing,source_node_ids/target_node_idsnot 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: Emptysource_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
Float32entity vector holding the node's coordinates. A node without this vector gets heuristic0, and if any target lacks it the heuristic is0for 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 as1. - is_undirected (optional, default
false): Whenfalse, only outbound relationships are followed; whentrue, both directions. - return_paths (optional, default
false): Whentrue, 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.0for an unreachable target.reachable: one boolean perdistancesentry,falsefor an unreachable target.paths(only whenreturn_pathsistrue): 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_idsnot 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: Emptysource_node_idsortarget_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): Whentrue, 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.0for an unreachable target. With negative weights-1.0can also be a real distance, so checkreachableinstead. Withtarget_node_ids: [], one entry for every reached node, including the source (0.0), in unspecified order.reachable: one boolean perdistancesentry, in the same order;falseonly for an unreachable target. A node reachable from a negative cycle counts as reachable. Withtarget_node_ids: []every entry istrue.affected_by_negative_cycle: one boolean perdistancesentry,truefor a node reachable from a negative cycle (whose distance is reported as0.0, see below). Allfalsewhen no negative cycle is found.paths(only whenreturn_pathsistrue): one[has_negative_cycle, edges]pair per target in request order, whereedgesis an array of[["src", "dst"], "rel_id"]listed from the source to the target. An unreachable target gives[false, []]. Withtarget_node_ids: [],pathsis[].- 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 notreturn_pathsis set; withtarget_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. Withreturn_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'sdstis the next edge'ssrc).
Additional failure codes:
400:target_node_idsmissing or not an array of strings,node_filters/edge_filtersnot 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<= 0returns500(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 as1. - is_undirected (optional, default
false): Whenfalse, only outbound relationships are followed; whentrue, both directions. - node_filters / edge_filters (optional): JSON predicate arrays (see Filters).
- use_job (optional): Run asynchronously as a job.
Response
distances: whenpath_node_idsis non-empty, one[entity_id, distance]entry per path node in request order,-1.0if unreachable. Otherwise, one entry for every reached node, including the source (0.0), in unspecified order.reachable: one boolean perdistancesentry,falsefor an unreachable path node. Withoutpath_node_idsevery entry istrue.paths: only present whenpath_node_idsis 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_idsnot an array of strings,deltanot 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],uwas already in the tree andvis the node the edge added, which may be the reverse of the stored relationship direction.total_weight: sum of the weights ofmst_edges(0.0for an empty result).
Additional failure codes:
400:start_node_idsmissing 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 as1. - apply_rerouting (optional, default
false): Whentrue, 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 recomputetotal_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 oftree_edges.
Additional failure codes:
400:source_node_idorterminal_node_idsmissing, orterminal_node_idsnot 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: Emptyterminal_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, orsource_node_idequal tosink_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 Link Prediction & Neighborhood Similarity
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_filtersapply to the neighbor entities (not tonode_ids);edge_filtersto 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_idsmissing, 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 adds1 / ln(deg(z)), and neighbors withdeg(z) <= 1add nothing. When false, each adds1 / 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:uorvmissing, 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), oruorvdoes 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:uorvmissing, 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), oruorvdoes 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 failnode_filtersare 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_idsmissing 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 failnode_filtersare 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_idsmissing 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 returns500(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 as1. - return_paths (optional, default
false): Whentrue, 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.0if unreachable. With negative weights-1.0can also be a real longest distance, so checkreachableinstead. Without targets, one entry for every reached node, including the sources, in unspecified order.reachable: one boolean perdistancesentry,falsefor an unreachable target. Without targets every entry istrue.paths(only whenreturn_pathsistrue): 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,pathsis[].
Additional failure codes:
400:source_node_idsmissing,source_node_ids/target_node_idsnot 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"}). Withuse_job, the job fails with the sameerror_message.404: Graph not found (graph does not exist), or a source or target does not exist (entity does not exist).500: Emptysource_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.0runs one iteration. Iteration stops early once the L1 change between iterations is below1e-10. - edge_weight_attr (optional): Relationship attribute for weighted PageRank. A negative value is treated as
0; a missing or non-numeric value as1. 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 as1; if all weights are0, 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), all0if every score is equal),max(x / max),mean(x / mean),log(ln(1 + x)), orstdscore/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_filtersare 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 negativemax_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 (
variableorfunction) marks variables and factors. - K (required, integer from 1 to 1000): Number of discrete states per variable.
0, a negative value or a value above1000returns400with the plain-text bodyfield with invalid value: K, also withuse_job. WithK=1every variable is assigned0without 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 belowtol. - 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, orK/max_iterationsout 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 (
variableorfunction) 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-objectboundsis ignored. An ID that is not an entity returns404(entity does not exist). A variable without bounds samples from[0, 1), and ifmax <= minthe 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 belowtol. - 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_namemissing, or a numeric parameter of the wrong type or out of range (plain text for0or negative counts).404: Graph not found (graph does not exist), or aboundskey 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, orK-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;
0returns400invalid clustering parameters).0leaves 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<= 0are ignored. Omit it to give every relationship weight1. - objective_function (optional, default
modularity):modularityfor Louvain;modularityorcpm(Constant Potts Model) for Leiden. Any other value returns400:clustering algorithm not supportedfor Louvain,invalid clustering parametersfor Leiden. - vector_name: Name of the dense entity vector used by K-Means.
- k (integer ≥ 1): Number of clusters for K-Means.
0returns400with the plain-text bodyfield with invalid value: k. - dist_type (optional, default
Euclidean): Distance metric for K-Means, using a name from Distance Function. OnlyEuclideanis supported: any other valid name returns400clustering algorithm not supported, and an unknown name returns400invalid dist_type. - use_job (optional): Run asynchronously as a job.
The parameter set is chosen from the fields present, in this order:
- K-Means set, if
vector_nameorkis present: requiresvector_name,k, andmax_iter;dist_typeis optional. Algorithms:K-Means,K-Means++. - Community set, if
resolution,weight_attribute, orobjective_functionis present: requiresmax_iterandresolution. Algorithms:Louvain,Leiden. - Label Propagation set, if only
max_iteris present. Algorithm:Label Propagation. - 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
modularityandcpmobjectives; withcpm, 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_iterrounds or when no label changes. Entities without neighbors keep their own cluster. - K-Means / K-Means++: clusters only the entities that have a dense
Float32vector namedvector_name; entities without it are not assigned to any cluster. All these vectors must have the same dimension.K-Meanspickskrandom entities as initial centroids;K-Means++uses k-means++ seeding.kmust not exceed the number of entities that have the vector. Iteration stops aftermax_iterrounds 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 Leidenobjective_function, or invalid K-Meansk/max_iter);clustering algorithm not supported(a Louvainobjective_functionother thanmodularity, or a non-EuclideanK-Meansdist_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 allFloat32with 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 returns400with the plain-text bodyfield 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, orcluster_idis 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 insideentity_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 returns403, not200.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
200with{"error_code": "Success"}when the graph exists, and404(GraphNotFound) when it does not. If the same ID appears twice, the second occurrence fails withEntityExist.
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: reasonentity already exists.500, other codes: reasoninternal 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
200with{"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: reasongraph does not exist.409: reasonentity not found.500: reasoninternal 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
200with{"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
400and{"error_code": "InvalidParameter", "error_message": "attributes are invalid"}. - vectors (array, optional): Each element needs
name(string) andtype:"Float32"withvector_dataas an array of finite numbers, or"SFloat32"withvector_dataas an array of[index, value]pairs, whereindexis a non-negative integer andvaluea finite number. A bad element rejects the whole request with400before 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: reasongraph does not exist.404,EntityNotFound: reasonentity does not exist.400,InvalidParameter/InvalidVectorType/InvalidData: reasona 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: reasoninternal 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
200with{"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
AttributeNotFoundand 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: reasongraph does not exist.404,EntityNotFound: reasonentity does not exist.404,AttributeNotFound: reasonattribute(s) does not exist.500, other codes: reasoninternal 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
200with{"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", ...]
},
...
]
}
resultshas one entry per requested item, in request order.valuesis present only when the item'serror_codeisSuccess, and follows the order ofattribute_names. If any requested attribute is missing, the item'serror_codeisAttributeNotFoundand no values are returned for it.- If the graph does not exist the request fails with
404and{"error_code": "GraphNotFound", "error_message": "graph does not exist"}. - With
"use_job": true,/get_job_resultreturns the sameresults.
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
200with{"error_code": "Success", "results": []}.
Response
Success Response (200 OK):
{
"error_code": "Success",
"results": [
{
"entity_id": "string",
"error_code": "string",
"attributes": {
"string": "string",
...
}
},
...
]
}
resultshas one entry per requested item, in request order.attributesis present only when the item'serror_codeisSuccess(an entity without attributes gives{}).- If the graph does not exist the request fails with
404and{"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
200with{"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": [ ... ]
},
...
]
},
...
]
}
resultshas one entry per requested item, in request order.vectorsis present only when the item'serror_codeisSuccess, and follows the order ofvector_names.- Only
SuccessandEntityNotFoundare reported per item. Any other per-item error fails the whole request with500and"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
500and{"error_code": "InvalidData", "error_message": "error in parsing vectors"}. - If the graph does not exist the request fails with
404and{"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
200with{"error_code": "Success", "results": []}.
Response
Success Response (200 OK):
{
"error_code": "Success",
"results": [
{
"entity_id": "string",
"error_code": "string",
"names": ["string", ...]
},
...
]
}
resultshas one entry per requested item, in request order.namesis present only when the item'serror_codeisSuccess([]for an entity without vectors); the order of the names is not guaranteed.- Only
SuccessandEntityNotFoundare reported per item. Any other per-item error fails the whole request with500and"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
404and{"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
200with{"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"
}
]
}
resultshas one entry per requested item, in request order.vectorsis present only when the item'serror_codeisSuccess([]for an entity without vectors).- Only
SuccessandEntityNotFoundare reported per item. Any other per-item error fails the whole request with500and"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
404and{"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
200with{"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: reasongraph does not exist.404,EntityNotFound: reasonentity does not exist.500, other codes: reasoninternal 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
200with{"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: reasongraph does not exist.404,EntityNotFound: reasonentity does not exist.404,RelationshipNotFound: reasonrelationship does not exist.500, other codes: reasoninternal 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, withrelationshipsandrelationship_idin place ofentitiesandentity_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: reasongraph does not exist.404,RelationshipNotFound: reasonrelationship does not exist.400,InvalidParameter/InvalidVectorType/InvalidData: reasona 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: reasoninternal 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_namesandvector_namesare optional, a missing attribute fails the item withAttributeNotFound, a missing vector name is ignored, and an emptyrelationshipsarray returns200with{"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: reasongraph does not exist.404,RelationshipNotFound: reasonrelationship does not exist.404,AttributeNotFound: reasonattribute(s) does not exist.500, other codes: reasoninternal 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
200with{"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", ...]
},
...
]
}
resultshas one entry per requested item, in request order.valuesis present only when the item'serror_codeisSuccess, in the order ofattribute_names; if any requested attribute is missing the item'serror_codeisAttributeNotFoundand no values are returned.- If the graph does not exist the request fails with
404and{"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
200with{"error_code": "Success", "results": []}.
Response
Success Response (200 OK):
{
"error_code": "Success",
"results": [
{
"relationship_id":"string",
"error_code": "string",
"attributes": {
"string": "string",
...
}
},
...
]
}
resultshas one entry per requested item, in request order.attributesis present only when the item'serror_codeisSuccess({}for a relationship without attributes).- If the graph does not exist the request fails with
404and{"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
200with{"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": [ ... ]
},
...
]
},
...
]
}
resultshas one entry per requested item, in request order.vectorsis present only when the item'serror_codeisSuccess, in the order ofvector_names.- Only
SuccessandRelationshipNotFoundare reported per item. Any other per-item error fails the whole request with500and"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
500and{"error_code": "InvalidData", "error_message": "error in parsing vectors"}. - If the graph does not exist the request fails with
404and{"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
200with{"error_code": "Success", "results": []}.
Response
Success Response (200 OK):
{
"error_code": "Success",
"results": [
{
"relationship_id": "string",
"error_code": "string",
"names": ["string", ...]
},
...
]
}
resultshas one entry per requested item, in request order.namesis present only when the item'serror_codeisSuccess([]for a relationship without vectors); the order of the names is not guaranteed.- Only
SuccessandRelationshipNotFoundare reported per item. Any other per-item error fails the whole request with500and"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
404and{"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
200with{"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"
}
]
}
resultshas one entry per requested item, in request order.vectorsis present only when the item'serror_codeisSuccess([]for a relationship without vectors).- Only
SuccessandRelationshipNotFoundare reported per item. Any other per-item error fails the whole request with500and"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
404and{"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
200with{"error_code": "Success", "results": []}. For vector indices supply the vector object undervector; for attribute indices supplyattribute_value(a string). - attribute_name, index_type (strings, required):
index_typeis one of"Vector Index","Attribute Index","Fuzzy Attribute Index","Integer Linear Index","Float Linear Index"; another value gives the queryUnknownIndexType. - top_k (integer from 1 to 2147483647, optional, default
5), similarity_measure (string, optional, default"Euclidean"; one ofEuclidean,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
resultsarray aligns withbatch_queriesorder. Each entry echoes the query metadata and includes the per-queryerror_code(for exampleIndexNotFound,UnknownIndexType,InvalidParameter);entity_idsis[]for a query that failed. Each query behaves like the same query sent to/search_entity_index: for example, a query on aVector Indexwhose vector is not denseFloat32getsInvalidParameter, and a query on an emptyVector IndexgetsSuccesswith[]. - With
"use_job": true,/get_job_resultreturns the sameresults.
Error Responses:
400: A query omitted bothattribute_valueand vector ("must contain either attribute value or vector") or provided both ("can not contain both attribute value and vector"); unsupportedsimilarity_measure("field with invalid value: similarity_measure"); atop_kthat is not an integer from 1 to 2147483647 ("field with invalid value: top_k (must be an integer from 1 to 2147483647)"); missingattribute_name/index_type. These bodies are JSON.400, plain-text bodyfield with invalid value: vector: thevectorobject could not be parsed.400,{"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}:entity_filtercould not be parsed, or nests more than 64 levels ofand/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 returns500with{"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, withrelationship_filterapplying 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 conflictingattribute_value/vectorin a query, or another invalid query field, as for/batch_search_entity_index.400,{"error_code": "InvalidParameter", "error_message": "invalid field: filter (<reason>)"}:relationship_filtercould not be parsed.404or500when 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.
urlis used when present. The graph must exist: a missing graph returns404before anything is read or downloaded. The file is read before the job is queued, so download and file errors are returned directly even withuse_job. http://orhttps://: 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 with400. Downloads larger than 512 MiB (536870912 bytes) are rejected with413.file://<path>: a file in the graph's.filesdirectory 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 with400. An absolute path such asfile:///data/x.csvis 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>"). Ifheadersis 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-separated0/1flags. - 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.,eorEis stored as an integer vector (Int32, orSInt32when 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 ininvalid_rows. - JSON format:
file_datamust be a JSON object keyed byentity_id, each value an object with optional"attributes"(string map) and"vectors"(array of vector objects withname,type,vector_data). Entities are processed in key-sorted order. - use_job (optional): When
true, return ajob_idand 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_rowsare 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 (EntityExistincreate_ecs,Successinset_ecs). CSV rows with nothing to set (only the ID column) getEmptyParameter. With CSV, a row whose create fails with any code other thanEntityExistis not written, and itsset_ecsrepeats the create code. With JSON the set is attempted whatever the create result; entries with nothing to set getSuccess. A JSON entry with an unknown key or a non-string attribute value getsParseErrorin both lists, and one whose vectors cannot be parsed or have an invalid name getsInvalidParameterin 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: Missingformat, or neitherurlnorfile_data("missing field: file_data").400,{"error_code": "InvalidParameter", "error_message": "invalid graph_id: <reason>"}:graph_idbreaks the/create_graphnaming 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 thanhttp://,https://,file://("Invalid url"); anhttp(s)URL that reaches a non-public address ("Invalid url: imports may only download from public addresses"); afile://path that is empty, absolute, contains..or a control character, or resolves outside the graph's.filesdirectory ("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.
urlis handled as for/import_entities:http://orhttps://from a public address (at most 512 MiB), orfile://<relative path>inside the graph's.filesdirectory. A missing graph returns404before anything is read or downloaded. For CSV, omitheaders/is_vectorto 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 ininvalid_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
headersis 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 as0/1flags. - JSON format: Provide an array (or an object with a
relationshipsarray) of objects each containingsrc_entity_id,relationship_id,dest_entity_id, optional"attributes"(string map), and optional"vectors"(vector objects). - use_job (optional): When
true, return ajob_idand 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_idappears 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 whoserelationship_idalready exists creates its edge withSuccessand its attributes are updated. CSV rows with nothing to set getEmptyParameter. With CSV, a row whose create fails with any other code (for exampleEntityNotFoundwhen the source or destination entity is missing) is not written, and itsset_ecsrepeats the create code. With JSON the set is attempted whatever the create result; entries with nothing to set getSuccess. 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 getsParseErrorin 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: Missingformat, or neitherurlnorfile_data; unsupported URI scheme ("Invalid url"), a non-publichttp(s)address, or afile://path outside the graph's.filesdirectory (InvalidParameter, messages as for/import_entities); file cannot be read (InvalidFile).400,{"error_code": "InvalidParameter", "error_message": "invalid graph_id: <reason>"}:graph_idbreaks the/create_graphnaming 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 whenuse_jobistrue): 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 arelationshipsarray ("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: Invalidmodel_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_weightsandembedding_nameare required (the values above are examples).embedding_dimmust be an integer from 1 to 4096,iteration_weightsmust be a non-empty array of numbers, andnormalization_strengthmust be between -1 and 1. Otherwise the server returns400("invalid fastrp parameters"), also whenuse_jobistrue. An invalidembedding_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_dimandembedding_nameare required (the values above are examples).iterationsmust be from 1 to 1000,embedding_densityandembedding_dimfrom 1 to 4096,output_dimandinitial_densityat most 4096, andneighbor_influencemust be ≥ 0. Otherwise the server returns400("invalid hashgnn parameters"), also whenuse_jobistrue. An invalidembedding_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_nameis 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_dimensionrandom features are used. - projected_feature_dimension: width of the hidden layers, that is, of every layer except the last.
0(default) meansembedding_dimension. It does not need to match the width offeature_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 returns400("aggregator must be one of: mean, pool, lstm"). - activation_function:
"relu"(default),"sigmoid","tanh"or"none". Any other string returns400("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. Whenfalse, the node's own features and the aggregated neighbour features go through separate weights. use_residual (defaulttrue) 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_sizessets 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_influenceandsearch_depthare accepted but currently have no effect.- Range limits:
embedding_dimension1 to 4096,projected_feature_dimension0 to 4096,epochs0 to 100000,negative_sample_weight0 to 100, and 1 to 10sample_sizesentries, each 1 to 1000. A value outside its range returns400with a message such as"embedding_dimension must be in [1, 4096]", also whenuse_jobistrue. model_nameand a non-emptyembedding_namemust be 1 to 128 characters long, must not contain/,\or control characters, and must not be.or... Otherwise the server returns400("invalid sage_train parameters"); withuse_job, the job fails withInvalidParameter.- device (optional, default
"cpu"):"cpu","cuda","cuda:N"or"auto"(case-insensitive). Any other value returns400("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 reportstrained_on(for example"cpu"or"cuda:0"). - Training fails if
model_namealready exists for this user (500,error_code"ModelNameExist"); remove the old model with/remove_modelfirst.
Response
{
"error_code": "Success",
"embedding_name": "sage_embedding"
}
Error Responses:
400: Invalid field type, invaliddevice, unknownaggregatororactivation_function, a value out of range, or"invalid sage_train parameters".404: Graph does not exist.500:ModelNameExist, or a training failure such asTrainFailed.
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_nameis 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_dimensionmust be > 0, otherwise the server returns400("projected_feature_dimension required with feature_properties").projected_feature_dimension> 0 adds a hidden layer of that width.activation_functionanddropout_rateonly affect that hidden layer. - activation_function:
"relu"(default),"sigmoid","tanh"or"none". Any other string falls back to"relu". - num_threads:
0keeps 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_dimension1 to 4096,projected_feature_dimension0 to 4096,epochs0 to 100000,num_classes1 to 4096, andnum_threads0 to the number of CPU cores. A value outside its range returns400with a message such as"num_threads must be in [0, 8]", also whenuse_jobistrue. model_nameand a non-emptyembedding_namemust be 1 to 128 characters long, must not contain/,\or control characters, and must not be.or... Otherwise the server returns400("invalid gcn_train parameters"); withuse_job, the job fails withInvalidParameter.- 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 returns400("invalid gcn_train parameters"). If no entity has the label, training fails with500(InvalidData).batch_sizeonly limits how many labelled nodes are sampled for the supervised loss. iterations,tolerance,max_iterationsandis_multi_labelare accepted but currently have no effect.- device (optional, default
"cpu"):"cpu","cuda","cuda:N"or"auto"(case-insensitive). Any other value returns400("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 reportstrained_on(for example"cpu"or"cuda:0"). - Training fails if
model_namealready exists for this user (500,error_code"ModelNameExist"); remove the old model with/remove_modelfirst.
Response
{
"error_code": "Success",
"embedding_name": "gcn_embedding"
}
Error Responses:
400: Invalid field, invaliddevice, 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 withuse_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_nameis 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". Iftarget_attributeis empty, training is always unsupervised, whatevertask_typesays. - target_attribute: the attribute to predict. Classification uses its distinct values as classes, and
num_classesis 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_dimension1 to 4096,epochs0 to 100000,num_heads1 to 64, at most 16hidden_dimsentries, each 1 to 4096, andtrain_splitfrom 0 to 1. A value outside its range returns400with a message such as"train_split must be in [0, 1]", also whenuse_jobistrue. model_nameand a non-emptyembedding_namemust be 1 to 128 characters long, must not contain/,\or control characters, and must not be.or... Otherwise the server returns400("invalid attention_train parameters"); withuse_job, the job fails withInvalidParameter.model_pathis accepted but has no effect; the model is stored undermodel_name.- device (optional, default
"cpu"):"cpu","cuda","cuda:N"or"auto"(case-insensitive). Any other value returns400("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 reportstrained_on(for example"cpu"or"cuda:0"). - Training fails if
model_namealready exists for this user (500,error_code"ModelNameExist"); remove the old model with/remove_modelfirst.
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, invaliddevice, 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 totrueto 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_neighborsand/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.Failedalso covers jobs whose operation returned an error (for example, the graph did not exist). Use/get_job_resultto 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 withuse_job=true), pluserror_code. For a failed job,error_codeis the failure code (for example"GraphNotFound"), anderror_messageexplains it. Checkerror_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, wherevalueis 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:
- 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 onlyEuclidean,InnerProduct,CosineandWeightedJaccard; creating one with anotherdist_typefails with400("wrong parameters for the type of index"). Only a Fuzzy Attribute Index usessimilarity_measureat search time, and it scores withEuclidean,Cosine,InnerProductandBM25. All other index types ignore these fields.- If you do not explicitly pass
dist_typeorsimilarity_measure, the API defaults toEuclidean.- In code, these are defined under
enum class DistanceFunctionType { Euclidean, NegativeInnerProduct, NegativeCosineSimilarity, Custom, Hamming, NegativeWeightedJaccard, NegativeWeightedContainment, BM25 }. The API stringsInnerProduct,Cosine,WeightedJaccardandWeightedContainmentmap to theNegative…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 ignorestop_k,similarity_measureand 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 withsimilarity_measure. -
Vector Index
An approximate nearest‐neighbor (HNSW) index over the dense vectors stored under the vector name, for exampleFloat32vectors. When creating a Vector Index, you supply: -
dim– dimensionality of the vectors (optional; if it is omitted or0, it is taken from the stored vectors) dist_type– distance metric to use:Euclidean,InnerProduct,CosineorWeightedJaccard(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: anInt32(orUInt8) value is used as is, and aFloat32value 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 aFloat32vector, 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 aFloat32,Int32orUInt8vector is accepted, and any finite query value is accepted. Distances are the exact absolute difference, fractions included, so values closer than1are ranked by how close they are. Use it forFloat32-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.