> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hydradb.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Tenant

> Create an isolated workspace for your data.

## When to use it

Creating a new tenant is the first step before any ingestion or recall. A tenant is a fully isolated workspace – no tenant can read another tenant's data.

In most cases, you create one tenant per organization. For per-user isolation (B2C), you use sub-tenants inside a single tenant.

## Endpoint

* **Auth:** Bearer token
* **Idempotency:** Re-sending with the same `tenant_id` returns `409 CONFLICT`
* **Async:** Yes – returns `status: accepted`. Poll `/tenants/infra/status` before use.

## Example

<CodeGroup>
  ```bash cURL theme={"dark"}
  curl -X POST 'https://api.hydradb.com/tenants/create' \
    -H "Authorization: Bearer <your_api_key>" \
    -H "Content-Type: application/json" \
    -d '{
      "tenant_id": "my_first_tenant",
      "tenant_metadata_schema": [
        {
          "name": "category",
          "data_type": "VARCHAR",
          "max_length": 256,
          "enable_match": true
        },
        {
          "name": "product_description",
          "data_type": "VARCHAR",
          "max_length": 4096,
          "enable_dense_embedding": true,
          "enable_sparse_embedding": true
        }
      ]
    }'
  ```

  ```typescript TypeScript SDK theme={"dark"}
  const response = await client.tenant.create({
    tenant_id: "my_first_tenant",
    tenant_metadata_schema: [
      {
        name: "category",
        data_type: "VARCHAR",
        max_length: 256,
        enable_match: true
      },
      {
        name: "product_description",
        data_type: "VARCHAR",
        max_length: 4096,
        enable_dense_embedding: true,
        enable_sparse_embedding: true
      }
    ]
  });
  ```

  ```python Python SDK theme={"dark"}
  response = client.tenant.create(
      tenant_id="my_first_tenant",
      tenant_metadata_schema={
          "category": "string",
          "product_description": "string",
      },
  )
  ```
</CodeGroup>

## Request parameters

