Versioned documents. Hierarchical trees. Multi-tenant isolation. All in one API. Cloud hosted or deploy to your own infrastructure.
// npm install @wren/client import { WrenClient } from "@wren/client"; const wren = new WrenClient({ baseUrl: "https://…", apiKey: "wren_…" }); // 1. Documents — create in a collection const doc = await wren.documents.create("events", { name: "Masters 2026" }); // 2. Versions — every update creates a new one await wren.documents.update("events", doc.id, { name: "Masters 2026", champion: "Scheffler" }); await wren.labels.set("events", doc.id, "published"); // 3. Trees — attach to any path, fetch the whole branch in one call await wren.trees.set("site", "/2026/masters", doc.id); const bundle = await wren.trees.getFull("site", { label: "published" });
Features
Three primitives that compose. Pick the ones you need — they all come together.
POST any JSON object into a collection. Attach a JSON Schema later if you want validation. Bring binary assets along for the ride.
Every mutation creates a new version. Roll back, diff, or time-travel to any point. No extra setup.
Pin any version as published, draft, or staging. Serve different audiences from the same document.
Organise documents into named paths. Fetch whole subtrees with ?full=true. Public read URLs with zero config.
Each org gets its own Postgres schema. Isolation is structural — not a policy to misconfigure.
Start free on our cloud, or deploy to your own infrastructure with Docker. Bring your own Postgres. No vendor lock-in.
How it works
Each one is useful on its own — together they replace a week of plumbing.
POST any JSON object. Schema-free by default, or attach a JSON Schema when you’re ready to lock it down. Binary uploads are first-class.
Every write creates a version. Diff, roll back, or pin a label to serve a specific snapshot to your clients.
Organise documents into a named hierarchy. Fetch a single path, bundle a subtree, or expose the whole thing as public URLs.
API Reference
The full API is documented at /docs. Here’s the shape of it.
# Create a document curl -X POST /api/v1/events \ -d '{"name": "Masters 2026"}' # Update (creates version 2) curl -X PUT /api/v1/events/abc \ -d '{"name": "Masters 2026", "champion": "Scheffler"}' # Pin a label curl -X POST /api/v1/events/abc/labels \ -d '{"label": "published"}' # Attach to a tree path curl -X PUT /api/v1/tree/site/2026/masters \ -d '{"documentId": "abc"}' # Bundle the published snapshot of the whole site tree curl /api/v1/tree/site?full=true&label=published
Client Libraries
Documents, versions, labels, trees. Full types. Zero extra dependencies. Works in Node, Bun, and async Python.
npm install @wren/client
import { WrenClient } from "@wren/client"; const wren = new WrenClient({ baseUrl, apiKey }); // Documents const doc = await wren.documents.create("events", data); // Versions & labels const hist = await wren.versions.list("events", doc.id); await wren.labels.set("events", doc.id, "published"); // Trees await wren.trees.set("site", "/2026/masters", doc.id); const bundle = await wren.trees.getFull("site");
pip install wren-client
from wren import WrenClient, AsyncWrenClient # Sync — documents, versions, trees with WrenClient(base_url, api_key=key) as wren: doc = wren.documents.create("events", data) wren.labels.set("events", doc.id, "published") wren.trees.set("site", "/2026/masters", doc.id) # Async async with AsyncWrenClient(base_url, api_key=key) as wren: bundle = await wren.trees.get_full("site")
Pricing
Every plan includes the full API, Admin UI, versioning, labels, trees, and binary assets.
For personal projects and experiments.
For side projects and small teams.
For production workloads and compliance.