npm package: @hydra_db/node
Description: The official TypeScript SDK for the Hydra DB platform.
Author: Nishkarsh Shrivastava
Latest version: 0.1.2

# Hydra DB TypeScript SDK

The official TypeScript SDK for the Hydra DB platform. Build powerful, context-aware AI applications in your Node.js or TypeScript projects.

**Hydra DB** is your plug-and-play memory infrastructure. It powers intelligent, context-aware retrieval for any AI app or agent. Whether you're building a customer support bot, research copilot, or internal knowledge assistant - Hydra DB handles all!

[Learn more about the SDK from our docs](https://docs.hydradb.com/)

## Core features

* **Dynamic retrieval and querying** that always retrieves the most relevant context
* **Built-in long-term memory** that evolves with every user interaction
* **Personalization hooks** for user preferences, intent, and history
* **Raw embeddings support** for bring-your-own vector workflows
* **Developer-first SDK** with the most flexible APIs and fine-grained controls

## Getting started

### Installation

```
npm i @hydra_db/node
# or
yarn add @hydra_db/node
# or
pnpm add @hydra_db/node
```

### Client setup

```ts
import { HydraDBClient } from "@hydra_db/node";

process.loadEnvFile(".env");

const client = new HydraDBClient({
  token: process.env.HYDRA_DB_API_KEY,
});

const TENANT_ID = process.env.HYDRA_TENANT_ID ?? "my-company";
const SUB_TENANT_ID = process.env.HYDRA_SUB_TENANT_ID ?? "";
```

---

## Tenant Management

A `tenant` is a single isolated database. Within it you can create further isolated collections called `sub-tenants`. [Learn more](https://docs.hydradb.com/essentials/multi-tenant)

### Create a Tenant

```ts
const tenantResponse = await client.tenant.create({
  tenant_id: TENANT_ID,
});
```

You can also create a tenant optimised for raw vector embeddings:

```ts
const embeddingsTenant = await client.tenant.create({
  tenant_id: "my-embeddings-tenant",
  is_embeddings_tenant: true,
  embeddings_dimension: 1536,
});
```

### Get Sub-Tenant IDs

```ts
const subTenants = await client.tenant.getSubTenantIds({
  tenant_id: TENANT_ID,
});
// subTenants.sub_tenant_ids -> string[]
```

### Get Infrastructure Status

Check whether the tenant's underlying infrastructure is ready:

```ts
const infraStatus = await client.tenant.getInfraStatus({
  tenant_id: TENANT_ID,
});
```

### Monitor Tenant Stats

```ts
const stats = await client.tenant.monitor({
  tenant_id: TENANT_ID,
});
```

### Delete a Tenant

> **Warning:** This is irreversible and permanently removes all data.

```ts
await client.tenant.deleteTenant({
  tenant_id: TENANT_ID,
});
```

---

## Index Your Data

### Upload Knowledge (Files)

Upload documents to make them retrievable via natural language search. Supports PDFs, text files, and other document formats.

```ts
import fs from "node:fs";

const uploadResult = await client.upload.knowledge({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  files: [
    fs.readFileSync("report.pdf"),
    fs.readFileSync("notes.txt"),
  ],
  upsert: true,
});
// uploadResult.results[0].source_id -> ID you can use later
```

You can attach metadata to each file by passing a JSON string. Each object in the array corresponds to the file at the same index:

```ts
const fileMetadata = [
  {
    id: "doc_a",
    tenant_metadata: { dept: "sales" },
    document_metadata: { author: "Alice" },
  },
  {
    id: "doc_b",
    tenant_metadata: { dept: "marketing" },
    document_metadata: { author: "Bob" },
    relations: {
      cortex_source_ids: ["doc_a"],
      properties: { relation: "same_upload_batch" },
    },
  },
];

const uploadWithMeta = await client.upload.knowledge({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  files: [
    fs.readFileSync("a.pdf"),
    fs.readFileSync("b.pdf"),
  ],
  file_metadata: JSON.stringify(fileMetadata),
  upsert: true,
});
```

### Verify Processing Status

After uploading, check when files have finished indexing:

```ts
const status = await client.upload.verifyProcessing({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  file_ids: ["source-id-1", "source-id-2"],
});
// status.statuses[0].indexing_status -> "queued" | "processing" | "completed" | "errored"
```

### Add Memories

Index free-form text, markdown content, or conversation pairs as searchable memories.

**Plain text:**

```ts
await client.upload.addMemory({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  upsert: true,
  memories: [
    {
      text: "User prefers detailed explanations and dark mode",
      infer: true,
      user_name: "John",
    },
  ],
});
```

**Markdown:**

```ts
await client.upload.addMemory({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  upsert: true,
  memories: [
    {
      text: "# Meeting Notes\n\n## Key Points\n- Budget approved\n- Launch date: Q2",
      is_markdown: true,
      infer: false,
      title: "Meeting Notes",
    },
  ],
});
```

**User–assistant conversation pairs:**

```ts
await client.upload.addMemory({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  upsert: true,
  memories: [
    {
      user_assistant_pairs: [
        { user: "What are my preferences?", assistant: "You prefer dark mode and detailed explanations." },
        { user: "How do I like my reports?", assistant: "You prefer weekly summary reports with charts." },
      ],
      infer: true,
      user_name: "John",
      custom_instructions: "Extract user preferences",
    },
  ],
});
```

### Delete a Memory

```ts
await client.upload.deleteMemory({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  memory_id: "memory-source-id",
});
```

---

## Search & Retrieval

### Full Recall

Hybrid semantic + keyword search across both knowledge and memories:

```ts
const results = await client.recall.fullRecall({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  query: "Which mode does the user prefer?",
  alpha: 0.8,        // 1.0 = pure semantic, 0.0 = pure keyword
  recency_bias: 0,   // 0.0 = no bias, 1.0 = strongly prefer recent
  max_results: 10,
});
// results.chunks -> VectorStoreChunk[]
// results.sources -> SourceInfo[]
```

### Recall Preferences

Search only user memory/preference data:

```ts
const preferences = await client.recall.recallPreferences({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  query: "dark mode preference",
  max_results: 5,
});
```

### Boolean Recall

Exact keyword / phrase / boolean search (BM25):

```ts
const boolResults = await client.recall.booleanRecall({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  query: "dark mode",
  operator: "phrase",   // "or" | "and" | "phrase"
  max_results: 10,
  search_mode: "memories",  // "sources" | "memories"
});
```

### Q&A (LLM-powered answer)

Ask a question and get a grounded answer generated by an LLM over your indexed content:

```ts
const answer = await client.recall.qna({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  question: "What is the user's preferred reporting format?",
  mode: "fast",          // "fast" | "thinking"
  search_mode: "memories",
  max_chunks: 6,
});
```

You can optionally choose the LLM provider and model:

```ts
const customAnswer = await client.recall.qna({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  question: "Summarise the budget decisions from the meeting notes.",
  mode: "thinking",
  search_mode: "sources",
  max_chunks: 10,
  llm_provider: "anthropic",
  model: "claude-sonnet-4-6",
  temperature: 0.2,
  max_tokens: 1024,
});
```

---

## Fetch & Inspect Data

### List All Data

List sources (knowledge) or memories with optional filtering and pagination:

```ts
// List knowledge sources
const sources = await client.fetch.listData({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  kind: "knowledge",
  page: 1,
  page_size: 50,
});

// List user memories
const memories = await client.fetch.listData({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  kind: "memories",
});
```

Filter by metadata:

```ts
const filtered = await client.fetch.listData({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  kind: "knowledge",
  filters: {
    tenant_metadata: { dept: "sales" },
  },
});
```

### Fetch Source Content

Retrieve the full content of a specific source by its ID:

```ts
const source = await client.fetch.content({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  source_id: "your-source-id",
  mode: "content",   // "content" | "url" | "both"
});
```

### Fetch Graph Relations

Retrieve the graph relations (linked sources) for a given source:

```ts
const relations = await client.fetch.graphRelationsBySourceId({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  source_id: "your-source-id",
  is_memory: false,
  limit: 10,
});
```

---

## Delete Data

Delete one or more sources (knowledge or memories) by their IDs:

```ts
await client.data.delete({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  ids: ["source-id-1", "source-id-2"],
});
```

---

## API Key Management

> **Note:** This endpoint requires a dashboard session token (obtained via your Hydra DB dashboard login), not a standard API key. Use it from a server-side admin context where you have a valid user session.

Create scoped API keys for controlled access:

```ts
const newKey = await client.key.createApiKey({
  owner: "service-account@myapp.com",
  scopes: ["query"],
  env: "live",
  prefix: "sk",
});
// newKey.full_api_key -> the actual key (only shown once)
```

---

## Raw Embeddings

Use Hydra DB as a vector store with your own embeddings — useful when you want to manage embedding generation yourself.

> **Note:** Raw embeddings require a tenant created with `is_embeddings_tenant: true` and a fixed `embeddings_dimension`. A standard knowledge tenant does not support raw embedding operations.
>
> ```ts
> await client.tenant.create({
>   tenant_id: "my-embeddings-tenant",
>   is_embeddings_tenant: true,
>   embeddings_dimension: 1536,
> });
> ```

### Insert Embeddings

```ts
await client.embeddings.insert({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  upsert: true,
  embeddings: [
    {
      source_id: "my-doc-001",
      metadata: { category: "finance", year: 2024 },
      embeddings: [
        { chunk_id: "my-doc-001-chunk-0", embedding: [0.1, 0.2, 0.3 /* ... 1536 dims */] },
        { chunk_id: "my-doc-001-chunk-1", embedding: [0.4, 0.5, 0.6 /* ... 1536 dims */] },
      ],
    },
  ],
});
```

### Search by Vector

Find the most similar chunks to a query embedding:

```ts
const searchResults = await client.embeddings.search({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  query_embedding: [0.1, 0.2, 0.3 /* ... 1536 dims */],
  limit: 10,
});
// searchResults -> RawEmbeddingSearchResult[]
```

### Filter Embeddings

Retrieve stored embeddings for a specific source or set of chunk IDs:

```ts
// By source
const bySource = await client.embeddings.filter({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  source_id: "my-doc-001",
  limit: 50,
});

// By chunk IDs
const byChunks = await client.embeddings.filter({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  chunk_ids: ["my-doc-001-chunk-0", "my-doc-001-chunk-1"],
});
```

### Delete Embeddings

```ts
// Delete all embeddings for a source
await client.embeddings.delete({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  source_id: "my-doc-001",
});

// Delete specific chunks
await client.embeddings.delete({
  tenant_id: TENANT_ID,
  sub_tenant_id: SUB_TENANT_ID,
  chunk_ids: ["my-doc-001-chunk-0"],
});
```

---

## Platform Metrics

Retrieve platform-level health and usage metrics:

```ts
const metrics = await client.metricsMetricsGet();
```

---

## SDK Method Reference

| Method | Description |
|---|---|
| `client.tenant.create` | Create a new tenant (standard or embeddings) |
| `client.tenant.getSubTenantIds` | List all sub-tenant IDs within a tenant |
| `client.tenant.getInfraStatus` | Check tenant infrastructure readiness |
| `client.tenant.monitor` | Get tenant usage and stats |
| `client.tenant.deleteTenant` | Permanently delete a tenant and all its data |
| `client.upload.knowledge` | Upload files to the knowledge base |
| `client.upload.verifyProcessing` | Poll indexing status of uploaded files |
| `client.upload.addMemory` | Index text, markdown, or conversation pairs as memories |
| `client.upload.deleteMemory` | Delete a specific memory by ID |
| `client.recall.fullRecall` | Hybrid semantic + keyword search |
| `client.recall.recallPreferences` | Search user memory / preference data only |
| `client.recall.booleanRecall` | Exact keyword / phrase / boolean search |
| `client.recall.qna` | LLM-powered question answering over indexed content |
| `client.fetch.listData` | List all knowledge sources or memories |
| `client.fetch.content` | Fetch full content of a source by ID |
| `client.fetch.graphRelationsBySourceId` | Fetch graph relations for a source |
| `client.data.delete` | Delete sources or memories by ID |
| `client.key.createApiKey` | Create a scoped API key *(requires dashboard session token)* |
| `client.embeddings.insert` | Store raw vector embeddings *(requires embeddings tenant)* |
| `client.embeddings.search` | Vector similarity search |
| `client.embeddings.filter` | Retrieve embeddings by source or chunk IDs |
| `client.embeddings.delete` | Delete embeddings by source or chunk IDs |
| `client.metricsMetricsGet` | Retrieve platform metrics |

> **Method Mapping:** `client.<group>.<method>` mirrors `api.hydradb.com/<group>/<method>`
>
> For example: `client.upload.knowledge()` → `POST /ingestion/upload_knowledge`

---

## Type Safety & IDE Support

The SDK provides exact type parity with the API:

- **Request parameters** — every field (required, optional, type, validation) is reflected in the method signature
- **Response objects** — return types match the exact JSON schema from each endpoint
- **Nested objects** — complex parameters and responses preserve their full structure

Your IDE will automatically provide autocompletion, type-checking, inline documentation, and compile-time validation for every method. Just hit **Cmd+Space / Ctrl+Space**.

---

## Links

- **Homepage:** [hydradb.com](https://www.hydradb.com/)
- **Documentation:** [docs.hydradb.com](https://docs.hydradb.com/)
- **API Reference:** [docs.hydradb.com/api-reference/introduction](https://docs.hydradb.com/api-reference/introduction)

## Support

If you have any questions or need help, reach out at [founders@hydradb.com](mailto:founders@usecortex.ai).