| Name                     | Type                                 | Required | Description                                                                          |
| ------------------------ | ------------------------------------ | -------- | ------------------------------------------------------------------------------------ |
| `tenant_id`              | string                               | Yes      | Unique identifier for the tenant.                                                    |
| `tenant_metadata_schema` | array (TypeScript) / object (Python) | No       | Defines tenant-level metadata fields. See [Metadata schema](#metadata-schema) below. |

## Response

```json theme={"dark"}
{
  "status": "accepted",
  "tenant_id": "my_first_tenant",
  "message": "Tenant creation started in the background. Use GET /tenants/infra/status?tenant_id=... to check progress."
}
```

| Field       | Description                                             |
| ----------- | ------------------------------------------------------- |
| `status`    | Always `accepted`. Provisioning runs in the background. |
| `tenant_id` | The tenant identifier provided in the request.          |
| `message`   | Human-readable next-step hint.                          |

## Metadata schema

`tenant_metadata_schema` defines fields that all documents in the tenant inherit. Each entry has:

| Field                     | Type    | Default   | Description                                                                                   |
| ------------------------- | ------- | --------- | --------------------------------------------------------------------------------------------- |
| `name`                    | string  | –         | The field name. Required.                                                                     |
| `data_type`               | enum    | `VARCHAR` | Milvus data type. See list below.                                                             |
| `max_length`              | integer | `1024`    | Max length for `VARCHAR` fields.                                                              |
| `enable_analyzer`         | boolean | `false`   | Enable text analyzer for full-text search capabilities.                                       |
| `enable_match`            | boolean | `false`   | Enable exact-match filtering on this field.                                                   |
| `enable_dense_embedding`  | boolean | `false`   | Create a dense embedding for semantic similarity search. Only applicable to `VARCHAR` fields. |
| `enable_sparse_embedding` | boolean | `false`   | Create a sparse embedding (BM25) for keyword search. Only applicable to `VARCHAR` fields.     |
| `nullable`                | boolean | `true`    | Whether the field can be null.                                                                |

**Valid `data_type` values:**

`BOOL`, `INT8`, `INT16`, `INT32`, `INT64`, `FLOAT`, `DOUBLE`, `VARCHAR`, `JSON`, `ARRAY`, `FLOAT_VECTOR`, `SPARSE_FLOAT_VECTOR`.

For text fields that need to be semantically searchable, use `VARCHAR` with `enable_dense_embedding: true`. For keyword (BM25) searchability, add `enable_sparse_embedding: true`. For fields that must be filterable via `metadata_filters`, use `enable_match: true`. These flags are independent and can be combined.

<Warning>
  Schema field names are **immutable** after tenant creation. You can add new `additional_metadata` fields per document at ingestion time, but tenant-level fields cannot be renamed or removed. Plan the schema carefully before creating the tenant.
</Warning>

### Metadata schema examples

The following patterns cover the most common shapes of `tenant_metadata_schema`. Each example shows only the schema entries – wrap them in a full `POST /tenants/create` request like the [Example](#example) above.

**Single exact-match filter field**

The minimum useful schema field for deterministic filtering with `metadata_filters` is a `VARCHAR` field with `enable_match: true`.

```json theme={"dark"}
{
  "tenant_metadata_schema": [
    {
      "name": "environment",
      "data_type": "VARCHAR",
      "enable_match": true
    }
  ]
}
```

Values written under `metadata.environment` at ingestion time can then be filtered exactly during recall:

```json theme={"dark"}
{
  "metadata_filters": {
    "environment": "production"
  }
}
```

**Multiple `enable_match` fields**

Applications commonly define several stable fields they expect to filter on via `metadata_filters`. Use `INT32`, `INT64`, `BOOL`, `FLOAT`, or other typed fields when the value is not a string. Every field that must be filterable requires `enable_match: true`.

```json theme={"dark"}
{
  "tenant_metadata_schema": [
    {
      "name": "environment",
      "data_type": "VARCHAR",
      "enable_match": true
    },
    {
      "name": "document_type",
      "data_type": "VARCHAR",
      "enable_match": true
    },
    {
      "name": "version",
      "data_type": "INT32",
      "enable_match": true
    },
    {
      "name": "is_published",
      "data_type": "BOOL",
      "enable_match": true
    }
  ]
}
```

When multiple keys are passed in `metadata_filters`, they combine as structured exact-match constraints – a chunk must satisfy every key to remain a candidate.

**Long VARCHAR field**

`VARCHAR` defaults to a `max_length` of 1024 characters. For longer structured string values – compound identifiers, full label strings, or composite tags – set `max_length` explicitly.

```json theme={"dark"}
{
  "name": "compliance_label",
  "data_type": "VARCHAR",
  "max_length": 4096,
  "enable_match": true
}
```

**`enable_match` vs no flag**

Only fields declared with `enable_match: true` are usable in `metadata_filters` for deterministic filtering. A field without `enable_match: true` can still be stored in the schema, but passing it as a `metadata_filters` key will have no effect.

```json theme={"dark"}
{
  "tenant_metadata_schema": [
    {
      "name": "region",
      "data_type": "VARCHAR",
      "enable_match": true
    },
    {
      "name": "internal_notes",
      "data_type": "VARCHAR"
    }
  ]
}
```

* `region` has `enable_match: true` and can be used in `metadata_filters`.
* `internal_notes` has no `enable_match`, so it cannot be used in `metadata_filters`. It is stored but not filterable.
* For free-form display or bookkeeping fields that do not need filtering, prefer `additional_metadata` at ingestion time rather than adding them to the tenant schema.

**`enable_dense_embedding` and `enable_sparse_embedding` fields**

`enable_dense_embedding` makes a field semantically searchable (dense vector). `enable_sparse_embedding` makes it keyword-searchable (BM25/sparse vector). Use these when the field itself is a body of text you want included in semantic or keyword recall, for example a `product_description` that should be retrieved alongside the document.

```json theme={"dark"}
{
  "name": "product_description",
  "data_type": "VARCHAR",
  "max_length": 4096,
  "enable_dense_embedding": true,
  "enable_sparse_embedding": true
}
```

* Use `enable_match: true` for fields you intend to filter on exactly via `metadata_filters`.
* Use `enable_dense_embedding` / `enable_sparse_embedding` for `VARCHAR` fields that should be searchable as text.
* These flags are independent: an embedding-enabled field is not automatically usable as a `metadata_filters` key.

## Behavior notes

<Info>
  **Tenant creation is asynchronous.** Always poll `GET /tenants/infra/status?tenant_id=...` before your first ingestion call. Both values in `vectorstore_status` and `graph_status` must be `true` before the tenant is ready.
</Info>

<Info>
  **Default sub-tenant.** A default sub-tenant is auto-created with your tenant. Any API call that omits `sub_tenant_id` targets this default. See [Essentials → Multi-Tenant](/essentials/multi-tenant) for details.
</Info>

## Related endpoints

* **Next:** [Check infra status](/api-reference/endpoint/infra-status) – poll until provisioning completes
* **Next:** [Upload knowledge](/api-reference/endpoint/upload-knowledge) – start ingesting data
* **Related:** [Delete tenant](/api-reference/endpoint/delete-tenant) – teardown

## Errors

Common codes: `400 INVALID_PARAMETERS`, `409 TENANT_ALREADY_EXISTS`, `422 VALIDATION_ERROR`. See [Error Responses](/api-reference/error-responses) for the full list.

Read more: [Essentials → Multi-Tenant Support](/essentials/multi-tenant) · [Essentials → Metadata](/essentials/metadata)


## OpenAPI

````yaml POST /tenants/create
openapi: 3.1.0
info:
  title: HydraDB API
  description: REST APIs for the HydraDB retrieval engine
  version: 0.0.1
servers:
  - url: https://api.hydradb.com
    description: Production
    x-fern-server-name: hydradb-prod
security: []
paths:
  /tenants/create:
    post:
      tags:
        - tenants
      summary: Create Tenant
      operationId: create_tenant_tenants_create_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TenantCreateRequest'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TenantCreateAcceptedResponse'
        '400':
          description: Bad Request - Invalid input parameters
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
        '401':
          description: Unauthorized - Authentication required
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
        '403':
          description: Forbidden - Access denied
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
        '404':
          description: Not Found - Resource does not exist
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
        '422':
          description: Unprocessable Entity - Validation failed
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
        '503':
          description: Service Unavailable
          content:
            application/json:
              schema:
                $ref: >-
                  #/components/schemas/cortex__models__response__commons__ActualErrorResponse
      security:
        - HTTPBearer: []
components:
  schemas:
    TenantCreateRequest:
      properties:
        tenant_id:
          type: string
          minLength: 1
          title: Tenant Id
          description: Unique tenant identifier
          example: tenant_1234
        is_embeddings_tenant:
          type: boolean
          title: Is Embeddings Tenant
          description: True to create embeddings tenant
          default: false
          example: true
        embeddings_dimension:
          anyOf:
            - type: integer
            - type: 'null'
          title: Embeddings Dimension
          description: >-
            Embedding dimensions for embeddings tenant. Not required for
            non-embeddings (is_embeddings_tenant=False) tenants
          default: 1536
        tenant_metadata_schema:
          anyOf:
            - items:
                $ref: '#/components/schemas/CustomPropertyDefinition'
              type: array
            - type: 'null'
          title: Tenant Metadata Schema
          description: >-
            Schema definition for tenant metadata fields. Each field can be
            configured for: filtering (enable_match), semantic search
            (enable_dense_embedding), and/or keyword search
            (enable_sparse_embedding). Fields with embeddings enabled must be
            VARCHAR type.
          examples:
            - - data_type: VARCHAR
                enable_match: true
                max_length: 256
                name: category
              - data_type: VARCHAR
                enable_dense_embedding: true
                enable_sparse_embedding: true
                max_length: 4096
                name: product_description
          example:
            - name: department
              data_type: VARCHAR
              max_length: 256
              enable_match: true
            - name: compliance_framework
              data_type: VARCHAR
              max_length: 256
              enable_match: true
              enable_dense_embedding: false
              enable_sparse_embedding: false
            - name: data_classification
              data_type: VARCHAR
              max_length: 128
              enable_match: true
      type: object
      required:
        - tenant_id
      title: TenantCreateRequest
      description: >-
        Request model for creating a tenant with optional metadata schema.


        The `tenant_metadata_schema` allows you to define custom fields that
        will be indexed in Milvus with configurable search capabilities.


        Example:


        ```json

        {
          "tenant_id": "my-tenant",
          "tenant_metadata_schema": [
            {
              "name": "category",
              "data_type": "VARCHAR",
              "max_length": 256,
              "enable_match": true
            },
            {
              "name": "product_description",
              "data_type": "VARCHAR",
              "max_length": 4096,
              "enable_dense_embedding": true,
              "enable_sparse_embedding": true
            }
          ]
        }

        ```
    TenantCreateAcceptedResponse:
      properties:
        status:
          type: string
          title: Status
          description: Status of the request
          default: accepted
        tenant_id:
          type: string
          title: Tenant Id
          description: Tenant identifier that is being created
          example: tenant_1234
        message:
          type: string
          title: Message
          description: Response message
          default: >-
            Tenant creation started in the background. Use GET
            /tenants/infra/status?tenant_id=... to check progress.
      type: object
      required:
        - tenant_id
      title: TenantCreateAcceptedResponse
      description: Response when tenant creation is accepted and runs in the background.
    cortex__models__response__commons__ActualErrorResponse:
      properties:
        detail:
          $ref: >-
            #/components/schemas/cortex__models__response__commons__ErrorResponse
      type: object
      required:
        - detail
      title: ActualErrorResponse
    CustomPropertyDefinition:
      properties:
        name:
          type: string
          title: Name
          description: Property name (used as field name in Milvus)
          example: <name>
        data_type:
          $ref: '#/components/schemas/MilvusDataType'
          description: Milvus data type. Use VARCHAR for text fields that need embeddings.
          default: VARCHAR
        max_length:
          type: integer
          title: Max Length
          description: Max length for VARCHAR fields. Increase for longer text content.
          default: 1024
          example: 1
        enable_analyzer:
          type: boolean
          title: Enable Analyzer
          description: Enable text analyzer for full-text search capabilities
          default: false
          example: true
        enable_match:
          type: boolean
          title: Enable Match
          description: Enable TEXT_MATCH filtering on this field
          default: false
          example: true
        enable_dense_embedding:
          type: boolean
          title: Enable Dense Embedding
          description: >-
            Create a dense embedding field (FLOAT_VECTOR) for semantic
            similarity search. Only applicable to VARCHAR fields. A
            corresponding '{name}_embedding' field will be created.
          default: false
          example: true
        enable_sparse_embedding:
          type: boolean
          title: Enable Sparse Embedding
          description: >-
            Create a sparse embedding field (BM25) for keyword search. Only
            applicable to VARCHAR fields. A corresponding '{name}_sparse' field
            and BM25 function will be created.
          default: false
          example: true
        nullable:
          type: boolean
          title: Nullable
          description: Whether field can be null
          default: true
          example: true
      type: object
      required:
        - name
      title: CustomPropertyDefinition
      description: >-
        Definition for custom/dynamic properties on a collection.


        Use this to define tenant metadata fields that can enhance search
        capabilities:

        - enable_dense_embedding: Creates a dense vector field for semantic
        similarity search

        - enable_sparse_embedding: Creates a sparse vector field for BM25
        keyword search


        Example:
            CustomPropertyDefinition(
                name="product_description",
                data_type=MilvusDataType.VARCHAR,
                max_length=4096,
                enable_dense_embedding=True,  # Enables semantic search on this field
                enable_sparse_embedding=True,  # Enables keyword search on this field
            )
    cortex__models__response__commons__ErrorResponse:
      properties:
        success:
          type: boolean
          title: Success
          default: false
          example: true
        message:
          type: string
          title: Message
          default: Error occurred
        error_code:
          anyOf:
            - type: string
            - type: 'null'
          title: Error Code
      type: object
      title: ErrorResponse
    MilvusDataType:
      type: string
      enum:
        - BOOL
        - INT8
        - INT16
        - INT32
        - INT64
        - FLOAT
        - DOUBLE
        - VARCHAR
        - JSON
        - ARRAY
        - FLOAT_VECTOR
        - SPARSE_FLOAT_VECTOR
      title: MilvusDataType
      description: Milvus data types mapped from Weaviate schema.
  securitySchemes:
    HTTPBearer:
      type: http
      scheme: bearer

````