---
title: "HeliosDB Nano API Reference"
---

# HeliosDB Nano API Reference

Complete API reference for all HeliosDB Nano integration points across languages and deployment modes.

---

## REST API (Server Mode)

Base URL: `http://localhost:8080` (default)

:::caution[Authentication and row-level security]
Keep the HTTP and MySQL listeners on loopback (the default): API-key authentication for the HTTP API is planned, and a smaller listening surface is good practice anyway.
Row-level security policies are not applied to
HTTP requests: enforce per-user access in your service layer. SQL
`CREATE POLICY` and RLS enforcement for REST and wire clients are planned.
:::

### Endpoints

#### Queries

**Execute SQL Query**

```
POST /v1/branches/{branch}/query
Content-Type: application/json

Request Body:
{
  "sql": "SELECT * FROM users WHERE id = $1",
  "params": [1]
}

Response (200 OK):
{
  "rows": [
    {"id": 1, "name": "Alice", "email": "alice@example.com"}
  ],
  "columns": ["id", "name", "email"],
  "rows_affected": 0
}

Error Response (400):
{
  "error": {
    "code": "42P01",
    "message": "relation \"users\" does not exist"
  }
}
```

**Natural Language Query (planned)**

A natural-language query (NL-to-SQL) route over HTTP is planned (roadmap); the current
release does not route `/v1/nl/query`.

**Query at Timestamp (Time-Travel)**

```
POST /v1/branches/{branch}/query
Content-Type: application/json

Request Body:
{
  "sql": "SELECT * FROM users",
  "params": [],
  "as_of_timestamp": "2025-01-01T00:00:00Z"
}

Response (200 OK):
{
  "rows": [...],
  "columns": [...],
  "rows_affected": 0
}
```

#### Vector Search

**Text Vector Search (planned)**

Searching a store by text, with the server embedding the query, is planned (roadmap). In
the current release `POST /v1/vectors/stores/{store}/search/text` is mounted but returns a not-implemented
error; embed the query in your application and search by vector.

**Vector Search by Vector**

```
POST /v1/vectors/stores/{store}/search
Content-Type: application/json

Request Body:
{
  "vector": [0.1, 0.2, 0.3, ...],
  "top_k": 10,
  "min_score": 0.5
}

Response (200 OK):
{
  "results": [
    {
      "id": "doc_123",
      "score": 0.95,
      "content": "...",
      "metadata": {}
    }
  ]
}
```

**Store Text with Embedding (planned)**

Storing texts with server-side embedding is planned (roadmap). In the current release
`POST /v1/vectors/stores/{store}/texts` is mounted but returns a not-implemented error;
compute embeddings in your application and store them as vectors, or keep text and
embeddings in a table and search it with SQL.

#### Vector Store Management

**List Vector Stores**

```
GET /v1/vectors/stores

Response (200 OK):
{
  "stores": [
    {
      "name": "documents",
      "dimensions": 1536,
      "metric": "cosine",
      "count": 1000
    }
  ]
}
```

**Create Vector Store**

```
POST /v1/vectors/stores
Content-Type: application/json

Request Body:
{
  "name": "documents",
  "dimensions": 1536,
  "metric": "cosine"
}

Response (201 Created):
{
  "name": "documents",
  "dimensions": 1536,
  "metric": "cosine",
  "count": 0
}
```

#### Branching

**List Branches**

```
GET /v1/branches

Response (200 OK):
{
  "branches": [
    {
      "name": "main",
      "parent": null,
      "created_at": "2025-01-01T00:00:00Z"
    },
    {
      "name": "dev",
      "parent": "main",
      "created_at": "2025-01-10T12:30:00Z"
    }
  ]
}
```

**Create Branch**

```
POST /v1/branches
Content-Type: application/json

Request Body:
{
  "name": "feature-branch",
  "from_branch": "main"
}

Response (201 Created):
{
  "name": "feature-branch",
  "parent": "main",
  "created_at": "2025-01-15T10:00:00Z"
}
```

**Merge Branches**

```
POST /v1/branches/{source}/merge
Content-Type: application/json

Request Body:
{
  "target": "main"
}

Response (200 OK):
{
  "status": "merged",
  "changes": 5
}
```

