Skip to main content

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".
See Overview → Branching for the full model.

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.
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"
}
FieldTypeDescription
metadataobjectThe object definition (YAML reference, as JSON). Fully validated.
projectstringId of the project to create the object in.
branchstring(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 or List objects for the definition and its status.
  • 400 if an object with the same name already exists in the project.

Update object

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 supportedmetadata.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_MIGRATIONREADY); metadata/settings-only changes apply in place.
  • Response: 200, no body. Poll Get object for the updated definition and status.

Delete object

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

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.
# Objects of one project, with their feature-x definitions
GET /knowledge-object/list?filters=[project.$id][$eq]:6748d8b66a5a2ac9f0d39326&branch=feature-x
{ "total_count": 3, "items": [ { "id": "…", "name": "Employee", "branches": ["main"], "definition": { } } ] }
Only objects deployed on the selected branch are returned.

Get object

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.
{
  "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

GET /knowledge-object/{id}/instances?page=1&page_size=50&branch=main
ParamTypeDefaultDescription
pageint1Page number.
page_sizeint50Rows per page.
branchstringmainBranch to read from.
fieldsrepeated string(all)Column selection.
filtersrepeated JSON(none)Row filtering.
{
  "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.
GET /knowledge-object/{id}/instances
    ?filters={"column":"is_active","operator":"equal","value":true}
    &filters={"column":"salary","operator":"greater_than","value":50000}
operatorMeaning
equalcolumn = value
not_equalcolumn ≠ value
greater_thancolumn > value
less_thancolumn < value
containscase-sensitive substring match
not_containsnegated 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

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).
{ "_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.
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 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). 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.
{ "created": 2, "updated": 1, "total": 3 }
To retrieve the resulting instances (with their _keys), read them back via List.

Get instance

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).
{
  "_key": "AB12...",
  "id": 5,
  "name": "Acme",
  "owner": "9F3C...",
  "_relationships": {
    "owner": { "_key": "9F3C...", "id": 1, "name": "John", "email": "j@acme.com" }
  }
}

Instance history

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).
[
  { "_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.
For objects with store_versions: false, superseded versions may be compacted away over time — history is best-effort in that mode.

Update instance

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

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

StatusWhenDetail
400Definition not READY on the branchInstance operations require a completed migration.
400Payload fails validationdetail.errors carries the validation message (detail.index on batch).
400Batch larger than 1000 itemsdetail.max_batch_size, detail.received.
400Duplicate primary key within a batchdetail.index, detail.error.
400Primary key field in a PATCH payloaddetail.fields lists the offending fields.
400Value outside a field’s optionsdetail.invalid_options maps field → rejected value.
400Unknown fields valuedetail.unknown_fields lists the unknown fields.
400Unknown filter columndetail.unknown_filter_column.
400Malformed filters JSONdetail.invalid_filter.
400Object with the same name already existsOn create object.
404Object id not found / other projectStandard not-found.
404Object not deployed on the branchdetail.branch.
404Instance missing or deleted
409Create with existing primary keydetail.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).