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

# Instance API

> REST API for managing Knowledge Objects and their instances.

# Knowledge Object API

Every Knowledge Object is backed by a REST API for managing its **instances** — the rows of its materialized table. This page covers the object endpoints (create, list, read) and the full instance CRUD API.

* **Base path:** `/knowledge-object`
* **Auth:** standard logged-in session, same as every other app endpoint.
* **Permissions:** resource type `knowledge_object` under the project hierarchy — read endpoints require `read`, instance writes require `write`.

## Branching

Every endpoint takes an optional **`branch` query parameter, defaulting to `main`**. Objects are stored in your repository, so each branch has its own definition and its own ClickHouse table:

* The object id in the URL is **stable across branches** — only the `branch` param changes when you switch.
* Object reads return `definition: null` when the object is not deployed on the requested branch.
* Instance calls return `404` when the object is not deployed on the requested branch.
* **Instance operations require the branch's definition to be `READY`** — otherwise they return `400`. Gate instance UIs on `definition.status === "READY"`.

<Info>
  See [Overview → Branching](/reference/knowledge-objects/overview#branching) for the full model.
</Info>

***

## Object endpoints

### Create object

Creates an object by writing its YAML file to the repository and deploying it — the object and its definition are then materialized by the loader, exactly as if you had committed the file yourself.

```http theme={null}
POST /knowledge-object/create
Content-Type: application/json

{
  "metadata": {
    "name": "Company",
    "description": "A company.",
    "fields": [
      { "name": "id", "type": "int", "primary_key": true },
      { "name": "name", "type": "str" },
      { "name": "owner", "type": "str", "optional": true, "relationship": [{ "object": "Person" }] }
    ],
    "settings": { "label_column": "name", "icon": "building" }
  },
  "project": "6748d8b66a5a2ac9f0d39326",
  "branch": "main"
}
```

| Field      | Type   | Description                                                                                                      |
| ---------- | ------ | ---------------------------------------------------------------------------------------------------------------- |
| `metadata` | object | The object definition ([YAML reference](/reference/knowledge-objects/yaml-reference), as JSON). Fully validated. |
| `project`  | string | Id of the project to create the object in.                                                                       |
| `branch`   | string | (Optional) Branch to deploy on. Defaults to `main`.                                                              |

* `metadata` is validated exactly like a deployed YAML file (primary key required, relationship rules, `label_column` must name a field, …) — an invalid definition returns `400`.
* The server writes `objects/<name>_<hash>.yaml`, registers it in the project's `config.yaml`, and deploys on `branch`. The definition starts at `PENDING_MIGRATION` and is materialized asynchronously.
* **Response:** `200` with no body. Poll [Get object](#get-object) or [List objects](#list-objects) for the definition and its `status`.
* `400` if an object with the same name already exists in the project.

### Update object

```http theme={null}
PATCH /knowledge-object/{id}
Content-Type: application/json

{ "metadata": { /* name, description, fields, settings */ }, "branch": "main" }
```

Updates the object's metadata **on one branch** by rewriting its YAML file and redeploying.

* Send the full `metadata` (same shape as create). `branch` is optional (defaults to `main`).
* **Renaming is not supported** — `metadata.name` must equal the current name (`400` otherwise).
* **Changing the primary key** (columns or types) is rejected (`400`) — the instance key derives from it.
* A schema change re-runs migration (definition returns to `PENDING_MIGRATION` → `READY`); metadata/settings-only changes apply in place.
* **Response:** `200`, no body. Poll [Get object](#get-object) for the updated definition and `status`.

### Delete object

```http theme={null}
DELETE /knowledge-object/{id}?branch=main
```

Removes the object's **definition on the given branch only** (other branches keep theirs; `branch` defaults to `main`).

* The object is removed from its YAML file (the file and its `config.yaml` entry are dropped when it was the only object in the file) and redeployed. The branch definition is deleted, and the object identity is deleted once no branch has a definition.
* A background task then drops that branch's ClickHouse table and view.
* **Response:** `204`, no body.

### List objects

```http theme={null}
GET /knowledge-object/list?branch=main
```

Standard list parameters — `filters`, `page`, `page_size`, `sort_by` — plus `branch` (default `main`). Filters apply to the object identity (e.g. `name`, `project.$id`); the definition for the selected branch is attached to each item.

```http theme={null}
# Objects of one project, with their feature-x definitions
GET /knowledge-object/list?filters=[project.$id][$eq]:6748d8b66a5a2ac9f0d39326&branch=feature-x
```

```json theme={null}
{ "total_count": 3, "items": [ { "id": "…", "name": "Employee", "branches": ["main"], "definition": { } } ] }
```

Only objects deployed on the selected branch are returned.

### Get object

```http theme={null}
GET /knowledge-object/get-by-id/{id}?branch=main
```

Returns the object identity plus the definition for the requested branch. `definition` is `null` when the object is not deployed on that branch.

```json theme={null}
{
  "id": "6863f1a2c9d4b2a7e1f00001",
  "name": "Employee",
  "project": { "id": "6748d8b66a5a2ac9f0d39326", "collection": "project" },
  "branches": ["feature-x", "main"],
  "definition": {
    "id": "6863f1a2c9d4b2a7e1f00002",
    "branch": "main",
    "file_path": "objects/employee.yaml",
    "status": "READY",
    "error_message": null,
    "table_name": "object_main_employee__raw",
    "view_name": "object_main_employee",
    "metadata": {
      "name": "Employee",
      "description": "Employee object.",
      "settings": { "object_type": "STANDALONE", "store_versions": false, "icon": "users", "label_column": "name" },
      "fields": [
        { "name": "id", "type": "int", "primary_key": true, "optional": false, "mutable": true, "default": null, "relationship": null },
        { "name": "name", "type": "str", "primary_key": false, "optional": false, "mutable": true },
        { "name": "owner", "type": "str", "optional": true, "relationship": [{ "object": "Person" }] }
      ],
      "actions": []
    }
  }
}
```

Use `definition.metadata.fields` to build instance forms and table columns, and `definition.view_name` to query the object in the SQL editor. The view exposes the object fields plus `__version`, `__timestamp`, and `__primary_key` (the instance key as hex).

***

## Instance endpoints

All instance endpoints are nested under an object id: `/knowledge-object/{id}/instances`. `{id}` is the object's id (not its name). Each accepts `branch` (default `main`) and operates on that branch's table.

### List instances

```http theme={null}
GET /knowledge-object/{id}/instances?page=1&page_size=50&branch=main
```

| Param       | Type            | Default  | Description                            |
| ----------- | --------------- | -------- | -------------------------------------- |
| `page`      | int             | `1`      | Page number.                           |
| `page_size` | int             | `50`     | Rows per page.                         |
| `branch`    | string          | `main`   | Branch to read from.                   |
| `fields`    | repeated string | *(all)*  | [Column selection](#column-selection). |
| `filters`   | repeated JSON   | *(none)* | [Row filtering](#row-filtering).       |

```json theme={null}
{
  "total_count": 128,
  "items": [
    { "_key": "8A3F9C2E1B4D6F7A8A3F9C2E1B4D6F7A", "id": 1, "name": "john", "last_login": "2026-07-01T09:30:00Z", "_version": 1 }
  ]
}
```

Each item is the selected object fields plus the meta fields `_key` and `_version`.

#### Column selection

Use the repeated `fields` query parameter to fetch only the columns you need — for example a dropdown that shows the label column and stores the primary key:

* **omitted** → all object fields (default).
* `?fields=id&fields=name` → only those fields, plus `_key` and `_version`.
* `?fields=` (present but empty) → only the meta fields `_key` and `_version`.
* An unknown field name → `400` (`detail.unknown_fields`).

The meta fields `_key` and `_version` are always included.

#### Row filtering

Use the repeated `filters` query parameter to filter rows. Each value is a JSON object `{ "column", "operator", "value" }`, and multiple filters are combined with **AND**. Filtering affects both the returned rows and `total_count`.

```http theme={null}
GET /knowledge-object/{id}/instances
    ?filters={"column":"is_active","operator":"equal","value":true}
    &filters={"column":"salary","operator":"greater_than","value":50000}
```

| `operator`     | Meaning                        |
| -------------- | ------------------------------ |
| `equal`        | column = value                 |
| `not_equal`    | column ≠ value                 |
| `greater_than` | column > value                 |
| `less_than`    | column \< value                |
| `contains`     | case-sensitive substring match |
| `not_contains` | negated substring match        |

* `column` must be an object field name → an unknown column returns `400` (`detail.unknown_filter_column`).
* `value` is **not** type-checked against the field; it is sent to the database as a safely-escaped literal.
* A filter that isn't valid JSON returns `400` (`detail.invalid_filter`).
* Combine freely with `fields`, `page`, and `page_size`.

### Create instance

```http theme={null}
POST /knowledge-object/{id}/instances
Content-Type: application/json

{ "id": 1, "name": "john", "last_login": null }
```

* The payload is validated against the object's field definitions (types, required, nullable).
* Optional fields, and fields with a `default`, may be omitted — the database fills in defaults (including functional ones like `now()`).

**Response:** `201 Created` with the created instance (its `_key` is in the body).

```json theme={null}
{ "_key": "8A3F9C2E1B4D6F7A8A3F9C2E1B4D6F7A", "id": 1, "name": "john", "last_login": null }
```

* `409` if an instance with the same primary key values already exists.
* Creating with the primary key of a previously **deleted** instance succeeds — the instance is revived under the same `_key`.

### Batch upsert instances

Insert or update many instances in a single request — useful for bulk imports and syncing.

```http theme={null}
POST /knowledge-object/{id}/instances/batch?branch=main
Content-Type: application/json

[
  { "id": 1, "name": "john" },
  { "id": 2, "name": "jane", "last_login": "2026-07-01T09:30:00Z" },
  { "id": 3, "name": "amir" }
]
```

The request body is a **JSON array of instance payloads** (each shaped exactly like a single [create](#create-instance) payload). Semantics are **upsert**:

* If an instance with the same primary key does **not** exist, it is inserted as a new instance (version `1`).
* If it **already exists**, a new version is appended with an incremented version number (the previous value is kept in [history](#instance-history)). A previously **deleted** instance is revived the same way.
* Optional fields and fields with a `default` may be omitted per item — the database fills them in.

Constraints:

* **Maximum 1000 items per request** — more returns `400` (`detail.max_batch_size`, `detail.received`).
* The **whole batch is validated before any write**. If any item is invalid, nothing is written and the response is `400` with the offending item's index (`detail.index`, `detail.errors`).
* A primary key that appears **more than once within the same batch** is rejected with `400` (`detail.index`, `detail.error`).

**Response:** `200` with a summary of what was applied.

```json theme={null}
{ "created": 2, "updated": 1, "total": 3 }
```

To retrieve the resulting instances (with their `_key`s), read them back via [List](#list-instances).

### Get instance

```http theme={null}
GET /knowledge-object/{id}/instances/{key}?branch=main&add_relationships=false
```

Returns the instance, or `404` if it does not exist or was deleted.

**Relationships** — pass `add_relationships=true` to resolve the object's relationship fields. Each relationship field keeps its raw `_key` value, and a parallel `_relationships` object is added, keyed by field name, holding the resolved related instance (or `null` when the key is empty, the target object is not deployed/ready on the branch, or the related instance was deleted). Resolution is **one level deep**. Default is `false` (no `_relationships` key, no extra queries).

```json theme={null}
{
  "_key": "AB12...",
  "id": 5,
  "name": "Acme",
  "owner": "9F3C...",
  "_relationships": {
    "owner": { "_key": "9F3C...", "id": 1, "name": "John", "email": "j@acme.com" }
  }
}
```

### Instance history

```http theme={null}
GET /knowledge-object/{id}/instances/{key}/history?branch=main
```

Returns **all versions** of an instance, newest first — including deletion rows, and even for instances that are currently deleted (so it works where a plain `GET` returns `404`).

```json theme={null}
[
  { "_key": "8A3F…", "id": 1, "name": "John Smith", "_version": 2, "_timestamp": "2026-07-06T10:00:00", "_deleted": false, "_user_id": "6748d8…" },
  { "_key": "8A3F…", "id": 1, "name": "john",       "_version": 1, "_timestamp": "2026-07-05T09:30:00", "_deleted": false, "_user_id": "6748d8…" }
]
```

Each item is the object fields plus `_version`, `_timestamp`, `_deleted`, and `_user_id` (empty string when not written by a user). `404` if no instance ever existed for the key.

<Note>
  For objects with `store_versions: false`, superseded versions may be compacted away over time — history is best-effort in that mode.
</Note>

### Update instance

```http theme={null}
PATCH /knowledge-object/{id}/instances/{key}
Content-Type: application/json

{ "name": "John Smith" }
```

* Send only the fields to change (partial update).
* Primary key fields in the payload → `400` (they are immutable; a different primary key is a different instance).
* Immutable fields (`mutable: false`) cannot be changed after creation.
* Returns the full updated instance.

### Delete instance

```http theme={null}
DELETE /knowledge-object/{id}/instances/{key}
```

`204 No Content`. A subsequent `GET` on the key returns `404`. Deletion is logical — history is kept internally and the key can be revived by creating an instance with the same primary key.

***

## Errors

| Status | When                                     | Detail                                                                    |
| ------ | ---------------------------------------- | ------------------------------------------------------------------------- |
| `400`  | Definition not `READY` on the branch     | Instance operations require a completed migration.                        |
| `400`  | Payload fails validation                 | `detail.errors` carries the validation message (`detail.index` on batch). |
| `400`  | Batch larger than 1000 items             | `detail.max_batch_size`, `detail.received`.                               |
| `400`  | Duplicate primary key within a batch     | `detail.index`, `detail.error`.                                           |
| `400`  | Primary key field in a `PATCH` payload   | `detail.fields` lists the offending fields.                               |
| `400`  | Value outside a field's `options`        | `detail.invalid_options` maps field → rejected value.                     |
| `400`  | Unknown `fields` value                   | `detail.unknown_fields` lists the unknown fields.                         |
| `400`  | Unknown filter column                    | `detail.unknown_filter_column`.                                           |
| `400`  | Malformed `filters` JSON                 | `detail.invalid_filter`.                                                  |
| `400`  | Object with the same name already exists | On create object.                                                         |
| `404`  | Object id not found / other project      | Standard not-found.                                                       |
| `404`  | Object not deployed on the branch        | `detail.branch`.                                                          |
| `404`  | Instance missing or deleted              | —                                                                         |
| `409`  | Create with existing primary key         | `detail.key` is the existing `_key`.                                      |

***

## Not available yet

* Executing object actions via the API (`POST /{id}/instances/{key}/actions/{action}`).
* Backed objects (`object_type: BACKED`).