#### Agent Memory (planned)

An agent-memory REST API (sessions, messages, memory search and summaries) is planned for
Nano. In the current release the `/v1/agents/memory` routes are mounted but do not store sessions or
messages yet: creating a session or adding a message returns a not-implemented error,
and listing returns an empty result. Today, keep messages and their embeddings in a
table and query them over the PostgreSQL wire protocol (recent history with
`ORDER BY id DESC LIMIT n`, related messages with `ORDER BY embedding <=> $1::vector(n)`).

#### Document Management (planned)

Document ingest, chunking and search over HTTP are planned for Nano. In the current
release the `/v1/documents` routes are mounted but do not store documents yet. Store text and
embeddings in tables and search them with SQL (vector distance operators and
`ts_rank_cd`).

#### Schema Inference

**Infer a table from JSON samples**

`POST /v1/schema/infer` takes sample JSON objects and returns inferred columns and a
`CREATE TABLE` statement. Inference from CSV text and from files is planned (in the
current release `POST /v1/schema/infer/file` returns a placeholder with a warning).

```
POST /v1/schema/infer
Content-Type: application/json

Request Body:
{
  "samples": [
    {"id": 1, "name": "Alice", "score": 95.5},
    {"id": 2, "name": "Bob", "score": 87.3}
  ],
  "table_name": "students"
}

Response (200 OK):
{
  "success": true,
  "data": {
    "table_name": "students",
    "columns": [
      {"name": "id", "sql_type": "INTEGER", "nullable": false, ...},
      ...
    ],
    "ddl": "CREATE TABLE students (...);",
    "warnings": [...]
  }
}
```

Review the generated `ddl` before running it: it marks every column `NOT NULL` and adds
`PRIMARY KEY (id)`.

#### Chat Completion (planned)

Chat completions over the Nano HTTP API are planned (roadmap). In the current release
`POST /v1/chat/completions` is mounted but returns a not-implemented error; call your
LLM provider from the application and pass it rows retrieved with SQL.

#### Query Management

**Cancel Query**

```
POST /v1/queries/{query_id}/cancel

Response (200 OK):
{
  "status": "cancelled",
  "query_id": "q_abc123"
}
```

**List Running Queries**

```
GET /v1/queries/?include_completed=false&user=app&database=main&state=executing

Response (200 OK):
{
  "queries": [ ... ],
  "total": 1
}
```

All query parameters are optional. Related routes: `GET /v1/queries/stats`,
`GET /v1/queries/{query_id}`, `POST /v1/queries/cancel-session` and
`POST /v1/queries/cancel-timed-out`.

#### Tenant Management (planned)

