openapi: 3.1.0 info: title: Samyama Graph Database API version: 1.7.0 description: | HTTP API for the Samyama high-performance distributed graph database. Supports OpenCypher queries, graph status, and CRUD operations. license: name: Apache-2.0 url: https://www.apache.org/licenses/LICENSE-2.0 servers: - url: http://localhost:8080 description: Local development server paths: /api/query: post: operationId: executeQuery summary: Execute a Cypher query description: | Execute an OpenCypher query against the graph database. Supports both read (MATCH) and write (CREATE, SET, DELETE, MERGE) queries. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/QueryRequest' examples: matchAll: summary: Match all Person nodes value: query: "MATCH (n:Person) RETURN n" matchWithFilter: summary: Match with WHERE filter value: query: "MATCH (n:Person) WHERE n.age > 25 RETURN n.name, n.age" createNode: summary: Create a new node value: query: 'CREATE (n:Person {name: "Alice", age: 30})' traversal: summary: Traverse relationships value: query: "MATCH (a:Person)-[:KNOWS]->(b:Person) RETURN a.name, b.name" responses: '200': description: Query executed successfully content: application/json: schema: $ref: '#/components/schemas/QueryResponse' '400': description: Query error (parse error, execution error) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/schema: get: operationId: getSchema summary: Get graph schema description: | Returns the full schema of the graph database including node types with property keys/types, edge types with source/target labels, indexes, constraints, and basic statistics. responses: '200': description: Graph schema content: application/json: schema: $ref: '#/components/schemas/SchemaResponse' /api/import/csv: post: operationId: importCsv summary: Import nodes from CSV description: | Upload a CSV file to create nodes. The first row is treated as column headers (property names). Each subsequent row creates one node with the specified label. Property types are auto-detected (integer → float → boolean → string). requestBody: required: true content: multipart/form-data: schema: type: object required: - file - label properties: file: type: string description: CSV file content label: type: string description: Node label to assign to all created nodes id_column: type: string description: Column to use as node ID mapping (optional) delimiter: type: string description: "CSV delimiter character (default: ',')" graph: type: string description: "Target graph/tenant name (default: 'default')" responses: '200': description: Import successful content: application/json: schema: $ref: '#/components/schemas/CsvImportResponse' '400': description: Import error (missing fields, parse error) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/import/json: post: operationId: importJson summary: Import nodes from JSON description: | Create nodes from an array of JSON objects. Each object becomes one node with the specified label. Object keys become property names; values must be string, number, or boolean (other types are silently skipped). requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/JsonImportRequest' example: label: Person nodes: - name: Alice age: 30 - name: Bob age: 25 responses: '200': description: Import successful content: application/json: schema: $ref: '#/components/schemas/JsonImportResponse' '400': description: Import error (missing label, invalid data) content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/status: get: operationId: getStatus summary: Get server status description: Returns the health status, version, and storage statistics of the database. responses: '200': description: Server status content: application/json: schema: $ref: '#/components/schemas/StatusResponse' example: status: healthy version: 1.7.0 storage: nodes: 2000 edges: 11000 /api/tenants: get: operationId: listTenants summary: List all tenants description: Returns all configured tenants with their settings and quotas. responses: '200': description: List of tenants content: application/json: schema: type: object properties: tenants: type: array items: $ref: '#/components/schemas/Tenant' post: operationId: createTenant summary: Create a new tenant description: Create a new tenant with optional resource quotas. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateTenantRequest' example: id: analytics name: Analytics Team responses: '201': description: Tenant created content: application/json: schema: $ref: '#/components/schemas/Tenant' '409': description: Tenant already exists content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/tenants/{id}: parameters: - name: id in: path required: true schema: type: string description: Tenant ID get: operationId: getTenant summary: Get a tenant description: Returns a single tenant by ID. responses: '200': description: Tenant details content: application/json: schema: $ref: '#/components/schemas/Tenant' '404': description: Tenant not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' delete: operationId: deleteTenant summary: Delete a tenant description: Delete a tenant by ID. The "default" tenant cannot be deleted. responses: '200': description: Tenant deleted content: application/json: schema: type: object properties: status: type: string id: type: string '403': description: Cannot delete default tenant content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '404': description: Tenant not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' patch: operationId: updateTenant summary: Update tenant settings description: | Update a tenant's enabled status, resource quotas, or configuration. Only provided fields are updated; omitted fields remain unchanged. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateTenantRequest' responses: '200': description: Updated tenant content: application/json: schema: $ref: '#/components/schemas/Tenant' '404': description: Tenant not found content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' /api/sample: post: operationId: sampleSubgraph summary: Sample a representative subgraph description: > Returns a label-stratified, size-capped subgraph intended for visualization. One call replaces the `1 + ` sequential queries a client would otherwise issue to draw an overview, and the default of 200 nodes is the point past which a node-link diagram stops being legible. requestBody: required: false content: application/json: schema: type: object properties: max_nodes: type: integer default: 200 description: Upper bound on returned nodes. Capped server-side at 1000. labels: type: array items: type: string description: Restrict sampling to these labels. Empty means all labels. graph: type: string description: Tenant/graph name. responses: '200': description: A sampled subgraph content: application/json: schema: type: object /api/vector/indexes: get: operationId: listVectorIndexes summary: List vector indexes responses: '200': description: The configured vector indexes content: application/json: schema: type: object post: operationId: createVectorIndex summary: Create a vector index requestBody: required: true content: application/json: schema: type: object required: - label - property_key - dimensions properties: label: type: string property_key: type: string dimensions: type: integer metric: type: string description: Distance metric, e.g. cosine or euclidean. responses: '200': description: The index was created /api/vector-search: post: operationId: vectorSearch summary: k-nearest-neighbour search over a vector index description: > Supply either `query_vector` or `query_text`; supplying text requires an embedding provider to be configured. requestBody: required: true content: application/json: schema: type: object properties: query_text: type: string query_vector: type: array items: type: number format: float label: type: string property_key: type: string k: type: integer description: Number of neighbours to return. responses: '200': description: The nearest neighbours, closest first content: application/json: schema: type: object /api/snapshot/export: post: operationId: exportSnapshot summary: Export a tenant as a portable .sgsnap snapshot responses: '200': description: The snapshot bytes content: application/octet-stream: schema: type: string format: binary /api/snapshot/import: post: operationId: importSnapshot summary: Import a .sgsnap snapshot into a tenant description: > The body is **multipart/form-data**, not a raw octet stream — posting the bytes directly is the mistake this description exists to prevent. Import merges into the target tenant rather than replacing it. requestBody: required: true content: multipart/form-data: schema: type: object properties: file: type: string format: binary responses: '200': description: The snapshot was imported /api/nlq: post: operationId: naturalLanguageQuery summary: Translate a natural-language question into read-only Cypher description: | Translate a natural-language question into a read-only OpenCypher query using a configured LLM provider. NLQ must be enabled via environment (`NLQ_MODEL`, `OPENAI_API_KEY`, optional `NLQ_API_BASE_URL`). Returns the generated Cypher only; execute it with `/api/query`. requestBody: required: true content: application/json: schema: type: object required: - question properties: question: type: string description: The natural-language question to translate. examples: ask: summary: Ask for equipment by work-order count value: question: "Which chillers have more than 100 work orders?" responses: '200': description: Cypher generated successfully content: application/json: schema: type: object properties: cypher: type: string '400': description: NLQ disabled or generation error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' components: schemas: QueryRequest: type: object required: - query properties: query: type: string description: An OpenCypher query string examples: - "MATCH (n:Person) RETURN n" graph: type: string description: "Target graph/tenant name (default: 'default')" default: default QueryResponse: type: object properties: nodes: type: array description: Graph nodes referenced in the result (for visualization) items: $ref: '#/components/schemas/GraphNode' edges: type: array description: Graph edges referenced in the result (for visualization) items: $ref: '#/components/schemas/GraphEdge' columns: type: array description: Column names for the tabular result items: type: string records: type: array description: Tabular result rows, one array per record items: type: array items: {} GraphNode: type: object properties: id: type: string description: Node ID labels: type: array items: type: string description: Node labels properties: type: object additionalProperties: true description: Node properties GraphEdge: type: object properties: id: type: string description: Edge ID source: type: string description: Source node ID target: type: string description: Target node ID type: type: string description: Relationship type properties: type: object additionalProperties: true description: Edge properties StatusResponse: type: object properties: status: type: string description: Server health status examples: - healthy version: type: string description: Server version examples: - 1.7.0 storage: type: object properties: nodes: type: integer description: Number of nodes in the graph edges: type: integer description: Number of edges in the graph SchemaResponse: type: object properties: node_types: type: array items: type: object properties: label: type: string count: type: integer properties: type: object additionalProperties: type: string description: "Property type: String, Integer, Float, Boolean, Vector, Unknown" edge_types: type: array items: type: object properties: type: type: string count: type: integer source_labels: type: array items: type: string target_labels: type: array items: type: string properties: type: object additionalProperties: type: string indexes: type: array items: type: object properties: label: type: string property: type: string type: type: string constraints: type: array items: type: object properties: label: type: string property: type: string type: type: string statistics: type: object properties: total_nodes: type: integer total_edges: type: integer avg_out_degree: type: number JsonImportRequest: type: object required: - label - nodes properties: label: type: string description: Node label to assign to all created nodes nodes: type: array description: Array of JSON objects, each becoming a node items: type: object additionalProperties: true graph: type: string description: "Target graph/tenant name (default: 'default')" default: default CsvImportResponse: type: object properties: status: type: string examples: - ok nodes_created: type: integer label: type: string columns: type: array items: type: string JsonImportResponse: type: object properties: status: type: string examples: - ok nodes_created: type: integer label: type: string ErrorResponse: type: object properties: error: type: string description: Error message Tenant: type: object properties: id: type: string description: Tenant ID (unique identifier) name: type: string description: Display name enabled: type: boolean description: Whether the tenant is enabled created_at: type: integer description: Creation timestamp (Unix seconds) quotas: $ref: '#/components/schemas/ResourceQuotas' nlq_config: type: object nullable: true description: NLQ configuration agent_config: type: object nullable: true description: Agent configuration embed_config: type: object nullable: true description: Auto-embed configuration ResourceQuotas: type: object properties: max_nodes: type: integer nullable: true description: Maximum number of nodes max_edges: type: integer nullable: true description: Maximum number of edges max_memory_bytes: type: integer nullable: true description: Maximum memory in bytes max_storage_bytes: type: integer nullable: true description: Maximum storage in bytes max_connections: type: integer nullable: true description: Maximum concurrent connections max_query_time_ms: type: integer nullable: true description: Maximum query execution time in milliseconds CreateTenantRequest: type: object required: - id - name properties: id: type: string description: Tenant ID (unique) name: type: string description: Display name quotas: $ref: '#/components/schemas/ResourceQuotas' UpdateTenantRequest: type: object properties: enabled: type: boolean description: Enable or disable the tenant quotas: $ref: '#/components/schemas/ResourceQuotas' nlq_config: type: object description: NLQ configuration agent_config: type: object description: Agent configuration embed_config: type: object description: Auto-embed configuration UsageResponse: type: object properties: tenant_id: type: string node_count: type: integer edge_count: type: integer memory_bytes: type: integer storage_bytes: type: integer active_connections: type: integer