Metadata-Version: 2.4
Name: hydradb-sdk
Version: 2.1.0
Summary: The official Python SDK for the Hydra DB (hydradb.com)
Author-email: Nishkarsh Srivastava <nishkarsh@hydradb.com>
License: Copyright (c) 2026 Hydra DB
        
        All Rights Reserved.
        
        PROPRIETARY AND CONFIDENTIAL
        
        This software is the proprietary and confidential property of AGI Context, INC ("the Company").
        Permission is hereby granted to users to install and use this software as part of the Hydra DB service, subject to the terms and conditions of the service agreement entered into with the Company.
        
        You may not, without the express written permission of the Company:
        
        1. Copy, modify, or create derivative works of the software.
        2. Distribute, sell, rent, lease, sublicense, or otherwise transfer the software to any third party.
        3. Reverse engineer, decompile, or disassemble the software, except and only to the extent that such activity is expressly permitted by applicable law notwithstanding this limitation.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Project-URL: Homepage, https://hydradb.com/
Project-URL: Documentation, https://docs.hydradb.com/
Keywords: hydradb-sdk,hydradb,ai,sdk,api,generative ai,rag,db
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24
Requires-Dist: pydantic<3,>=1.10
Dynamic: license-file

# HydraDB Python SDK

The official Python SDK for [HydraDB](https://hydradb.com) — a managed retrieval engine that
combines vector search, full‑text search, and a knowledge graph behind a single API.

- **Package:** `hydradb-sdk`
- **Import module:** `hydra_db`
- **Version:** `2.0.2` (API version `2`)
- **Docs:** https://docs.hydradb.com
- **Python:** 3.10+

---

## Table of contents

- [Installation](#installation)
- [Quick start](#quick-start)
- [Client configuration](#client-configuration)
- [Core concepts](#core-concepts)
- [Endpoints](#endpoints)
  - [`query` — unified retrieval](#query--unified-retrieval)
  - [Context (`client.context`)](#context-clientcontext)
    - [`ingest`](#contextingest)
    - [`list`](#contextlist)
    - [`inspect`](#contextinspect)
    - [`status`](#contextstatus)
    - [`relations`](#contextrelations)
    - [`update_source_metadata`](#contextupdate_source_metadata)
    - [`delete`](#contextdelete)
  - [Databases (`client.databases`)](#databases-clientdatabases)
    - [`create`](#databasescreate)
    - [`list`](#databaseslist)
    - [`collections`](#databasescollections)
    - [`stats`](#databasesstats)
    - [`status`](#databasesstatus)
    - [`delete`](#databasesdelete)
  - [Webhooks (`client.webhooks`)](#webhooks-clientwebhooks)
    - [`register`](#webhooksregister)
    - [`get`](#webhooksget)
    - [`test`](#webhookstest)
    - [`delete`](#webhooksdelete)
    - [`list_deliveries`](#webhookslist_deliveries)
    - [`get_delivery`](#webhooksget_delivery)
    - [`retry_delivery`](#webhooksretry_delivery)
- [Async usage](#async-usage)
- [Error handling](#error-handling)
- [Advanced](#advanced)
  - [Request options (timeouts & retries)](#request-options-timeouts--retries)
  - [Raw responses](#raw-responses)
  - [Custom HTTP client](#custom-http-client)

---

## Installation

```bash
pip install hydradb-sdk
```

## Quick start

```python
from hydra_db import HydraDB

client = HydraDB(
    token="YOUR_API_KEY",      # your HydraDB API key (bearer token)
    api_version="2",           # optional, defaults to "2"
)

# Run a hybrid search over a database ("tenant")
result = client.query(
    query="What is our refund policy?",
    database="acme-corp",
    type="knowledge",
    max_results=5,
)

for chunk in result.data.chunks:
    print(chunk)
```

Every method returns a typed response object (Pydantic models). Responses are wrapped in a
`HandlerEnvelope…` type — the payload lives on `.data`, with request metadata on `.meta`.

---

## Client configuration

```python
from hydra_db import HydraDB
from hydra_db.environment import HydraDBEnvironment

client = HydraDB(
    token="YOUR_API_KEY",
    api_version="2",
    environment=HydraDBEnvironment.DEFAULT,   # https://api.hydradb.com
    # base_url="https://api.hydradb.com",     # override for self-hosted / staging
    timeout=60.0,                             # seconds; default 60
    headers={"X-Custom-Header": "value"},     # sent on every request
)
```

| Parameter          | Type                              | Default                     | Notes |
| ------------------ | --------------------------------- | --------------------------- | ----- |
| `token`            | `str \| Callable[[], str]`        | –                           | Bearer token. Pass a callable for dynamic/refreshing tokens. |
| `api_version`      | `str`                             | `"2"`                       | Sets the API version header. |
| `environment`      | `HydraDBEnvironment`              | `DEFAULT`                   | `DEFAULT` → `https://api.hydradb.com`. |
| `base_url`         | `str`                             | –                           | Explicit URL; overrides `environment`. |
| `timeout`          | `float`                           | `60`                        | Per‑request timeout in seconds. |
| `headers`          | `dict[str, str]`                  | –                           | Extra headers on every request. |
| `follow_redirects` | `bool`                            | `True`                      | – |
| `httpx_client`     | `httpx.Client`                    | –                           | Bring your own configured client. |

---

## Core concepts

**Database vs. Collection (tenant vs. sub‑tenant).** HydraDB v2 renamed the isolation scopes:

| v2 name (canonical) | v1 alias (deprecated, still accepted) | Meaning |
| ------------------- | ------------------------------------- | ------- |
| `database`          | `tenant_id`                           | Top‑level isolation boundary. |
| `collection`        | `sub_tenant_id`                       | A namespace within a database. |

The server’s `TenantAliases` middleware reconciles the two, so you can pass either — but new
code should use `database` / `collection`. The legacy aliases will be removed in a future release.

**Corpora (`type`).** Data is split into two corpora you can target independently:
`"knowledge"` (documents), `"memory"` (agent memories), or `"all"`.

---

## Endpoints

### `query` — unified retrieval

`POST /query` → `HandlerEnvelopeSearchV2RetrievalResult`

The single retrieval endpoint. Dispatches across corpus (`type`) and retrieval method
(`query_by`), optionally enriching results with knowledge‑graph context.

```python
from hydra_db import HydraDB

client = HydraDB(token="YOUR_API_KEY")

result = client.query(
    query="How do I rotate API keys?",
    database="acme-corp",           # v2 name for the tenant scope
    type="knowledge",               # "knowledge" | "memory" | "all"
    query_by="hybrid",              # "hybrid" | "text"
    mode="auto",                    # "fast" | "thinking" | "auto"
    operator="or",                  # "or" | "and" | "phrase"
    max_results=10,
    num_related_chunks=3,
    graph_context=True,             # include KG context (default True)
    recency_bias=0.2,
    metadata_filters={              # exact-match on tenant/document metadata
        "department": "security",
        "additional_metadata": {"author": "ada"},
    },
)

print(result.data)
```

**Scoping to specific collections** (preferred over the deprecated `sub_tenant_ids`):

```python
# Equal weighting across collections
client.query(query="pricing", database="acme-corp", collections=["eu", "us"])

# Weighted ranking (one decimal place max)
client.query(query="pricing", database="acme-corp", collections={"eu": 1.0, "us": 0.5})
```

**Scoping to specific source IDs** — `ids` applies a hard `source_id in [...]` pre‑filter;
if nothing matches it returns empty rather than widening to the whole corpus:

```python
client.query(query="onboarding", database="acme-corp", ids=["doc_123", "doc_456"])
```

Key parameters:

| Parameter                  | Type                          | Notes |
| -------------------------- | ----------------------------- | ----- |
| `query`                    | `str`                         | The search text. |
| `database`                 | `str`                         | Tenant scope (v2). Alias: `tenant_id`. |
| `collection` / `collections` | `str` / `list \| dict`      | Sub‑tenant scope. Prefer over `sub_tenant_id(s)`. |
| `type`                     | `"knowledge" \| "memory" \| "all"` | Corpus to query. |
| `query_by`                 | `"hybrid" \| "text"`          | Retrieval method. |
| `mode`                     | `"fast" \| "thinking" \| "auto"` | Recall mode. |
| `operator`                 | `"or" \| "and" \| "phrase"`   | Text‑match operator. |
| `max_results`              | `int`                         | Result cap. |
| `num_related_chunks`       | `int`                         | Neighboring chunks to attach. |
| `graph_context`            | `bool`                        | Include KG context. Default `True`. |
| `query_apps`               | `bool`                        | App‑aware knowledge retrieval. |
| `query_forceful_relations` | `bool`                        | Force relation expansion. Default `True`. |
| `metadata_filters`         | `dict[str, Any]`              | Exact‑match on metadata (nest under `additional_metadata` for doc metadata). |
| `recency_bias`             | `float`                       | Boost newer sources. |
| `ids`                      | `list[str]`                   | Restrict to specific source IDs. |

---

### Context (`client.context`)

Everything about the data *inside* a database: ingesting, listing, inspecting, updating
metadata, checking processing status, reading graph relations, and deleting.

#### `context.ingest`

`POST` (multipart) → `HandlerEnvelopeIngestionV2SourceUploadResponse`

Ingest knowledge documents or memories. `documents` is a file upload; the other fields are
form fields (JSON strings where structured).

```python
from hydra_db import HydraDB

client = HydraDB(token="YOUR_API_KEY")

# Ingest a document file
with open("handbook.pdf", "rb") as f:
    resp = client.context.ingest(
        tenant_id="acme-corp",          # required
        documents=f,                    # file-like / (filename, bytes) / bytes
        sub_tenant_id="hr",
        type="knowledge",
        # document_metadata is a JSON *array* — one object per uploaded file.
        document_metadata='[{"title": "Employee Handbook", "author": "HR"}]',
        upsert="true",                  # form field is a string
    )

print(resp.data)

# Ingest memories (no file). Each item needs "text" (or "user_assistant_pairs").
client.context.ingest(
    tenant_id="acme-corp",
    memories='[{"text": "User prefers dark mode"}]',
    type="memory",
)
```

| Parameter           | Type              | Notes |
| ------------------- | ----------------- | ----- |
| `tenant_id`         | `str` (required)  | Database. |
| `documents`         | `core.File`       | File upload (path handle, bytes, or `(name, bytes)` tuple). |
| `memories`          | `str`             | JSON **array** string; each item needs `text` (or `user_assistant_pairs`). |
| `document_metadata` | `str`             | JSON **array** string of per‑document metadata — one object per uploaded file (count must match). |
| `app_knowledge`     | `str`             | App‑knowledge payload. |
| `graph_payload`     | `str`             | Pre‑computed graph payload. |
| `sub_tenant_id`     | `str`             | Collection. |
| `type`              | `str`             | `"knowledge"` or `"memory"`. |
| `upsert`            | `str`             | `"true"` to upsert on existing IDs. |

#### `context.list`

`GET /context/list` → `HandlerEnvelopeListV2SourceListResponse`

List sources or memories (IDs + metadata) for a database, with filtering and pagination.

```python
from hydra_db import HydraDB
from hydra_db import ListContentFilter

client = HydraDB(token="YOUR_API_KEY")

resp = client.context.list(
    database="acme-corp",
    collection="hr",
    type="knowledge",
    page=1,
    page_size=50,
    include_fields=["title", "type", "timestamp"],
    filters=ListContentFilter(
        metadata={"department": "finance"},          # tenant/source metadata
        additional_metadata={"author": "ada"},       # document metadata
        source_fields={"type": "pdf"},               # well-known source fields
    ),
)

for source in resp.data.sources:
    print(source)
```

#### `context.inspect`

`GET` → `HandlerEnvelopeFetchV2SourceFetchResponse`

Fetch a single ingested source: its content, inferred content, and a presigned download URL.

```python
resp = client.context.inspect(
    id="doc_1234",                 # required — source ID
    tenant_id="acme-corp",         # required
    sub_tenant_id="hr",
    expiry_seconds=3600,           # presigned URL lifetime
    mode="both",                   # fetch mode: "content", "url", or "both"
)
print(resp.data.download_url)
```

#### `context.status`

`GET` → `HandlerEnvelopeIngestionV2BatchProcessingStatus`

Check processing status for one or more source IDs.

```python
# Single source
client.context.status(tenant_id="acme-corp", id="doc_1234", sub_tenant_id="hr")

# Batch
resp = client.context.status(
    tenant_id="acme-corp",
    ids=["doc_1", "doc_2", "doc_3"],
)
print(resp.data)
```

#### `context.relations`

`GET` → `HandlerEnvelopeGraphGraphRelationsResponse`

Return knowledge‑graph relations for a whole database or a single source.

```python
resp = client.context.relations(
    tenant_id="acme-corp",         # required
    sub_tenant_id="hr",
    id="doc_1234",                 # omit for database-wide relations
    type="knowledge",              # "knowledge" | "memory"
    limit=100,
    cursor=0,                      # pagination cursor (float)
)
for triplet in resp.data.relations:
    print(triplet)
```

#### `context.update_source_metadata`

`PATCH` → `HandlerEnvelope…MetadataEditResult`

Merge/upsert `tenant_metadata` and `additional_metadata` for one source. `sub_tenant_id`
is required by the server.

```python
resp = client.context.update_source_metadata(
    source_id="doc_1234",          # required
    tenant_id="acme-corp",
    sub_tenant_id="hr",
    # tenant_metadata keys must be declared in the database's tenant_metadata_schema
    # (and match the declared type). Use additional_metadata for free-form fields.
    tenant_metadata={"department": "finance"},
    additional_metadata={"author": "ada", "tags": ["policy", "2026"], "reviewed": True},
)
print(resp.data)
```

> **Note:** although the SDK exposes a `document_metadata` parameter here, this endpoint
> **rejects** it (HTTP 400 "document_metadata is not accepted; use additional_metadata").
> Put per-document fields in `additional_metadata` instead.

#### `context.delete`

`DELETE` → `HandlerEnvelopeSourcesMemoryDeleteResponse`

Delete one or more sources or memories by ID.

```python
resp = client.context.delete(
    database="acme-corp",
    collection="hr",
    ids=["doc_1234", "doc_5678"],
    type="knowledge",
)
print(resp.data)
```

---

### Databases (`client.databases`)

Manage databases (tenants) and inspect their collections, stats, and provisioning status.

#### `databases.create`

`POST` → `HandlerEnvelopeTenantsTenantCreateAcceptedResponse`

Create a new database, optionally with a custom metadata schema for its collections.

```python
from hydra_db import HydraDB
from hydra_db import TenantsCustomPropertyDefinition

client = HydraDB(token="YOUR_API_KEY")

resp = client.databases.create(
    database="acme-corp",
    embeddings_dimension=1536,
    is_embeddings_tenant=True,
    tenant_metadata_schema=[
        TenantsCustomPropertyDefinition(
            name="department",
            data_type="VARCHAR",   # BOOL | INT8..INT64 | FLOAT | DOUBLE | VARCHAR | JSON | ARRAY
            max_length=128,
            enable_match=True,
        ),
        TenantsCustomPropertyDefinition(name="priority", data_type="INT32"),
    ],
)
print(resp.data)
```

> Creation is asynchronous — poll [`databases.status`](#databasesstatus) until infrastructure
> is provisioned before ingesting.

#### `databases.list`

`GET` → `HandlerEnvelopeTenantsTenantIdsResponse`

List all databases for the authenticated user.

```python
resp = client.databases.list()
print(resp.data)
```

#### `databases.collections`

`GET` → `HandlerEnvelopeTenantsSubTenantIdsResponse`

List all collections within a database.

```python
resp = client.databases.collections(database="acme-corp")
print(resp.data)
```

#### `databases.stats`

`GET` → `HandlerEnvelopeTenantsTenantStatsResponse`

Get collection statistics for a database.

```python
resp = client.databases.stats(database="acme-corp")
print(resp.data)
```

#### `databases.status`

`GET` → `HandlerEnvelopeTenantsInfraStatusResponseV2`

Check infrastructure provisioning status for a database.

```python
resp = client.databases.status(database="acme-corp")
print(resp.data)
```

#### `databases.delete`

`DELETE` → `HandlerEnvelopeTenantsTenantDeleteResponse`

Delete a database and **all** associated data.

```python
resp = client.databases.delete(database="acme-corp")
print(resp.data)
```

---

### Webhooks (`client.webhooks`)

Register a single indexing webhook per org and inspect/replay its deliveries.

#### `webhooks.register`

`POST` → `HandlerEnvelopeWebhooksWebhookRegisterResponse`

Register (or update) the indexing webhook for this API key’s org.

```python
resp = client.webhooks.register(
    url="https://example.com/hooks/hydradb",
    event_types=["indexing.status_changed"],   # the only supported event type
    signing_secret="whsec_at_least_16_chars",  # must be >= 16 characters
)
print(resp.data)
```

#### `webhooks.get`

`GET` → `HandlerEnvelopeWebhooksWebhookGetResponse`

Fetch the currently registered webhook.

```python
resp = client.webhooks.get()
print(resp.data)
```

#### `webhooks.test`

`POST` → `HandlerEnvelopeWebhooksWebhookTestResponse`

Send a test delivery to the registered endpoint.

```python
resp = client.webhooks.test()
print(resp.data)
```

#### `webhooks.delete`

`DELETE` → `HandlerEnvelopeWebhooksWebhookDeleteResponse`

Remove the registered webhook.

```python
resp = client.webhooks.delete()
print(resp.data)
```

#### `webhooks.list_deliveries`

`GET` → `HandlerEnvelopeWebhooksDeliveryListResponse`

List recent webhook deliveries, with filtering and cursor pagination.

```python
resp = client.webhooks.list_deliveries(
    limit=50,
    cursor=None,                    # pass the previous page's cursor to continue
    status="failed",               # filter by delivery status
)
for delivery in resp.data.deliveries:
    print(delivery)
```

#### `webhooks.get_delivery`

`GET` → `HandlerEnvelopeWebhooksDeliveryItem`

Fetch a single delivery by ID.

```python
resp = client.webhooks.get_delivery(delivery_id="dlv_1234")
print(resp.data)
```

#### `webhooks.retry_delivery`

`POST` → `HandlerEnvelopeWebhooksRetryResponse`

Re‑attempt a failed delivery.

```python
resp = client.webhooks.retry_delivery(delivery_id="dlv_1234")
print(resp.data)
```

---

## Async usage

Every method has an `async` twin on `AsyncHydraDB`. The API surface is identical — just
`await` each call.

```python
import asyncio
from hydra_db import AsyncHydraDB

client = AsyncHydraDB(token="YOUR_API_KEY")


async def main() -> None:
    result = await client.query(query="refund policy", database="acme-corp")
    print(result.data)

    dbs = await client.databases.list()
    print(dbs.data)


asyncio.run(main())
```

`AsyncHydraDB` also accepts an `async_token` callable for token acquisition that involves
async I/O (e.g. refreshing a token over HTTP).

---

## Error handling

Non‑2xx responses raise typed exceptions, all subclasses of `ApiError`. Each carries
`status_code` and the parsed `body`.

```python
from hydra_db import HydraDB
from hydra_db.core.api_error import ApiError
from hydra_db.errors import (
    BadRequestError,          # 400
    ForbiddenError,           # 403
    NotFoundError,            # 404
    ConflictError,            # 409
    UnprocessableEntityError, # 422
    InternalServerError,      # 500
)

client = HydraDB(token="YOUR_API_KEY")

try:
    client.databases.status(database="does-not-exist")
except NotFoundError as e:
    print("not found:", e.body)
except ApiError as e:
    print(f"API error {e.status_code}: {e.body}")
```

---

## Advanced

### Request options (timeouts & retries)

Pass `request_options` to any method to override per call.

```python
client.query(
    query="hello",
    database="acme-corp",
    request_options={
        "timeout_in_seconds": 30,
        "max_retries": 3,
        "additional_headers": {"X-Trace-Id": "abc123"},
    },
)
```

### Raw responses

Use `with_raw_response` to access status code and headers alongside the parsed body.

```python
raw = client.with_raw_response.query(query="hello", database="acme-corp")
print(raw.headers)
print(raw.data)
```

### Custom HTTP client

```python
import httpx
from hydra_db import HydraDB

client = HydraDB(
    token="YOUR_API_KEY",
    httpx_client=httpx.Client(
        proxies="http://localhost:8080",
        transport=httpx.HTTPTransport(retries=3),
    ),
)
```

---

## Endpoint reference

| Group     | Method                          | Description |
| --------- | ------------------------------- | ----------- |
| —         | `query`                         | Unified hybrid/text retrieval across corpora with optional graph context. |
| context   | `ingest`                        | Ingest documents or memories (multipart upload). |
| context   | `list`                          | List sources/memories with metadata filters + pagination. |
| context   | `inspect`                       | Fetch a source’s content + presigned download URL. |
| context   | `status`                        | Processing status for one or many source IDs. |
| context   | `relations`                     | Knowledge‑graph relations for a database or source. |
| context   | `update_source_metadata`        | Merge/upsert metadata for a source. |
| context   | `delete`                        | Delete sources/memories by ID. |
| databases | `create`                        | Create a database with optional metadata schema. |
| databases | `list`                          | List all databases for the user. |
| databases | `collections`                   | List collections in a database. |
| databases | `stats`                         | Collection statistics for a database. |
| databases | `status`                        | Infrastructure provisioning status. |
| databases | `delete`                        | Delete a database and all its data. |
| webhooks  | `register`                      | Register/update the org indexing webhook. |
| webhooks  | `get`                           | Get the registered webhook. |
| webhooks  | `test`                          | Send a test delivery. |
| webhooks  | `delete`                        | Remove the webhook. |
| webhooks  | `list_deliveries`               | List recent deliveries. |
| webhooks  | `get_delivery`                  | Fetch one delivery by ID. |
| webhooks  | `retry_delivery`                | Retry a failed delivery. |

---

_This SDK is generated from the HydraDB API definition. For the full parameter reference see
[`src/hydra_db/reference.md`](src/hydra_db/reference.md) or https://docs.hydradb.com._
