Memory API
How to use the Quotient SDK to read and write Memory programmatically
Prerequisites
Before you begin, ensure you have:
- A Quotient account with a private API key
- The
MEMORY_READand/orMEMORY_WRITEscopes enabled on your key - Installed the Quotient Server SDK (
@quotientjs/server)
Overview
Quotient exposes its memories via API, making it easy to integrate with other systems and agents. For example, you can fetch Quotient's marketing-related memories inside of a coding agent to help it write better copy for your website. Or you can go in the opposite direction — you can have your AI personal assistant create memories directly in Quotient, or you can set up an integration to write to Quotient's memory from your company knowledge store.
The Memory API models your content as a path-aware filesystem. Content is stored internally as Quotient Rich Text but the SDK uses markdown as the wire format for simplicity.
All paths start with /. The SDK provides separate ls and cat methods
with unambiguous return types — no need to check what you got back.
Reading Memory
List folder contents (ls)
import { QuotientServer } from "@quotientjs/server"
const quotient = new QuotientServer({ privateKey: process.env.QUOTIENT_PRIVATE_KEY })
// List direct children of root
const root = await quotient.memory.ls({ path: "/" })
// root.items → [{ type: "folder", name: "projects", path: "/projects/", ... }, ...]
// List direct children of a specific folder
const projects = await quotient.memory.ls({ path: "/projects" })
// Get full recursive tree
const tree = await quotient.memory.ls({ path: "/", deep: true })
// tree.items → nested structure with children arrays
Read a document (cat)
const doc = await quotient.memory.cat({ path: "/projects/budget" })
// doc.title → "Budget"
// doc.content → "# Q1 Budget\n\nTotal: $50,000\n..."
// doc.updatedAt → "2024-01-15T10:30:00.000Z"
Calling cat on a folder path returns a 400 error. Calling ls on a document
path returns a 400 error. Each method has a single, unambiguous return type.
Writing Memory
Create or update a document
// Upsert — creates if missing, updates if exists
// Parent folders are auto-created
const doc = await quotient.memory.write({
path: "/projects/budget",
title: "Budget",
content: "# Q1 Budget\n\nTotal: $50,000",
})
Create a folder
const folder = await quotient.memory.mkdir({
path: "/projects",
name: "Projects",
})
Deleting Memory
Archive a document
await quotient.memory.rm({ path: "/projects/budget" })
Archive a folder (cascading)
// Archives the folder and all its contents
await quotient.memory.rm({ path: "/projects" })
Path Type Safety
The SDK uses the Path type (/${string}) for compile-time path
validation. All paths must start with /:
import type { Path } from "@quotientjs/core"
// TypeScript will enforce the leading slash
const path: Path = "/projects/budget" // OK
// const path: Path = "projects/budget" // Error
Example: Next.js ISR Integration
Here's an example showing how the Memory API can be used in a Next.js app with Incremental Static Regeneration. This is just one way to consume the API — it works with any server-side TypeScript environment.
// app/docs/[...path]/page.tsx
import { QuotientServer } from "@quotientjs/server"
import type { Path } from "@quotientjs/core"
const quotient = new QuotientServer({
privateKey: process.env.QUOTIENT_PRIVATE_KEY!,
baseUrl: process.env.BASE_URL,
})
export const revalidate = 60
export default async function DocPage({
params,
}: {
params: Promise<{ path: string[] }>
}) {
const { path } = await params
const memoryPath = ("/" + path.join("/")) as Path
// Try as document first, fall back to folder listing
try {
const doc = await quotient.memory.cat({ path: memoryPath })
return <pre>{doc.content}</pre>
} catch {
const listing = await quotient.memory.ls({ path: memoryPath })
return (
<ul>
{listing.items.map((item) => (
<li key={item.path}>{item.name}</li>
))}
</ul>
)
}
}
API Reference
memory.cat(options)
| Parameter | Type | Description |
|---|---|---|
path | Path | Document path |
Returns: CatMemoryResponse — { title, path, content, updatedAt, createdAt }
Returns 400 if path is a folder. Returns 404 if path doesn't exist.
memory.ls(options)
| Parameter | Type | Description |
|---|---|---|
path | Path | Folder path |
deep | boolean? | If true, returns recursive tree with nested children |
Returns: LsMemoryResponse — { items: MemoryFolderItem[] }
Returns 400 if path is a document. Returns 404 if path doesn't exist.
memory.write(options)
| Parameter | Type | Description |
|---|---|---|
path | Path | Document path |
title | string? | Document title (derived from path if omitted) |
content | string | Markdown content |
Returns: WriteMemoryResponse
memory.mkdir(options)
| Parameter | Type | Description |
|---|---|---|
path | Path | Folder path |
name | string? | Folder name (derived from path if omitted) |
Returns: MkdirMemoryResponse
memory.rm(options)
| Parameter | Type | Description |
|---|---|---|
path | Path | Path to archive (auto-detects document vs folder) |
Returns: RmMemoryResponse — { success: boolean }
Scopes
| Scope | Required for |
|---|---|
MEMORY_READ | memory.cat(), memory.ls() |
MEMORY_WRITE | memory.write(), memory.mkdir(), memory.rm() |
Memory scopes are available on private keys only. Documents created via the SDK are visible in the Quotient web UI, and vice versa.