Tenant routes over HTTP are planned; the current release routes no `/v1/tenants` endpoints.
Manage tenants, plans and quotas with the REPL `\tenant` commands or the embedded Rust
API (see [Multi-Tenancy](https://www.heliosdb.com/docs/nano/features/multi-tenancy/)).

In the stock Nano server, row-level security is enforced through the embedded API and the
REPL; SQL `CREATE POLICY` and enforcement for REST and wire clients are planned.

#### Health

**Health Check**

```
GET /health

Response (200 OK):
{
  "status": "ok"
}
```

`GET /version` returns the server version.

---

## PostgreSQL Wire Protocol (Server Mode)

Standard PostgreSQL protocol on port 5432.

### Connection String Format

```
postgresql://[user[:password]@][host][:port]/[database]

Examples:
postgresql://localhost:5432/mydb
postgresql://user:password@db.example.com:5432/mydb
postgres://localhost/mydb
```

### Supported Features

- Standard SQL (DML/DDL)
- Parameterized queries ($1, $2,...)
- Transactions (BEGIN/COMMIT/ROLLBACK)
- Multiple data types
- Indexes
- Transactions with isolation levels

### Supported Client Libraries

- **Python**: psycopg2, asyncpg, sqlalchemy
- **JavaScript/Node**: pg, node-postgres, sequelize
- **Rust**: sqlx, tokio-postgres, diesel
- **Go**: database/sql, pgx, sqlc
- **Java**: JDBC, Hibernate
- **.NET**: Npgsql, Entity Framework
- **PHP**: PDO, php-pgsql

---

## Rust API (Native/Embedded Mode)

### Core Types

```rust
pub struct EmbeddedDatabase {
    // ...
}

pub struct QueryResult {
    pub rows: Vec<HashMap<String, Value>>,
    pub columns: Vec<String>,
    pub rows_affected: i64,
}

pub struct VectorSearchResult {
    pub id: String,
    pub score: f64,
    pub content: Option<String>,
    pub metadata: Option<HashMap<String, Value>>,
}

pub enum Value {
    Null,
    Bool(bool),
    Int4(i32),
    Int8(i64),
    Float4(f32),
    Float8(f64),
    String(String),
    Bytes(Vec<u8>),
    Json(serde_json::Value),
    Vector(Vec<f32>),
}
```

### Core Methods

```rust
impl EmbeddedDatabase {
    // Lifecycle
    pub fn new(path: &str) -> Result<Self>;
    pub fn new_in_memory() -> Result<Self>;
    pub fn with_config(path: &str, config: Config) -> Result<Self>;

    // Query execution
    pub fn execute(&self, sql: &str, params: &[Value]) -> Result<()>;
    pub fn query(&self, sql: &str, params: &[Value]) -> Result<QueryResult>;
    pub fn query_row(&self, sql: &str, params: &[Value]) -> Result<Option<Row>>;

    // Transactions
    pub fn begin_transaction(&self) -> Result<Transaction>;

    // Vector operations
    pub fn vector_search(&self, store: &str, query: &str, top_k: usize)
        -> Result<Vec<VectorSearchResult>>;
    pub fn store_text(&self, store: &str, text: &str,
        metadata: Option<HashMap<String, Value>>) -> Result<String>;

    // Branching
    pub fn create_branch(&self, name: &str, from: Option<&str>,
        options: Option<BranchOptions>) -> Result<()>;
    pub fn merge_branch(&self, source: &str, target: &str) -> Result<()>;
    pub fn drop_branch(&self, name: &str) -> Result<()>;
    pub fn switch_branch(&self, name: &str) -> Result<()>;

    // Time-travel
    pub fn query_as_of_timestamp(&self, sql: &str,
        timestamp: &str, params: &[Value]) -> Result<QueryResult>;
    pub fn query_as_of_transaction(&self, sql: &str,
        txn_id: u64, params: &[Value]) -> Result<QueryResult>;
}
```

### Trait Methods

```rust
pub trait ToSqlValue {
    fn to_sql_value(&self) -> Value;
}

impl ToSqlValue for i32 { ... }
impl ToSqlValue for i64 { ... }
impl ToSqlValue for f64 { ... }
impl ToSqlValue for String { ... }
impl ToSqlValue for &str { ... }
impl ToSqlValue for bool { ... }
impl ToSqlValue for Vec<f32> { ... }
```

---

## Python SDK API

### Client

```python
class Client:
    def __init__(
        self,
        base_url: str = "http://localhost:8080",
        api_key: Optional[str] = None,
        branch: str = "main",
        timeout: float = 30.0
    ) -> None: ...

    async def query(
        self,
        sql: str,
        params: Optional[List[Any]] = None,
        branch: Optional[str] = None
    ) -> QueryResult: ...

    async def execute(
        self,
        sql: str,
        params: Optional[List[Any]] = None
    ) -> int: ...

    async def nl_query(
        self,
        question: str
    ) -> Tuple[QueryResult, str]: ...

    async def vector_search(
        self,
        store: str,
        query: str,
        top_k: int = 10,
        min_score: Optional[float] = None,
        filter: Optional[Dict[str, Any]] = None
    ) -> List[VectorSearchResult]: ...

    async def store_text(
        self,
        store: str,
        text: str,
        metadata: Optional[Dict[str, Any]] = None
    ) -> str: ...

    async def create_vector_store(
        self,
        name: str,
        dimensions: int,
        metric: str = "cosine"
    ) -> Dict[str, Any]: ...

    async def list_vector_stores(self) -> List[Dict[str, Any]]: ...

    async def create_branch(
        self,
        name: str,
        from_branch: Optional[str] = None
    ) -> Dict[str, Any]: ...

    async def merge_branch(self, source: str, target: str) -> None: ...

    async def memory_add(
        self,
        session_id: str,
        role: str,
        content: str
    ) -> None: ...

    async def memory_get(
        self,
        session_id: str,
        limit: int = 50
    ) -> List[Dict[str, Any]]: ...

    async def memory_search(
        self,
        session_id: str,
        query: str,
        top_k: int = 5
    ) -> List[VectorSearchResult]: ...

    async def close(self) -> None: ...
```

### Data Classes

```python
@dataclass
class QueryResult:
    rows: List[Dict[str, Any]]
    columns: List[str]
    rows_affected: int = 0

@dataclass
class VectorSearchResult:
    id: str
    score: float
    content: Optional[str] = None
    metadata: Optional[Dict[str, Any]] = None

@dataclass
class VectorStore:
    name: str
    dimensions: int
    metric: str
    count: int

@dataclass
class Branch:
    name: str
    parent: Optional[str] = None
    created_at: str = ""

@dataclass
class Message:
    role: str
    content: str
    timestamp: Optional[str] = None
```

---

## TypeScript SDK API

### Client

```typescript
class HeliosDBClient {
    constructor(config: ClientConfig);

    async query(sql: string, params?: any[]): Promise<QueryResult>;

    async execute(sql: string, params?: any[]): Promise<number>;

    async nlQuery(question: string): Promise<[QueryResult, string]>;

    async vectorSearch(
        store: string,
        query: string,
        options?: VectorSearchOptions
    ): Promise<VectorSearchResult[]>;

    async storeText(
        store: string,
        text: string,
        metadata?: Record<string, any>
    ): Promise<string>;

    async createVectorStore(
        name: string,
        dimensions: number,
        metric?: string
    ): Promise<Record<string, any>>;

    async listVectorStores(): Promise<Record<string, any>[]>;

    async createBranch(
        name: string,
        fromBranch?: string
    ): Promise<Record<string, any>>;

    async mergeBranch(source: string, target: string): Promise<void>;

    async memoryAdd(
        sessionId: string,
        role: string,
        content: string
    ): Promise<void>;

    async memoryGet(
        sessionId: string,
        limit?: number
    ): Promise<Record<string, any>[]>;

    async memorySearch(
        sessionId: string,
        query: string,
        topK?: number
    ): Promise<VectorSearchResult[]>;

    async close(): Promise<void>;
}
```

### Types

```typescript
interface QueryResult {
    rows: Record<string, any>[];
    columns: string[];
    rows_affected?: number;
}

interface VectorSearchResult {
    id: string;
    score: number;
    content?: string;
    metadata?: Record<string, any>;
}

interface ClientConfig {
    baseUrl?: string;
    apiKey?: string;
    branch?: string;
    timeout?: number;
}

interface VectorSearchOptions {
    topK?: number;
    minScore?: number;
    filter?: Record<string, any>;
}
```

---

## Go SDK API

### Client

```go
type Client struct {
    // ...
}

func NewClient(baseURL, apiKey string) *Client

func (c *Client) Query(ctx context.Context, sql string,
    params ...interface{}) (*QueryResult, error)

func (c *Client) Execute(ctx context.Context, sql string,
    params ...interface{}) (int64, error)

func (c *Client) NLQuery(ctx context.Context, question string)
    (*QueryResult, string, error)

func (c *Client) VectorSearch(ctx context.Context, store, query string,
    opts ...*SearchOptions) ([]VectorSearchResult, error)

func (c *Client) StoreText(ctx context.Context, store, text string,
    metadata map[string]interface{}) (string, error)

func (c *Client) CreateBranch(ctx context.Context, name string,
    fromBranch ...string) error

func (c *Client) MergeBranch(ctx context.Context, source, target string) error

func (c *Client) MemoryAdd(ctx context.Context, sessionID, role, content string)
    error

func (c *Client) MemoryGet(ctx context.Context, sessionID string,
    limit int) ([]map[string]interface{}, error)

func (c *Client) MemorySearch(ctx context.Context, sessionID, query string,
    topK int) ([]VectorSearchResult, error)

func (c *Client) Close() error
```

### Types

```go
type QueryResult struct {
    Rows         []map[string]interface{}
    Columns      []string
    RowsAffected int64
}

type VectorSearchResult struct {
    ID       string
    Score    float64
    Content  *string
    Metadata map[string]interface{}
}

type SearchOptions struct {
    TopK     int
    MinScore *float64
    Filter   map[string]interface{}
}
```

---

## Error Codes & Responses

### HTTP Response Codes

| Code | Meaning | Example |
|------|---------|---------|
| 200 | Success | Query executed |
| 201 | Created | Resource created |
| 400 | Bad Request | Invalid SQL syntax |
| 401 | Unauthorized | Missing or expired token on an `/auth/v1` route |
| 404 | Not Found | Table not found |
| 429 | Rate Limited | Too many requests |
| 500 | Server Error | Internal error |

### PostgreSQL Error Codes (SQLSTATE)

| Code | Class | Meaning |
|------|-------|---------|
| 00000 | SUCCESS | Success |
| 42P01 | SYNTAX_ERROR | Relation does not exist |
| 42P02 | SYNTAX_ERROR | Column does not exist |
| 23505 | INTEGRITY | Unique violation |
| 23503 | INTEGRITY | Foreign key violation |
| 25001 | TRANSACTION | Transaction failed |

---

## Configuration Reference

### Server Configuration (heliosdb.toml)

```toml
[storage]
path = "./heliosdb-data"
cache_size = 536870912
compression = "Zstd"
memory_only = false

[server]
listen_addr = "127.0.0.1"
port = 5432
max_connections = 100

[performance]
simd_enabled = true
worker_threads = 0          # 0 = one per CPU core

[encryption]
enabled = false
algorithm = "Aes256Gcm"

[encryption.key_source]
Environment = "HELIOSDB_ENCRYPTION_KEY"

[vector]
# Product Quantization is chosen per index, not in this file:
#   CREATE INDEX ... USING hnsw (embedding) WITH (quantization = 'product');
```

### Command-Line Flags

Listener and data settings come from `heliosdb-nano start` flags or the config file, not
from environment variables:

| Flag | Default | Meaning |
|------|---------|---------|
| `--data-dir <dir>` (or `-m`/`--memory`) | required | Data directory, or in-memory mode |
| `--listen <addr>` | `127.0.0.1` | PostgreSQL listener address |
| `--port <port>` | `5432` | PostgreSQL listener port |
| `--http-port <port>` | `8080` | HTTP API port (`0` disables the HTTP listener) |
| `--http-listen <addr>` | value of `--listen` | HTTP API listener address |
| `--config <file>` | none | TOML configuration file |

Keep the HTTP and MySQL listeners on loopback (the default): API-key authentication for the HTTP API is planned, and a smaller listening surface is good practice anyway.

### Environment Variables

| Variable | Meaning |
|----------|---------|
| `HELIOSDB_ENCRYPTION_KEY` | Encryption-at-rest key (64 hex characters) when `[encryption.key_source] Environment` names it, as in the default |
| `RUST_LOG` | Log filter, for example `RUST_LOG=info` (default: warnings only) |

---

## Rate Limits & Quotas

### Rate Limiting (Server Mode)

- Default: 1000 requests/second per IP
- Configurable via `max_connections`
- WebSocket connections: 100/second

### Resource Limits

- Max query size: No hard limit
- Max result rows: Limited by memory
- Max vector dimensions: 4096
- Max text length: 2 GB per cell

---

## Changelog & Versioning

### Versioning Scheme

`MAJOR.MINOR.PATCH[-PRERELEASE]`

- MAJOR: Breaking API changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes
- PRERELEASE: alpha, beta, rc

### Compatibility

- SDK versions must match server major version
- Patch versions are forward compatible
- Minor versions are forward compatible

---

## Support & Contact

- **GitHub Issues**: https://github.com/HeliosDatabase/HeliosDB-Nano/issues
- **Documentation**: https://www.heliosdb.com/docs/nano/
- **Email**: support@heliosdb.com
