Skip to main content
File endpoints are the core of the API. Every write goes through the write pipeline: it lands on disk, becomes a git commit, updates the search index, and is broadcast to SSE subscribers. All paths below are relative to http://localhost:3333/api/kiwi unless they start with /raw. File paths in ?path= are relative to the knowledge root; paths that escape the root or point into hidden directories return 400.

Get the directory tree

Returns the folder hierarchy as a nested object, up to 20 levels deep. GET /tree
string
default:"/"
Folder to start from.
string
Path relative to the root.
string
File or folder name.
boolean
true for folders.
integer
File size in bytes. Omitted for folders.
Public URL for the file. Present only for files when a public URL is configured.
object[]
Nested entries with the same shape. Omitted when empty.
Response
Returns 404 if the folder does not exist.

Read a file

Returns the raw file bytes with an ETag you can use for conditional writes. GET /file
string
required
File path.
boolean
default:"false"
Return only the parsed frontmatter as a JSON object.
Rewrite wiki links to absolute URLs. Requires a configured public URL.
string
default:"api"
Label stored with the page view in analytics. Also accepted as the X-Kiwi-Source header.
string
ETag from an earlier read. Returns 304 when it still matches.
string
HTTP date. Returns 304 when the file has not changed since.
Response
Response headers: Returns 404 if the file does not exist.

Write a file

Creates or replaces a file. The request body is the full file content, up to 32 MB. PUT /file
string
required
File path. Parent folders are created as needed.
string
ETag the file must still have. Returns 409 on mismatch.
string
default:"anonymous"
Commit author.
string
type:id pair appended to the page’s derived-from frontmatter list, for example run:run-249.
string
Send application/x-symlink to create a symbolic link whose target is the body.
string
Path written.
string
New ETag (also in the ETag header).
Response
A symlink write returns {"path": "latest.md", "type": "symlink"}.

Patch frontmatter

Merges fields into a page’s YAML frontmatter and leaves the body byte-for-byte unchanged. Two equivalent routes exist.
The body wraps the fields in a fields object.
string
required
Markdown file to update. Must already exist.
boolean
default:"false"
Take over keys that another field manager owns.
string
ETag the file must still have.
string
Name that owns the keys you set. Another manager changing an owned key gets 409 unless it sends force=true.
string
default:"anonymous"
Commit author.
Response
When a key belongs to another manager, nothing is written and the response lists the conflicts:
409 Conflict
Returns 400 for a non-markdown file or an empty field map, and 404 if the file does not exist.

Append to a file

Adds content to the end of a file without a read-modify-write cycle. Creates the file if it does not exist. POST /file/append
string
required
File path.
string
default:"\\n"
Inserted between the existing content and the new content.
string
default:"anonymous"
Commit author.
Response
Use append for agent logs, episodic memory, and append-only files. The body limit is 32 MB.

Delete a file

Deletes a file and records the deletion as a commit. DELETE /file
string
required
File path.
string
default:"anonymous"
Commit author.
Response
Returns 404 if the file does not exist.

Bulk write

Writes several files in one git commit. If any file fails a check, nothing is written. POST /bulk
object[]
required
Files to write.
string
Commit author. Falls back to X-Actor.
string
Commit message.
string
type:id pair added to every file’s derived-from list.
integer
Number of files written.
object[]
path and new etag for each file.
Response

Rename a file

Moves a file and rewrites every wiki link and markdown link that points to it, in one commit. POST /rename
string
required
Current path.
string
required
New path. Must not exist unless overwrite=true.
Set false to move the file and leave references as written.
boolean
default:"false"
Replace an existing destination, like rename(2). Meant for protocol clients that save by writing a temp file and renaming it over the original.
string
default:"anonymous"
Commit author.
string
Original path.
string
New path.
string
ETag of the moved file.
Other pages whose links were rewritten. Omitted when none changed.
Response
Returns 404 if the source does not exist and 409 if the destination exists or a link could not be kept pointing at the file.

Rename a folder

Moves a folder, rewrites links into it from elsewhere, and fixes relative links inside it, in one commit. POST /rename-dir
string
required
Current folder.
string
required
New folder. No destination file may exist.
Set false to leave references as written.
Response
renamed is the number of files moved. For multi-file moves and merges with a review step, see Refactor.

Upload an asset

Uploads an image, video, audio file, or PDF as multipart form data and returns a ready-to-paste markdown link. POST /assets
string
Folder to store the file in, for example assets/diagrams. Defaults to the root.
file
required
The file (multipart field name file). Hidden names starting with . are rejected.
string
default:"anonymous"
Commit author.
string
Stored path.
string
Embed (![]()) for images, video, and audio; a link for other types.
string
Detected MIME type.
integer
Size in bytes.
string
ETag of the stored file.
Response
The default limit is 100 MiB and the default allowlist covers common image, video, and audio types plus PDF. Override both with [assets] max_file_size and allowed_types. Too large returns 413; a type outside the allowlist returns 415.

Serve a raw file

Serves file bytes at a stable URL for <img>, <video>, and <iframe> tags. The web UI uses it for every embedded asset. GET /raw/{path} (also GET /api/kiwi/raw/{path} and GET /api/kiwi/{space}/raw/{path} for non-primary spaces)
string
required
File path, URL-escaped per segment.
string
Expiry from GET /raw-sign.
string
Signature from GET /raw-sign.
When auth is on, a request needs one of:
  • An Authorization header that passes normal auth (key scopes apply to the file path).
  • A valid exp and sig pair. An invalid or expired signature returns 403.
  • A target that is already public: a branding logo or favicon, a page with visibility: public or that is published, or an asset next to such a page.
Spaces with visibility = "public" or "unlisted" serve raw files without credentials. Responses include X-Content-Type-Options: nosniff, and SVGs get a restrictive Content-Security-Policy. Use GET /file instead when you need an ETag.

Sign a raw file URL

Returns a short-lived /raw/ URL that works without an Authorization header, for clients that can’t send one. GET /raw-sign
string
required
File path.
string
Normalized path.
string
Signed URL, relative to the server root.
string
Expiry time (RFC 3339).
Response
A signed URL stays valid for 30 to 60 minutes. Signatures are per space and do not survive a server restart.

Get a table of contents

Returns a page’s headings with anchor slugs. GET /toc
string
required
Markdown file.
Response
Rewrites [[wiki links]] in a markdown string to absolute URLs, for rendering content outside KiwiFS. POST /resolve-links
string
required
Markdown to rewrite.
Response
Without a configured public URL, the content comes back unchanged. To resolve links while reading a file, use GET /file?resolve_links=true.

List page templates

Returns the markdown templates in .kiwi/templates/, sorted by name. GET /templates
Response
Returns an empty templates array when the folder does not exist. See Templates.

Read a page template

Returns one template’s content. GET /template
string
required
Template name without .md.
Response
Returns 404 if the template does not exist and 400 for a name containing /, \, or ... Returns the target of a symbolic link as plain text, without following it. GET /readlink
string
required
Symlink path.
Response
Returns 404 if the path does not exist and 400 if it is not a symlink.

Versioning

History, diff, and blame for any file.

Utilities

Peek, sections, lint, and more.

Drafts

Stage file changes on a branch before merging.

Wiki links

How links resolve and get rewritten on rename.
Last modified on October 19, 2026