Skip to main content
The KiwiFS REST API gives you read and write access to a markdown filesystem over HTTP. Everything the web UI does goes through these endpoints, and most MCP tools have a REST equivalent.

Base URL

Every knowledge endpoint lives under /api/kiwi/. Health, metrics, OpenAPI, raw files, llms.txt, and MCP sit at the server root.

Selecting a space

A server can host several spaces. Pick one in either of two ways:
The header takes precedence over the path. An unknown name in X-Kiwi-Space returns 404 instead of falling back to another space. Requests with neither go to the primary space. Space administration (/api/spaces) is covered in Spaces admin.

Authentication

Set the mode with [auth] type in .kiwi/config.toml. Every mode except none expects an Authorization: Bearer <token> header on /api/kiwi/* requests.
No credentials. Use this for local development and trusted networks.
Send SIGHUP to the server process to reload [auth] from disk without a restart. See Auth tokens for key management.

What auth covers

/mcp only checks credentials in apikey mode, using the same key. With perspace or oidc, put /mcp behind your proxy’s auth or disable it.

Request headers

Set X-Actor on every write when you use none or apikey auth. It becomes the git commit author, so you can trace which agent changed what with blame.

Optimistic concurrency

Every file read returns an ETag header: the quoted git blob hash of the content. Writes return the new ETag in both the ETag header and the JSON etag field. Send that value back in If-Match to make a write conditional. If someone else changed the file since your read, the write is rejected with 409 and nothing is written.
409 Conflict
If-Match works on PUT /file, PATCH /file, and PATCH /file/frontmatter. For POST /bulk, set if_match per file; one mismatch fails the whole batch. Quotes around the ETag are optional.

Errors

Errors return a JSON body with a single error field. Server-side failures (5xx) return a generic message; details go to the server log.

Pagination

There is no global pagination envelope. Endpoints that return long lists take their own parameters:

Rate limiting

Rate limiting is off unless you set requests_per_minute above zero:
.kiwi/config.toml
KiwiFS then applies a token bucket per bearer token (hashed) or per client IP for anonymous requests. /health, /healthz, /readyz, and /metrics are never limited. Over the limit, requests get 429 with Retry-After: 60.

Health and metrics

Use these unauthenticated endpoints for container probes and monitoring.
GET /health always returns {"status": "ok"}. GET /healthz adds uptime and version:
GET /readyz checks storage and any enabled protocol servers (NFS, S3, WebDAV). It returns 200 with status: "ready", or 503 with status set to storage-unreachable or protocol-unhealthy.
503 Service Unavailable
GET /metrics returns Prometheus text with kiwi_build_info, kiwi_uptime_seconds, kiwi_sse_subscribers, and kiwi_janitor_issues (after the first janitor scan). It does not export per-request counters; collect those at your proxy.

Machine-readable references

Next steps

Files

Read, write, rename, and upload.

Search

Full-text, hybrid, and semantic search.

Versioning

History, diff, blame, and the change feed.

Metadata and graph

DQL queries and the link graph.

Drafts

Staging branches for agents.

Utilities

Lint, timeline, rules, audit.
Last modified on October 19, 2026