Skip to main content
Every write in KiwiFS becomes a git commit, authored by the request’s actor. These endpoints read that history: list a file’s commits, fetch an old version, diff two versions, see who wrote each line, or follow every change across the workspace. All paths are relative to http://localhost:3333/api/kiwi. Blame and some diff modes depend on the versioning strategy; see Versioning.

List file versions

Returns the commits that touched a file, newest first. GET /versions
string
required
File path.
string
The requested path.
object[]
Response
A file with no history returns an empty versions array.

Read a past version

Returns a file’s content as it was at a given commit. GET /version
string
required
File path.
string
required
Commit hash, full or abbreviated.
Response
The body is text/markdown. Returns 404 if the file did not exist at that commit.

Diff two versions

Returns a unified diff of one file between two commits, as plain text. GET /diff
string
required
File path.
string
required
Older commit hash.
string
required
Newer commit hash.
string
default:"line"
line for a unified diff or word for a word-level diff ([-removed-]{+added+} markers).
Response
Returns 400 for any other granularity and 501 when the versioning strategy cannot produce a word diff.

Blame

Returns the commit, author, and date that last changed each line of a file. GET /blame
string
required
File path.
string
The requested path.
object[]
Response
Blame needs the git strategy. Copy-on-write and noop strategies return 501. An uncommitted file returns an empty lines array.
author is the X-Actor (or the key’s actor) from the original write, so blame shows which agent wrote each section.

Change feed

Lists recent commits across the whole workspace, newest first. Use it to sync external systems: poll with the last hash you saw, or long-poll to wait for the next change. GET /changes
string
Commit hash. Returns only commits after it. Omit to get the latest commits.
integer
default:"50"
Maximum changes to return, up to 500.
string
Set to longpoll to hold the request open until a change arrives when there are none yet.
string
default:"30s"
How long a long-poll waits, as a Go duration. Capped at 120s. Returns an empty list on timeout.
object[]
string
Hash of the newest change in this response. Pass it as since next time. Empty when there are no changes.
Response
Returns 400 with unknown sequence when since is not a known commit, and 503 if the long-poll subscriber limit is reached. For a push stream instead of polling, use Server-Sent Events.

Optimistic concurrency

Use ETags and If-Match to avoid lost updates.

Versioning concepts

Git, copy-on-write, and noop strategies.

Real-time events

Subscribe to changes over SSE.

Drafts

Stage changes on a branch.
Last modified on October 19, 2026