Documentation
On this page

Objects and links

Create, read, change, query, and delete objects; follow and change links.

Objects are addressed by their type’s api_name and their id. Every endpoint here needs view_objects on the type; writes also need edit_objects on it. A restricted type you cannot view is 404, as is an object of another type.

The object

JSON
{
  "id": "o4b8j2e6c0t1q5w9r3y7u2i6",
  "type": "employee",
  "properties": { "name": "Ada", "email": "ada@acme.example", "started": "2026-01-05" },
  "version": 1,
  "etag": "q8XyZ3bKp1mWc0rT5vNa2g",
  "validation": { "state": "valid", "rules_version": 3 },
  "created_by": "h3jd8s0q2l5x7c1v9b4n6m8k",
  "updated_by": "h3jd8s0q2l5x7c1v9b4n6m8k",
  "created_at": "2026-10-24T10:00:00Z",
  "updated_at": "2026-10-24T10:00:00Z"
}

version starts at 1 and grows with every change to a property you can see; etag identifies that state exactly. Both, updated_at, updated_by and validation are per reader: a change to a property you cannot see changes none of them. Schema changes do not change them. validation is where the object stands against its type’s current rules: valid, invalid (with errors, each a path and a message), or pending until the background job has checked it; see Versions and schema changes. A write always leaves the object valid.

properties holds only the properties you may see. A restricted property you may not see is absent from every object, filter and sort here, and a write naming it is refused as for a property that does not exist; one you may see but not write may be sent back unchanged.

Objects of a team type are teams. Creating one creates the team, changing its name renames it (409 if another team has the name), and deleting it deletes the team.

Pages

Lists and queries return a page:

JSON
{ "data": [ { "id": "o4b8j2e6c0t1q5w9r3y7u2i6", "type": "employee", "...": "..." } ],
  "next_cursor": "eyJrIjpbIjIwMjYtMTAtMjRUMTA6MDA6MDBaIiwi..." }

next_cursor is null on the last page. Pass it back as cursor with the same ordering to get the next one.

Objects

GET /v1/ontology/objects/{type}

AuthfullPermissionview_objects on the type

Lists objects. Query parameters, all optional:

Parameter
limit1-500, default 50
cursornext_cursor of the previous page
order_bya scalar property, or $id, $created_at, $updated_at (your updated_at, from the properties you see; default: $id)
directionasc (default) or desc
Shell
curl "$BASE/v1/ontology/objects/employee?order_by=started&direction=desc&limit=20" \
  -H "Authorization: Bearer $TOKEN"

POST /v1/ontology/objects/{type}

AuthfullPermissionview_objects and edit_objects on the type

JSON
{ "properties": { "name": "Ada", "email": "ada@acme.example", "started": "2026-01-05" } }

201 with the object. The properties are checked against the type’s current definition, then its custom validators.

  • 422 validation_failed, one details entry per problem (path, message): missing required properties, unknown properties, wrong types, broken rules, unknown user or file ids, failed validators.
  • 409 if a unique value is taken (the message names the property).
  • 503 validators_unavailable if the type uses validators and no sandbox is configured.

POST /v1/ontology/objects/{type}/query

AuthfullPermissionview_objects on the type

Queries with a filter tree. All fields are optional.

JSON
{
  "filter": {
    "op": "and",
    "filters": [
      { "op": "in", "property": "name", "values": ["Ada", "Grace", "Alan"] },
      { "op": "not", "filter": { "op": "is_null", "property": "email" } },
      { "op": "gte", "property": "started", "value": "2026-01-01" }
    ]
  },
  "order_by": { "property": "$created_at", "direction": "desc" },
  "limit": 100,
  "cursor": null
}

Returns a page. The operators are listed in The ontology; they apply to top-level properties. 400 for a filter that does not fit the type (an unknown property, a value of the wrong type, an ordering on a non-scalar property) or exceeds the limits (100 conditions, 10 levels, 500 in values).

linked filters by links: { "op": "linked", "link": "projects", "object": "<project id>" } finds the objects linked to that project through this type’s end named projects. { "op": "validation", "state": "invalid" } finds the objects that fail the type’s current rules, by the state you are shown: a problem with a property you cannot see does not count.

GET /v1/ontology/objects/{type}/{id}

AuthfullPermissionview_objects on the type

The object.

PATCH /v1/ontology/objects/{type}/{id}

AuthfullPermissionview_objects and edit_objects on the type

Merges properties into the stored ones (null removes a property) and checks the result. expected_version, the object’s version or its etag as you read it, makes the change conditional. Prefer the etag: it stays exact when your grants change, while the version can then jump or go backwards.

JSON
{ "properties": { "email": "ada@analytical.example", "started": null },
  "expected_version": "q8XyZ3bKp1mWc0rT5vNa2g" }

Returns the object at its new version. A change to a property you cannot see is not a conflict. A write that changes no value writes nothing and returns the object as it was. Errors as for creation, plus 409 if the object is no longer at expected_version.

DELETE /v1/ontology/objects/{type}/{id}

AuthfullPermissionview_objects and edit_objects on the type

Deletes the object, at once: it and its links disappear from every read (one link.deleted event per link) and its unique values are free. The rows are removed in the background. 204.

AuthfullPermissionview_objects on both types

The objects linked to this one through its link end named link (a link type’s forward_name from the source type, reverse_name from the target type), as a page. limit and cursor work as for lists. 404 if the end does not exist or leads to a type you cannot view.

Shell
curl "$BASE/v1/ontology/objects/employee/o4b8j2e6c0t1q5w9r3y7u2i6/links/projects" \
  -H "Authorization: Bearer $TOKEN"

AuthfullPermissionview_objects and edit_objects on both types

Links the source object from to the target object to with the link type link (its api_name). Idempotent: 201 when created, 200 when the link existed. 409 if the link type’s cardinality does not allow it (the message names the cardinality; links of deleted objects do not count); 404 if either object is not of the declared type. For a team hierarchy, 409 if the link would close a cycle; as for any link, it needs edit access to both teams.

Shell
curl -X PUT "$BASE/v1/ontology/links/works_on/o4b8j2e6c0t1q5w9r3y7u2i6/o9k3m7p1s5v2x6z0b4d8f2h6" \
  -H "Authorization: Bearer $TOKEN"

AuthfullPermissionview_objects and edit_objects on both types

Removes the link. 204; 404 if it did not exist.

Esc
↑ ↓ navigate↵ open