Skip to main content
Version: 0.3.36

Nodes API

Read and write nodes at /api/repository/{repo}/{branch}/head/{workspace}/{path}. {path} is the node's path inside the workspace without the leading slash; the trailing-slash form .../{workspace}/ addresses the workspace root.

Node object

{
"id": "fzpbHQs6kHJjK246z4n6a",
"name": "hello-world",
"path": "/articles/hello-world",
"node_type": "raisin:Page",
"archetype": null,
"properties": {"title": "Hello World", "status": "draft", "$supertypes": ["raisin:Page"], "$mixins": []},
"parent": "articles",
"order_key": "",
"has_children": false,
"version": 1,
"created_at": "2026-09-06T18:33:43.132065Z",
"updated_at": "2026-09-06T18:33:43.151412Z",
"created_by": "system",
"updated_by": "system",
"published_at": null,
"published_by": null,
"translations": null,
"workspace": "content",
"owner_id": null,
"relations": []
}

$supertypes and $mixins are added on read from the node's type.

Create

POST /api/repository/{repo}/{branch}/head/{workspace}/{parent_path}
POST /api/repository/{repo}/{branch}/head/{workspace}/ (at the root)
{
"name": "hello-world",
"node_type": "raisin:Page",
"properties": {"title": "Hello World"},
"commit": {"message": "Add hello world", "actor": "alice"}
}

commit is optional. name becomes the last path segment (sanitized). The node type must be in the workspace's allowed_node_types (and allowed_root_node_types for root creation).

Response 201. Under a parent the node is returned in a commit envelope, {"node": {...}, "revision": "1788719623132-0", "committed": true}; at the root the bare node is returned.

Read

GET /api/repository/{repo}/{branch}/head/{workspace}/{path}
GET /api/repository/{repo}/{branch}/head/{workspace}/$ref/{id}
GET /api/repository/{repo}/{branch}/head/{workspace}/ (root listing)
GET /api/repository/{repo}/{branch}/head/{workspace}/{path}@{property}

Query parameters:

ParameterEffect
level=NReturn descendants to depth N instead of the node
deep=trueReturn the whole subtree
flatten=trueFlatten a subtree into a list
format=arrayChildren as an array (default is a map keyed by name)
cursor, limitKeyset pagination for listings; limit defaults to 100, max 1000
lang=xxResolve translations for a locale
command=downloadStream an asset's bytes as an attachment
command=displayStream an asset's bytes inline
revision=NRead at an older revision (or use the rev/ route below)

A node the caller cannot read returns 404, the same as a missing node.

Update

PUT /api/repository/{repo}/{branch}/head/{workspace}/{path}
{"properties": {"title": "Hello World", "status": "published"}, "commit": {"message": "Publish", "actor": "alice"}}

properties replaces the stored properties. translations may be included. Returns the updated node (200), or the commit envelope when commit is present.

To set a single property, address it with @ and send the value as the JSON body:

PUT /api/repository/{repo}/{branch}/head/{workspace}/{path}@title
"Hello Again"

Response: {"status": "property updated"}.

Delete

DELETE /api/repository/{repo}/{branch}/head/{workspace}/{path}

Response: {"deleted": true}.

Commands

Structural operations are POST requests to the node path with the command as the last segment, .../{path}/raisin:{command}. They cover move, rename, copy, publish, reorder, relations and translations; the JavaScript client's Node Operations wraps them. Two are commonly called directly:

Sign an asset URL

POST /api/repository/{repo}/{branch}/head/{workspace}/{path}/raisin:sign
{"command": "download", "expires_in": 600}
{"url": "/api/repository/myapp/main/head/content/site/index.html/raisin:download?sig=HATkBlR...&exp=1788720991", "expires_at": "2026-09-06T18:56:31+00:00"}

The returned URL serves the bytes without a token until exp. command is download or display.

Upload bytes

Multipart POST to an asset node path stores the file on that node. For large files use the resumable upload endpoints.

Time travel

GET /api/repository/{repo}/{branch}/rev/{revision}/{workspace}/{path}
GET /api/repository/{repo}/{branch}/rev/{revision}/{workspace}/$ref/{id}
GET /api/repository/{repo}/{branch}/rev/{revision}/{workspace}/

{revision} is a revision id such as 1788719623132-0, as returned by a commit or listed under /api/management/repositories/{tenant}/{repo}/revisions.

Revision history

Lists a node's own revisions, newest first, independent of the NodeType's auditable flag.

GET /api/history/{repo}/{branch}/{workspace}/by-id/{id}?limit=50
GET /api/history/{repo}/{branch}/{workspace}/{path}?limit=50
[
{"revision": "1788720442090-0", "updated_at": "…", "updated_by": "admin", "deleted": false, "message": "publish", "is_system": false}
]

Use revision with the rev/ route to fetch the full snapshot.

Audit log

Audit entries are recorded only for NodeTypes with auditable: true (see NodeTypes).

GET /api/audit/{repo}/{branch}/{workspace}/by-id/{id}
GET /api/audit/{repo}/{branch}/{workspace}/{path}
[{"action": "Update", "user_id": "alice", "timestamp": "…", "path": "/content/page", "details": null}]

History and audit reads go through row-level security: you only see entries for nodes you can read.