# Authentication and API Keys
Source: https://docs.memorylake.ai/authentication
One API key authenticates the REST API, Model Router, and agent plugins — how to create, use, and manage keys
## One Key, Every Surface
MemoryLake uses API keys (`sk-…`) as the credential for all programmatic access. The same key authenticates:
| Surface | Base URL | Auth header |
| - | - | - |
| MemoryLake REST API | `https://app.memorylake.ai/openapi/memorylake` | `Authorization: Bearer sk-…` |
| Model Router (OpenAI-compatible) | `https://app.memorylake.ai/v1` | `Authorization: Bearer sk-…` |
| Model Router (Claude-native) | `https://app.memorylake.ai/claude/v1` | `x-api-key: sk-…` |
| Model Router (Gemini-native) | `https://app.memorylake.ai/gemini/:version` | `x-goog-api-key: sk-…` |
| Memory Router (private preview) | `https://app.memorylake.ai/openai/v1` · `…/anthropic/v1` | native header, see [Memory Router](/features/memory-router/quickstart) |
| Agent plugins (OpenClaw / QClaw / Hermes) | configured once during install | plugin config `apiKey` |
| MCP clients | `https://app.memorylake.ai/memorylake/mcp/v2` | OAuth2 — no key needed |
MCP clients don't use API keys at all — they authorize with OAuth2 and pick their scope on the consent screen. See [Connect via MCP](/features/memorylake/mcp-servers/creating-api-keys).
## Creating an API Key
1. Open **API Keys** in the [console](https://app.memorylake.ai) sidebar
2. Click create and fill in:
* **Name** — for your own reference, changeable later
* **Expiry** — Never / 7 days / 30 days (default) / 90 days / 1 year / custom date
* **Advanced → Group** — optional model-access group, when your account has more than one
3. Copy the revealed `sk-…` key immediately — it is shown in full **only once**
Store keys in a password manager or environment variables. Never commit them to version control or share them in chat. If a key leaks, **rotate** it from the key's detail panel — rotation issues a new secret without recreating your configuration.
## What a Key Can Do
An API key inherits the permissions of the member who created it. In your personal space that means full access to your own resources; in a team space, a key can do exactly what its creator's role and [resource scopes](/features/team-collaboration/permission-reference) allow — no more.
Per-key controls available from the key detail panel:
* **Enable / disable** — suspend a key without deleting it
* **Rotate** — replace the secret, keep the key's identity
* **Model restrictions** — limit which models the key may call
* **IP allowlist** — restrict usage to known addresses
* **Heartbeat** — optionally require periodic liveness signals for long-running automation
Key states: **enabled**, **disabled**, **expired**, and **exhausted** (quota depleted). Requests with a key in any non-enabled state are rejected.
## Using Your Key
```bash MemoryLake REST API theme={null}
curl https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces \
-H "Authorization: Bearer sk-your-key"
```
```bash Model Router (OpenAI-compatible) theme={null}
curl https://app.memorylake.ai/v1/chat/completions \
-H "Authorization: Bearer sk-your-key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "hi"}]
}'
```
```bash Model Router (Claude-native) theme={null}
curl https://app.memorylake.ai/claude/v1/messages \
-H "x-api-key: sk-your-key" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "hi"}]
}'
```
The console's API Keys page always shows your current **API base address** with a copy button, plus setup guides for common integrations.
## Personal vs. Team Context
Keys are created within a space — personal or team. A key created in a team space operates in that team's context: its calls draw on team quota and see team resources (per the creator's permissions). Check which space you are in (sidebar space switcher) before creating keys for automation.
## Troubleshooting
* **`401 Unauthorized`** — key missing, mistyped, disabled, or expired. Verify the exact header format for the surface you're calling (table above).
* **Quota errors** — the account or team balance is insufficient; check **Billing** in the console.
* **Model not available** — the key's group or model restrictions exclude that model; list available models first (see [Model Router](/features/model-router/list-available-models)).
## Limitations and Notes
* API keys are the only programmatic credential — console login sessions cannot call the APIs.
* A key's permissions track its creator: if the creator's role is downgraded or they leave the team, the key's access changes accordingly.
# Core Concepts
Source: https://docs.memorylake.ai/concepts
The vocabulary of MemoryLake — and how individual and organizational memory fit together
MemoryLake models memory the way organizations actually work: knowledge has an **owner**, a **scope**, and a **source**. This page is the short orientation; each concept links to its deep dive.
You don't need to set any of this up by hand. When you sign up, MemoryLake automatically provisions a workspace and assistant for you — these concepts become useful as your usage grows from "my personal memory" to "my team's memory" to "memory inside my product."
## The Hierarchy
```text theme={null}
Workspace ← top-level container and isolation boundary
├── Project ← a focused body of knowledge
│ ├── Documents ← files whose content is parsed and indexed
│ ├── Conversations ← message exchanges memory is extracted from
│ ├── Project Facts ← knowledge scoped to this project
│ └── Open Data ← subscribed external datasets
├── Actors ← who memories belong to (people and assistants)
│ └── Actor Facts ← per-person memory, follows them across projects
└── Agents ← AI assistants operating in this workspace
```
Isolation boundaries, knowledge containers, and multi-tenant patterns.
Identities, project facts vs. actor facts, and per-user memory.
How documents and conversations become searchable memory.
## Individual Memory and Organizational Memory
The same machinery serves two different kinds of knowledge, and knowing which you're building matters more than any API detail.
| | Individual memory | Organizational memory |
| - | - | - |
| Belongs to | A person, across every tool they use | A team, in a shared workspace |
| Examples | "Prefers TypeScript", "allergic to shellfish", "working on the marathon plan" | "Refund window is 30 days", "Customer X renews in March", "we chose Postgres because…" |
| Lives as | Actor facts (follow the person across projects) | Project facts (scoped to the shared body of knowledge) |
| Governed by | The person's own workspace — private | Roles, fine-grained permissions, and per-resource scopes |
| The worry it solves | "Will my tools remember me?" | "Will knowledge survive people leaving?" |
Both flow through the same pipeline — extraction, source traces, conflict checking, retrieval. The difference is scope and governance. See the [Personal AI Memory](/scenarios/personal-ai-memory) and [Team Knowledge Base](/scenarios/team-knowledge-base) scenarios.
## Memory Hygiene: Traces and Conflicts
Two properties make memory trustworthy enough to build on:
* **Source traces** — every memory links back to the conversation or document it came from. When an assistant asserts something, you can always answer *"how do you know that?"* Available in the console and via the trace API.
* **Conflict detection** — when a new memory contradicts an existing one (a moved deadline, a changed policy), MemoryLake flags a **conflict** for review instead of silently keeping both. In teams, whoever holds the resolve permission decides what's true.
See [Memories](/features/memorylake/memories/overview) for how both work in practice.
## Open Data
**Open Data** is curated external knowledge you subscribe a project to — research and academic sources, clinical trials, drug databases, financial markets, company fundamentals, economic indicators, patents, and more. Subscribed categories become searchable by agents alongside your own content, so a biotech project can cite PubMed while a fintech project cites SEC filings.
## Boundary (Memory Router & MCP)
A **boundary** is the memory scope used by API traffic and MCP clients. It binds a workspace, project(s), and actors into a single reference:
* With [Memory Router](/features/memory-router/overview), you pass it as `?boundary_id=` on LLM calls — commonly one boundary per end user, so each user's conversations read and write only their own memory.
* With [MCP](/features/memorylake/mcp-servers/creating-api-keys), you select the workspace and boundary on the OAuth consent screen when a client connects.
## API Key
An **API key** (`sk-…`) is your credential for everything programmatic: the REST API, Model Router, and agent plugins. Create keys in the console under **API Keys** — each has a name and an expiry, and its permissions mirror those of the member who created it. Rotate or revoke anytime. See [Authentication](/authentication).
## How the Concepts Map to You
| You are… | Workspace | Projects | Memory flows |
| - | - | - | - |
| An individual | Your default personal workspace | One per life/work context | Your chats & files → your memories → every tool you connect |
| A team | Shared team workspaces | One per initiative or client | Everyone's contributions → governed shared memory → every member's assistant |
| A product builder | One workspace, or one per tenant | Per product domain or per end user | Your users' sessions → per-user memory via boundaries → your app's LLM calls |
Experience memory in the console in five minutes.
Deep-dive walkthroughs for personal, team, agent, and product use cases.
# Deployment Modes
Source: https://docs.memorylake.ai/features/memory-router/deployment-modes
Connect with your own provider key (BYOK) or with MemoryLake-hosted models — same memory layer either way
Memory Router works two ways. Unlike proxies that force you to bring your own key, you can keep your provider account **or** let MemoryLake run the models for you. Both modes share the same endpoints — the difference is which keys you send. Everything else — prompts, streaming, tool calls — stays the same.
## Endpoints
| Protocol | Endpoint |
| - | - |
| OpenAI · Chat Completions | `POST https://app.memorylake.ai/openai/v1/chat/completions` |
| OpenAI · Responses | `POST https://app.memorylake.ai/openai/v1/responses` |
| OpenAI · Embeddings | `POST https://app.memorylake.ai/openai/v1/embeddings` |
| Anthropic · Messages | `POST https://app.memorylake.ai/anthropic/v1/messages` |
Append `?boundary_id=` to enable memory on a request — see [How It Works](/features/memory-router/how-it-works#boundaries-define-the-scope).
With the Anthropic SDK, set `base_url` to `https://app.memorylake.ai/anthropic` (without `/v1`) — the SDK appends `/v1/messages` itself.
## MemoryLake-hosted
No provider account required. MemoryLake runs the major models for you, so a single MemoryLake API key is all you need to start.
* One key for everything — nothing else to sign up for.
* GPT, Claude, and Qwen model families built in and ready to call by their native names.
* The simplest possible way to ship with memory.
**Keys:** MemoryLake key only, in the native auth header (`Authorization: Bearer` for OpenAI-style calls, `x-api-key` for Anthropic)
```ts TypeScript theme={null}
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/openai/v1",
apiKey: process.env.MEMORYLAKE_API_KEY,
});
// Pick any built-in model by its native name, e.g. "gpt-4o-mini" or "qwen-plus".
```
## BYOK — Bring Your Own Key
Use your own provider account. Your provider key is encrypted in transit, forwarded to the provider per call, and never stored on our servers.
* Keep your existing OpenAI / Anthropic account.
* Your key, your billing, your rate limits.
* Key is encrypted + passthrough only — never persisted or logged.
**Keys:** your provider key in the provider's **native** auth header + MemoryLake key in the `x-memorylake-api-key` header
```ts TypeScript theme={null}
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/openai/v1",
apiKey: process.env.OPENAI_API_KEY, // your provider key
defaultHeaders: {
"x-memorylake-api-key": process.env.MEMORYLAKE_API_KEY,
},
});
```
The native auth header differs by protocol: OpenAI-style calls use `Authorization: Bearer `; Anthropic calls use `x-api-key: `. In BYOK mode your provider key goes there, and the MemoryLake key always rides in `x-memorylake-api-key`.
## Choosing a Mode
| | MemoryLake-hosted | BYOK |
| - | - | - |
| Provider account | Not required | Required (yours) |
| Keys | MemoryLake key only | Provider key + MemoryLake key |
| Billing & rate limits | Handled by MemoryLake | Stay with your provider account |
| Best for | Fastest path to ship with memory | Teams with existing provider contracts and quotas |
## Key Safety, by Design
In BYOK mode your provider key is encrypted in transit and passed straight through to the provider on every call. MemoryLake never stores, logs, or reuses it — the design is stateless, per-request passthrough with zero server-side key storage.
## Supported Providers
| Provider | BYOK | Hosted |
| - | - | - |
| OpenAI / GPT (Chat Completions & Responses) | ✅ | ✅ |
| Anthropic / Claude (Messages) | ✅ | ✅ |
| Alibaba Qwen (OpenAI-compatible, via `/openai/v1`) | — | ✅ |
Additional providers and protocols are added over time; the console's **Integrations → Memory Router API** page always reflects the current catalog.
## Next Steps
Copy-paste setup for both modes.
Trace requests and understand the error contract.
# FAQ
Source: https://docs.memorylake.ai/features/memory-router/faq
Common questions about Memory Router — code changes, Boundaries, providers, security, and availability
Only the base URL, a `boundary_id` query parameter, and — in BYOK mode — one header. Your prompts, streaming, tool calls, and response handling stay identical, because Memory Router speaks the same API as your provider.
A Boundary is the memory scope for a conversation — it binds requests to a workspace, project(s), and actors so the Router knows whose memory to read and write. You create it once in the console and pass its id as `?boundary_id=` on each call. Requests without a `boundary_id` still work, but pass through with memory disabled.
OpenAI (Chat Completions, Responses, Embeddings) and Anthropic (Messages) protocols. In hosted mode, GPT, Claude, and Qwen model families are built in and callable by their native names. See [Deployment Modes](/features/memory-router/deployment-modes#supported-providers) for the current matrix.
BYOK (Bring Your Own Key) means you supply your own provider key plus a MemoryLake key — billing and rate limits stay with your provider account. MemoryLake-hosted needs only a MemoryLake key: we run the major models for you, so you skip provider sign-up entirely. Both modes use the same endpoints; the difference is which keys you send.
Yes. Your provider key is encrypted in transit and forwarded to the provider on each call. MemoryLake never stores, logs, or reuses it — the design is stateless, per-request passthrough with zero server-side key storage.
The gateway returns `502 Bad Gateway` for that call — retry with backoff, and keep a fallback to a direct provider call if your application requires strict availability. Memory *writes* are asynchronous, so a slow memory store never delays a successful response. See [Observability](/features/memory-router/observability#error-contract) for the full error contract.
Memory recall happens before the model call and is optimized for low overhead; memory extraction and storage happen asynchronously after the response is returned, so writing memories never adds latency.
Yes. The Router and the [MemoryLake API](/features/memorylake/overview) operate on the same memory pool, so anything stored one way is retrievable the other — and visible in the console.
Memory Router is in private preview. If the Memory Router card is not yet visible under **Integrations** in your console, contact [support@memorylake.ai](mailto:support@memorylake.ai) to request access.
# How It Works
Source: https://docs.memorylake.ai/features/memory-router/how-it-works
A transparent gateway that intercepts, recalls, forwards, and remembers — scoped by Boundaries
## A Transparent Gateway
Memory Router sits between your application and the model provider. Your app talks to the Router exactly as it would talk to the provider — same payload, same SDK, same response shape — and the Router adds a memory layer transparently on the way through.
Because the Router speaks your provider's protocol, integrating it is a **base-URL change plus a `boundary_id` query parameter**. Nothing else in your code needs to move.
## The Four Steps
Your app sends the request to Memory Router instead of the provider — same payload, same SDK, same response shape. The `boundary_id` on the URL tells the Router which memory scope this conversation belongs to.
The Router searches prior memories within the Boundary's scope and injects only the relevant context into the prompt.
The enhanced request goes to the model — your own provider (BYOK) or a MemoryLake-hosted model.
New memories are extracted and stored asynchronously in the background — the response is never delayed.
## Boundaries Define the Scope
Every memory-enabled request carries a `boundary_id`. A **Boundary** binds the conversation to a workspace, one or more projects, a human actor, and an assistant actor — so the Router knows exactly whose memory to read and where to write new memories.
* One user talking to one assistant? One Boundary.
* The same product serving many users? One Boundary per user (or per user–assistant pair), so memories never leak across users.
* A request **without** `boundary_id` skips the memory layer entirely and passes straight through to the model.
Memory extraction and storage happen **asynchronously**. The model's response is returned as soon as it is ready; writing new memories never adds latency to the call.
## Shared Memory Pool
The Router and the [MemoryLake API](/features/memorylake/overview) operate on the same memory pool. Anything stored through the Router is retrievable through the API (and visible in the console), and vice versa — one source of truth across sessions, apps, and models.
## Next Steps
Go live in three steps.
BYOK vs. MemoryLake-hosted, endpoints, and supported providers.
# Observability
Source: https://docs.memorylake.ai/features/memory-router/observability
Trace every request, read the console call logs, and understand the error contract
Every request through Memory Router is traceable end to end — from your client, through the gateway, to the memory layer and the model.
## Request Tracing
Each response carries an **`X-Trace-ID`** header — a W3C-compatible trace id that spans the whole call chain. Log it alongside your own request ids; when something looks off, it is the fastest way for support to locate the exact call.
Memory Router also honors inbound **W3C Trace Context** (`traceparent` / `tracestate`) headers, so if your application already propagates distributed traces, the Router's spans join your existing trace.
## Console Call Logs
Every call lands in the console **Logs** page with per-call details:
| Field | What it tells you |
| - | - |
| **Model** | The canonical model that served the request. |
| **Tokens** | Prompt, completion, and total token counts as metered by the model. |
| **Finish reason** | Why generation stopped (`stop`, `length`, tool call, …). |
| **Key source** | `byok` (your provider key) or `platform` (MemoryLake-hosted). |
| **Trace ID** | Matches the `X-Trace-ID` response header for cross-referencing. |
Use **Key source** to verify BYOK is actually in effect, and compare token counts across turns to see the effect of memory injection versus replaying full history.
## Error Contract
| Status | Meaning | What to do |
| - | - | - |
| `401 Unauthorized` | Missing or invalid MemoryLake key. | Check the key in the native auth header (hosted) or `x-memorylake-api-key` (BYOK). |
| `402 Payment Required` | Account balance below the minimum required to forward the call. | Top up your balance in the console, then retry. |
| `502 Bad Gateway` | The memory gateway could not reach its upstream service. | Retry with backoff; if it persists, contact support with your `X-Trace-ID`. |
| Provider errors (`4xx`/`5xx`) | Returned by the model provider itself, in the provider's own format. | Handle exactly as you would on a direct provider call. |
Requests **without** a `boundary_id` skip the memory layer but still authenticate and meter through the gateway. If you want to isolate whether an issue is memory-related, retry the same call without `boundary_id` and compare.
## Next Steps
BYOK vs. hosted, endpoints, and supported providers.
Common questions about code, providers, security, and availability.
# Overview
Source: https://docs.memorylake.ai/features/memory-router/overview
A drop-in memory gateway that adds persistent memory to your LLM calls with a base-URL change
## Quick Introduction
Memory Router is a transparent gateway that sits between your app and the model. Point your existing SDK at MemoryLake, attach a memory Boundary, and every conversation gains long-term memory — no new SDK, no retrieval pipeline to build.
* **Minimal integration** — change the base URL and pass a `boundary_id`; keep your SDK and code as they are
* **BYOK or hosted** — bring your own provider key (encrypted in transit, never stored), or use MemoryLake-hosted models with a single key
* **Shared memory pool** — the Router and the [MemoryLake API](/features/memorylake/overview) read and write the same memories, so there is one source of truth
Memory Router is currently in **private preview**. If the Memory Router card is not yet visible under **Integrations** in your console, contact [support@memorylake.ai](mailto:support@memorylake.ai) to request access.
Memory Router speaks the OpenAI and Anthropic protocols natively. Your prompts, streaming, and tool calls stay identical.
## The Problem It Solves
Every LLM call is stateless. To fake continuity you re-send the entire history on every turn — which is slow, expensive, and eventually overflows the context window. Bolting on a vector DB and retrieval pipeline solves it, but it is weeks of plumbing you have to build and maintain.
* Full chat history re-sent on every call — token cost climbs with conversation length.
* Long sessions hit the context-window ceiling and start truncating mid-task.
* Memory lives in one app — switch models or sessions and the context is gone.
* Stand up a vector DB, embeddings pipeline, chunking, and retrieval logic.
* Write extraction, dedup, and relevance ranking — then keep it tuned.
* Maintain it across every provider and every model you support.
Memory Router collapses all of that into a base-URL change plus one query parameter. **The memory layer is the gateway.**
## What You Get
| Capability | What it means |
| - | - |
| **Minimal integration** | Change the base URL and pass `boundary_id`. Keep your SDK and your code as they are. |
| **BYOK or hosted** | Bring your own provider key (encrypted in transit, never stored) or use MemoryLake-hosted models with a single key. |
| **Automatic memory** | Relevant memories are recalled and injected before the call; new memories are extracted asynchronously after it — never delaying the response. |
| **Scoped by Boundary** | A [Boundary](#boundaries:-the-memory-scope) defines exactly which workspace, projects, and actors a conversation's memory belongs to. |
| **Shared memory pool** | The Router and the MemoryLake API read and write the same memories — one source of truth. |
| **Traceable** | Every response carries an `X-Trace-ID` header, and each call lands in the console Logs with model, token, and key-source details. |
## Boundaries: The Memory Scope
Memory on the Router is **opt-in per request**. A **Boundary** binds a conversation to its memory scope — a workspace, one or more projects, a human actor, and an assistant actor. You create a Boundary once in the console, then pass its id on each call:
```text theme={null}
POST /openai/v1/chat/completions?boundary_id=
```
* **With `boundary_id`** — memories in that scope are recalled and injected, and new memories from the conversation are stored back into it.
* **Without `boundary_id`** — the request passes through to the model unchanged, with memory disabled.
This makes memory explicit and controllable: the same endpoint can serve memory-enabled product traffic and plain passthrough traffic side by side.
## Direct API Call vs. Memory Router
| | Direct provider call | With Memory Router |
| - | - | - |
| Long-term memory | You build and host it | Built in, automatic |
| Keys & accounts | A provider account is required | BYOK or use just a MemoryLake key |
| Code changes | New SDK + retrieval pipeline | Base-URL change + `boundary_id` |
| Across sessions & models | Memory is siloed per app | Shared memory pool |
| Memory scoping | Ad-hoc, per app | Explicit Boundaries per workspace/project/actor |
| Visibility | None by default | `X-Trace-ID` + console call logs |
## Quick Start
1. **[Get a MemoryLake key and a Boundary](/features/memory-router/quickstart#step-1:-get-a-key-and-a-boundary)**: Create an API key and a Boundary in the console.
2. **[Pick a mode and swap the base URL](/features/memory-router/deployment-modes)**: Choose BYOK or MemoryLake-hosted and point your SDK at the Router.
3. **[Call as normal](/features/memory-router/quickstart#step-3:-call-as-normal)**: Send requests exactly as you do today — memory is recalled and stored automatically.
## Documentation
Understand the transparent gateway and what happens on each request.
Go live in three steps with copy-paste code for BYOK and hosted modes.
Compare BYOK and MemoryLake-hosted, endpoints, supported providers, and key safety.
Trace requests, read the console call logs, and understand the error contract.
Common questions about code changes, providers, security, and availability.
# Quickstart
Source: https://docs.memorylake.ai/features/memory-router/quickstart
Add persistent memory to your LLM calls in three steps
Get Memory Router running in three steps. The only changes to your application are the base URL, a `boundary_id` query parameter, and — in BYOK mode — one header.
Memory Router is in **private preview**. If the Memory Router card is not yet visible under **Integrations** in your console, contact [support@memorylake.ai](mailto:support@memorylake.ai) to request access.
## Step 1: Get a key and a Boundary
1. Sign in to the [console](https://app.memorylake.ai) and create a MemoryLake API key (starts with `sk-`).
2. Open **Integrations → Memory Router API** and create a **Boundary** — the memory scope that binds your conversations to a workspace, project, and actors. Copy its id.
Keep your MemoryLake key in an environment variable such as `MEMORYLAKE_API_KEY`. See [Authentication](/authentication) for details on managing keys. Requests **without** a `boundary_id` still work, but run as plain passthrough with memory disabled.
## Step 2: Pick a mode and swap the base URL
Both modes use the same endpoints — what differs is which keys you send:
| Mode | Keys |
| - | - |
| **MemoryLake-hosted** | MemoryLake key only, in the native auth header |
| **BYOK** (bring your own key) | Your provider key in the native auth header + MemoryLake key in the `x-memorylake-api-key` header |
| Protocol | Endpoint |
| - | - |
| OpenAI · Chat Completions | `POST https://app.memorylake.ai/openai/v1/chat/completions` |
| OpenAI · Responses | `POST https://app.memorylake.ai/openai/v1/responses` |
| OpenAI · Embeddings | `POST https://app.memorylake.ai/openai/v1/embeddings` |
| Anthropic · Messages | `POST https://app.memorylake.ai/anthropic/v1/messages` |
See [Deployment Modes](/features/memory-router/deployment-modes) for a full comparison.
### MemoryLake-hosted — one key
No provider account required. GPT, Claude, and Qwen model families are built in; pick any model by its native name.
```ts TypeScript theme={null}
import OpenAI from "openai";
// Hosted: no provider account. MemoryLake runs the models,
// so a single MemoryLake key is all you need.
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/openai/v1",
apiKey: process.env.MEMORYLAKE_API_KEY,
});
const resp = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
}, { query: { boundary_id: process.env.MEMORYLAKE_BOUNDARY_ID } });
```
```py Python theme={null}
from openai import OpenAI
import os
# Hosted: no provider account. MemoryLake runs the models,
# so a single MemoryLake key is all you need.
client = OpenAI(
base_url="https://app.memorylake.ai/openai/v1",
api_key=os.environ["MEMORYLAKE_API_KEY"],
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello!"}],
extra_query={"boundary_id": os.environ["MEMORYLAKE_BOUNDARY_ID"]},
)
```
```bash cURL theme={null}
curl "https://app.memorylake.ai/openai/v1/chat/completions?boundary_id=$MEMORYLAKE_BOUNDARY_ID" \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello!"}]
}'
```
### BYOK — your provider key
Keep your provider account. Your provider key goes in the provider's **native** auth header (`Authorization: Bearer` for OpenAI, `x-api-key` for Anthropic); the MemoryLake key rides in the `x-memorylake-api-key` header.
```ts TypeScript theme={null}
import OpenAI from "openai";
// BYOK: you send your own provider key. It is encrypted in transit,
// forwarded to the provider, and never stored.
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/openai/v1",
apiKey: process.env.OPENAI_API_KEY, // your provider key
defaultHeaders: {
"x-memorylake-api-key": process.env.MEMORYLAKE_API_KEY,
},
});
const resp = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello!" }],
}, { query: { boundary_id: process.env.MEMORYLAKE_BOUNDARY_ID } });
```
```py Python theme={null}
from openai import OpenAI
import os
# BYOK: you send your own provider key. It is encrypted in transit,
# forwarded to the provider, and never stored.
client = OpenAI(
base_url="https://app.memorylake.ai/openai/v1",
api_key=os.environ["OPENAI_API_KEY"], # your provider key
default_headers={
"x-memorylake-api-key": os.environ["MEMORYLAKE_API_KEY"],
},
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello!"}],
extra_query={"boundary_id": os.environ["MEMORYLAKE_BOUNDARY_ID"]},
)
```
```bash cURL theme={null}
curl "https://app.memorylake.ai/openai/v1/chat/completions?boundary_id=$MEMORYLAKE_BOUNDARY_ID" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "x-memorylake-api-key: $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello!"}]
}'
```
### Anthropic SDK
With the Anthropic SDK, set the base URL to `https://app.memorylake.ai/anthropic` — the SDK appends `/v1/messages` itself.
```ts TypeScript theme={null}
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://app.memorylake.ai/anthropic",
apiKey: process.env.MEMORYLAKE_API_KEY, // or your Anthropic key + x-memorylake-api-key header for BYOK
});
const resp = await client.messages.create({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello!" }],
}, { query: { boundary_id: process.env.MEMORYLAKE_BOUNDARY_ID } });
```
```py Python theme={null}
import anthropic
import os
client = anthropic.Anthropic(
base_url="https://app.memorylake.ai/anthropic",
api_key=os.environ["MEMORYLAKE_API_KEY"],
)
resp = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
extra_query={"boundary_id": os.environ["MEMORYLAKE_BOUNDARY_ID"]},
)
```
```bash cURL theme={null}
curl "https://app.memorylake.ai/anthropic/v1/messages?boundary_id=$MEMORYLAKE_BOUNDARY_ID" \
-H "x-api-key: $MEMORYLAKE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Hello!"}]
}'
```
The console's **Integrations → Memory Router API** page generates these snippets for you, pre-filled with your Boundary id, across cURL / Python / Node.js and both modes.
## Step 3: Call as normal
Send requests exactly as you do today. With a `boundary_id` attached, relevant memories are recalled into the prompt automatically, and new memories are extracted and stored asynchronously — the response is never delayed.
```ts TypeScript theme={null}
const completion = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Remind me what we decided last time." }],
}, { query: { boundary_id: process.env.MEMORYLAKE_BOUNDARY_ID } });
console.log(completion.choices[0].message.content);
```
Check the `X-Trace-ID` response header and the console **Logs** page to confirm the call went through the Router — see [Observability](/features/memory-router/observability).
Newer OpenAI reasoning models (`gpt-5` family, `o1`/`o3`/`o4`) expect `max_completion_tokens` instead of `max_tokens` on Chat Completions. Keep your parameters in the provider's official format — the Router passes them through unchanged.
## Next Steps
Full comparison of BYOK and hosted, plus supported providers.
Trace requests and understand the error contract.
# A2A Integration
Source: https://docs.memorylake.ai/features/memorylake/api-reference/a2a/overview
Use the standard A2A protocol to communicate with MemoryLake agents
MemoryLake implements the [A2A (Agent-to-Agent) protocol](https://a2a-protocol.org/) by Google. If you are already familiar with A2A, you can use any A2A-compatible client to interact with MemoryLake agents.
Refer to the [A2A specification](https://a2a-protocol.org/latest/specification/) for the standard request and response schemas. Official SDKs are available at [github.com/a2aproject](https://github.com/a2aproject).
**Permission required:** `workspace_agent:a2a`
## Base URL
```
https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/{workspaceId}/agents/{agentId}/a2a
```
Append standard A2A paths directly — for example `POST {baseUrl}/message:send` or `GET {baseUrl}/tasks/{taskId}`.
## Protocol Versions
MemoryLake exposes two parallel sets of A2A routes, one per protocol version, and each version is reachable over **two transports**: REST and JSON-RPC 2.0.
| Protocol version | REST routes | Message body | `role` value |
| - | - | - | - |
| **A2A v1.0** | `{baseUrl}/message:send`, `{baseUrl}/tasks/...` | `message.parts` (proto-JSON, no `kind` discriminator) | `ROLE_USER` |
| **A2A v0.3** | `{baseUrl}/v1/message:send`, `{baseUrl}/v1/tasks/...` | REST: `message.content` · JSON-RPC: `message.parts` with a `kind` discriminator | REST: `ROLE_USER` · JSON-RPC: `user` |
The `/v1/` path prefix refers to the older **A2A v0.3** wire format, not to protocol version 1.0. The un-prefixed routes implement the current **A2A v1.0** format. Make sure the request body shape matches the route you call — a v0.3-style REST body (`message.content`) is rejected by the v1.0 REST routes, and vice versa.
Over JSON-RPC, both versions post to the bare `{baseUrl}` and pick the operation with `method`: v1.0 uses `SendMessage`, `SendStreamingMessage`, `GetTask`, `CancelTask`, `SubscribeToTask`; v0.3 uses `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`, `tasks/resubscribe`. The protocol version is negotiated from the method name, and v1.0 clients should also send `A2A-Version: 1.0`.
All four route families accept the same `configuration` object and the same MemoryLake extension described below:
| `configuration` field | Type | Description |
| - | - | - |
| `blocking` | boolean | Wait for the task to complete before responding. Applies to both v1.0 and v0.3. |
| `historyLength` | integer | Number of most recent messages from the task history to include in the response. |
| `acceptedOutputModes` | array | Output MIME types the client can handle. |
| `pushNotificationConfig` | object | Callback URL (plus optional auth) for task update notifications. |
## MemoryLake Extension
MemoryLake extends the standard A2A protocol through the `metadata.memorylake` namespace. Pass this object in the request metadata of `message:send` or `message:stream` to control how the agent interacts with MemoryLake's memory layer.
This is the key difference from a vanilla A2A server — these fields connect the agent to workspaces, projects, and actors in MemoryLake.
MemoryLake-specific configuration. Without this, the agent runs without any memory context.
Actor identifier representing the end user. Facts extracted from the conversation are associated with this actor, enabling per-user memory.
Project the agent can both read from and write to. Extracted facts are persisted to this project; conversation history is stored at the workspace level, not in the project.
Additional projects the agent can search (documents and facts) but not modify. Use this to give the agent access to shared knowledge bases.
Maps subagent names (defined in the agent configuration) to concrete agent IDs. Allows dynamic routing of subagent calls at request time.
Runtime overrides for the agent's configuration.
Override the agent's model (e.g. `gpt-4o`, `claude-sonnet-4-20250514`)
Replace the agent's system prompt for this request
Override model parameters (e.g. `temperature`, `max_tokens`)
Reasoning configuration
Reasoning type
Token budget for reasoning
Per-request capability overrides, keyed by capability name. Include a capability to turn it on for this request with the configuration you supply; omit it to keep the agent's own setting. Capability names and their fields are snake\_case, unlike the camelCase fields around them. `web_search` is the only capability exposed here today — more may follow.
Lets the agent search the web. Pass an empty object `{}` for web search on its own, or add `open_datasets` to search MemoryLake's curated Open Data collections as well.
Open Data collections to search alongside the web, by identifier: `research/academic`, `clinical/trials`, `drug/database`, `company/fundamentals`, `financial/markets`, `economic/data`, `patents/ip`.
Override the maximum number of turns
Run options for this request.
Language the agent responds in, given as a language name such as `English`, `Chinese`, or `Japanese`. Omit it to have the agent reply in the language of the user's message.
## Examples
Sending a message spans three independent choices — **protocol version** (v1.0 / v0.3) × **method** (send / stream) × **transport** (REST / JSON-RPC) — so there are eight valid combinations. All eight are shown below.
Paths below are relative to the base URL; JSON-RPC always posts to the bare base URL and selects the operation with `method`.
| # | Combination | Request | Headers |
| - | - | - | - |
| 1 | v1.0 · send · REST | `POST /message:send` | — |
| 2 | v1.0 · stream · REST | `POST /message:stream` | SSE |
| 3 | v0.3 · send · REST | `POST /v1/message:send` | — |
| 4 | v0.3 · stream · REST | `POST /v1/message:stream` | SSE |
| 5 | v1.0 · send · JSON-RPC | `SendMessage` | v1.0 |
| 6 | v1.0 · stream · JSON-RPC | `SendStreamingMessage` | v1.0 + SSE |
| 7 | v0.3 · send · JSON-RPC | `message/send` | — |
| 8 | v0.3 · stream · JSON-RPC | `message/stream` | SSE |
In the **Headers** column, **SSE** means `Accept: text/event-stream` and **v1.0** means `A2A-Version: 1.0`. All eight take the same `configuration` object and the same `metadata.memorylake` extension. The four streaming variants respond with `text/event-stream`; the four send variants respond with a single JSON body.
Watch the three shape differences between versions and transports: v1.0 uses `parts` with `role: "ROLE_USER"`; v0.3 **REST** uses `content` with `role: "ROLE_USER"`; v0.3 **JSON-RPC** uses `parts` where every part carries a `kind` discriminator, with `role: "user"` in lowercase.
### REST transport
```bash 1 · v1.0 send theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a/message:send' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"message": {
"role": "ROLE_USER",
"parts": [
{ "text": "How do I configure two-factor authentication?" }
],
"contextId": "ctx_m4n7p2q9"
},
"configuration": {
"blocking": true,
"historyLength": 10
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readWriteProjectId": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8",
"readOnlyProjectIds": ["proj_shared_kb"],
"overrides": {
"model": "gpt-4o",
"maxTurns": 5,
"capabilitiesOverride": {
"web_search": {
"open_datasets": ["research/academic", "clinical/trials"]
}
}
}
}
}
}'
```
```bash 2 · v1.0 stream theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a/message:stream' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{
"message": {
"role": "ROLE_USER",
"parts": [
{ "text": "Summarize our last meeting notes" }
]
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readOnlyProjectIds": ["proj_meetings"]
}
}
}'
```
```bash 3 · v0.3 send theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a/v1/message:send' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"message": {
"role": "ROLE_USER",
"content": [
{ "text": "How do I configure two-factor authentication?" }
]
},
"configuration": {
"blocking": true,
"historyLength": 10
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readWriteProjectId": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"
}
}
}'
```
```bash 4 · v0.3 stream theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a/v1/message:stream' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{
"message": {
"role": "ROLE_USER",
"content": [
{ "text": "Summarize our last meeting notes" }
]
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readOnlyProjectIds": ["proj_meetings"]
}
}
}'
```
### JSON-RPC transport
Both versions share the same path — `POST {baseUrl}` with no suffix. The version comes from the method name; v1.0 clients should also send `A2A-Version: 1.0`.
```bash 5 · v1.0 send theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-H 'A2A-Version: 1.0' \
-d '{
"jsonrpc": "2.0",
"id": "req-1",
"method": "SendMessage",
"params": {
"message": {
"messageId": "msg-1",
"role": "ROLE_USER",
"parts": [
{ "text": "How do I configure two-factor authentication?" }
],
"contextId": "ctx_m4n7p2q9"
},
"configuration": {
"blocking": true,
"historyLength": 10
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readWriteProjectId": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8",
"readOnlyProjectIds": ["proj_shared_kb"],
"overrides": {
"model": "gpt-4o",
"maxTurns": 5
}
}
}
}
}'
```
```bash 6 · v1.0 stream theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-H 'A2A-Version: 1.0' \
-H 'Accept: text/event-stream' \
-d '{
"jsonrpc": "2.0",
"id": "req-2",
"method": "SendStreamingMessage",
"params": {
"message": {
"messageId": "msg-2",
"role": "ROLE_USER",
"parts": [
{ "text": "Summarize our last meeting notes" }
]
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readOnlyProjectIds": ["proj_meetings"]
}
}
}
}'
```
```bash 7 · v0.3 send theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"jsonrpc": "2.0",
"id": "req-3",
"method": "message/send",
"params": {
"message": {
"messageId": "msg-3",
"role": "user",
"parts": [
{ "kind": "text", "text": "How do I configure two-factor authentication?" }
],
"contextId": "ctx_m4n7p2q9"
},
"configuration": {
"blocking": true,
"historyLength": 10
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readWriteProjectId": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"
}
}
}
}'
```
```bash 8 · v0.3 stream theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/a2a' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{
"jsonrpc": "2.0",
"id": "req-4",
"method": "message/stream",
"params": {
"message": {
"messageId": "msg-4",
"role": "user",
"parts": [
{ "kind": "text", "text": "Summarize our last meeting notes" }
]
},
"metadata": {
"memorylake": {
"actorId": "act_user_jane",
"readOnlyProjectIds": ["proj_meetings"]
}
}
}
}'
```
# Bind Actor to Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/bind-actor
Bind an existing actor to a workspace
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors
```
Binds an existing actor to a workspace. Once bound, the actor can participate in conversations within the workspace's projects. An actor can be bound to multiple workspaces.
**Permission required:** `workspace_actor:create`
### Path Parameters
Workspace ID
### Request Body
ID of the actor to bind. The actor must already exist (see [Create Actor](/features/memorylake/api-reference/actors/create-actor)).
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-7k8m9n0p1q2r/actors' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"actor_id": "actor-8d093c0578ffeb19f8fa10ea28ee9362"
}'
```
### Response
Actor ID
Caller-defined external identifier
Human-readable display name
Timestamp when the actor was bound to this workspace
```json Success (200) theme={null}
{
"success": true,
"data": {
"actor_id": "actor-8d093c0578ffeb19f8fa10ea28ee9362",
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen",
"bound_at": "2025-03-15T09:00:00Z"
}
}
```
# Create Actor
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/create-actor
Create a new actor to represent a conversation participant
```
POST /openapi/memorylake/api/v3/actors
```
Creates a new actor. Actors represent participants in conversations -- typically end users or system identities whose interactions generate memories. After creating an actor, you can [bind it to a workspace](/features/memorylake/api-reference/actors/bind-actor) so it can participate in conversations within that workspace's projects.
**Permission required:** `actor:create`
### Request Body
Your own identifier for this actor — the one it already has in your system. Must be unique within your tenant. Pass `by_custom_id=true` on later requests to address the actor by it instead of by `id`. See [Your own identifiers](/features/memorylake/api-reference/overview#your-own-identifiers).
Human-readable name shown in the console and returned in API responses.
Free-text description of the actor's role or purpose.
Labels used to group and filter actors, for example `vip` or `cn`. Duplicates are removed and surrounding whitespace is trimmed. Matching is exact and case-sensitive, so `VIP` and `vip` are two different tags. Up to 20 tags per actor, each at most 64 characters, and a tag may not contain a comma.
Arbitrary key-value pairs for caller-defined metadata, such as tier, region, or department. Metadata cannot be filtered on -- use `tags` for attributes you want to search by.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen",
"description": "Primary end user for the mobile app",
"tags": ["vip", "cn"],
"metadata": {
"tier": "premium",
"region": "us-west"
}
}'
```
### Response
Actor ID
Caller-defined external identifier
Human-readable display name
Actor description
Labels attached to the actor. Empty when the actor has none
Caller-defined metadata
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "actor-8d093c0578ffeb19f8fa10ea28ee9362",
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen",
"description": "Primary end user for the mobile app",
"tags": ["vip", "cn"],
"metadata": {
"tier": "premium",
"region": "us-west"
},
"created_at": "2025-03-10T08:00:00Z",
"updated_at": "2025-03-10T08:00:00Z"
}
}
```
# Delete Actor
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/delete-actor
Permanently delete an actor
```
DELETE /openapi/memorylake/api/v3/actors/{id}
```
Permanently deletes an actor. Any workspace bindings for this actor are also removed.
**Permission required:** `actor:delete`
This action is irreversible. Memories and conversation history associated with the actor are not deleted, but the actor can no longer be referenced in new conversations.
### Path Parameters
Actor ID
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors/act-a1b2c3d4e5f6' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully"
}
```
# Get Actor
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/get-actor
Retrieve a single actor by ID or custom ID
```
GET /openapi/memorylake/api/v3/actors/{id}
```
Returns the full details of a single actor. By default, `{id}` is treated as the MemoryLake actor ID. Set `by_custom_id=true` to look up the actor by its `custom_id` instead.
**Permission required:** `actor:read`
### Path Parameters
Actor ID, or the actor's `custom_id` when `by_custom_id` is `true`.
### Query Parameters
When `true`, the path parameter is interpreted as the actor's `custom_id` rather than its MemoryLake ID.
```bash By actor ID theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors/act-a1b2c3d4e5f6' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash By custom ID theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors/user-ext-001?by_custom_id=true' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Actor ID
Caller-defined external identifier
Human-readable display name
Actor description
Labels attached to the actor. Empty when the actor has none
Caller-defined metadata
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "actor-8d093c0578ffeb19f8fa10ea28ee9362",
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen",
"description": "Primary end user for the mobile app",
"tags": ["vip", "cn"],
"metadata": {
"tier": "premium",
"region": "us-west"
},
"created_at": "2025-03-10T08:00:00Z",
"updated_at": "2025-03-10T08:00:00Z"
}
}
```
# List Actors
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/list-actors
Returns a paginated list of actors
```
GET /openapi/memorylake/api/v3/actors
```
Returns a paginated list of all actors in your account. You can filter by actor type or search by display name.
**Permission required:** `actor:read` — rows you cannot open are left out of the list rather than the list being refused
### Query Parameters
Number of actors per page.
Token returned by the previous call. Omit on the first request.
Filter by actor type. One of `HUMAN` or `ASSISTANT`.
Fuzzy search by display name.
Filter by tag. Repeat the parameter (`?tags=vip&tags=cn`) or comma-separate the values (`?tags=vip,cn`) to require several tags at once -- only actors carrying every listed tag are returned. Matching is exact and case-sensitive.
```bash First page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Filter by type theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors?actor_type=HUMAN' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Search by display name theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors?display_name_fuzzy=Alice' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Filter by tag theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors?tags=vip&tags=cn' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Next page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors?page_size=20&continuation_token=eyJsYXN0X2lkIjoiYWN0LTk4NzY1NCJ9' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of actor objects
Actor ID
Caller-defined external identifier
Human-readable display name
Actor description
Labels attached to the actor. Empty when the actor has none
Caller-defined metadata (key-value pairs)
Creation timestamp
Last update timestamp
Token for the next page. Absent or `null` when this is the last page.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "actor-8d093c0578ffeb19f8fa10ea28ee9362",
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen",
"description": "Primary end user for the mobile app",
"tags": ["vip", "cn"],
"metadata": {
"tier": "premium",
"region": "us-west"
},
"created_at": "2025-03-10T08:00:00Z",
"updated_at": "2025-03-10T08:00:00Z"
},
{
"id": "actor-7aab545a90516584422410fc767cbca0",
"custom_id": "system-intake",
"actor_type": "ASSISTANT",
"display_name": "Intake Bot",
"description": "Automated intake system for onboarding flows",
"tags": [],
"metadata": {},
"created_at": "2025-03-12T14:30:00Z",
"updated_at": "2025-03-12T14:30:00Z"
}
],
"continuation_token": "eyJsYXN0X2lkIjoiYWN0LWY2ZTVkNGMzYjJhMSJ9"
}
}
```
# List Workspace Actors
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/list-workspace-actors
List actors bound to a workspace
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors
```
Returns a paginated list of actors that are bound to the specified workspace. Only bound actors can participate in conversations within the workspace's projects.
**Permission required:** `workspace_actor:read` — rows you cannot open are left out of the list rather than the list being refused
### Path Parameters
Workspace ID
### Query Parameters
Number of bindings per page.
Token returned by the previous call. Omit on the first request.
Filter by actor type. One of `HUMAN` or `ASSISTANT`.
Fuzzy search by display name.
Filter by tag. Repeat the parameter (`?tags=vip&tags=cn`) or comma-separate the values (`?tags=vip,cn`) to require several tags at once -- only actors carrying every listed tag are returned. Matching is exact and case-sensitive.
```bash First page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-7k8m9n0p1q2r/actors?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Next page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-7k8m9n0p1q2r/actors?page_size=20&continuation_token=eyJsYXN0X2lkIjoiYWN0LWY2ZTVkNCJ9' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of actor binding objects
Actor ID
Caller-defined external identifier
Human-readable display name
Labels attached to the actor. Empty when the actor has none
Timestamp when the actor was bound to this workspace
Token for the next page. Absent or `null` when this is the last page.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"actor_id": "actor-8d093c0578ffeb19f8fa10ea28ee9362",
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen",
"tags": ["vip", "cn"],
"bound_at": "2025-03-15T09:00:00Z"
},
{
"actor_id": "actor-7aab545a90516584422410fc767cbca0",
"custom_id": "system-intake",
"actor_type": "ASSISTANT",
"display_name": "Intake Bot",
"tags": [],
"bound_at": "2025-03-15T09:05:00Z"
}
],
"continuation_token": null
}
}
```
# Overview
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/overview
Actors are the identity layer in MemoryLake — the subject of all memories
An **Actor** represents a participant identity in MemoryLake. Every message in a conversation is attributed to an actor, and every fact extracted from those conversations is associated with one. Actors are the **subject of memory** — they are what MemoryLake "remembers about."
## Actor Types
The Actor API works with the people using your application. An actor you create here is a person —
there is nothing else to choose.
**An agent is not reachable through this API.** Agents have memories of their own, but you address
them through the [Agent](/features/memorylake/api-reference/agents/overview) endpoints, using the
agent's id. Nothing belonging to an agent is returned here, and an id that is not an actor's answers
`404`.
If you previously read an agent's memories through its identity actor, switch to the agent id. It
is the same memories, named the way everything else names them.
## How Actors Work
1. **Create** an actor globally with a `custom_id` that maps to your user ID
2. **Bind** the actor to one or more workspaces
3. **Use** the actor's ID when [appending messages](/features/memorylake/api-reference/conversations/create-message) to conversations
4. **Query** the actor's accumulated facts via [Actor Facts](/features/memorylake/api-reference/facts/list-actor-facts)
## An actor's facts
An actor accumulates facts across every project in a workspace — *"Jane prefers dark mode"* — and
they follow the actor from project to project. That is what gives each person a memory of their own
throughout your application. Read them at:
```
/api/v3/workspaces/{workspaceId}/actors/{actorId}/facts
```
Facts scoped to a project rather than to a person stay with the project. For how the scopes relate,
see [Memories](/features/memorylake/memories/overview).
## Endpoints
| Operation | Method | Path |
| - | - | - |
| [List Actors](/features/memorylake/api-reference/actors/list-actors) | `GET` | `/api/v3/actors` |
| [Create Actor](/features/memorylake/api-reference/actors/create-actor) | `POST` | `/api/v3/actors` |
| [Get Actor](/features/memorylake/api-reference/actors/get-actor) | `GET` | `/api/v3/actors/{id}` |
| [Update Actor](/features/memorylake/api-reference/actors/update-actor) | `PATCH` | `/api/v3/actors/{id}` |
| [Delete Actor](/features/memorylake/api-reference/actors/delete-actor) | `DELETE` | `/api/v3/actors/{id}` |
| [Bind to Workspace](/features/memorylake/api-reference/actors/bind-actor) | `POST` | `/api/v3/workspaces/{id}/actors` |
| [List in Workspace](/features/memorylake/api-reference/actors/list-workspace-actors) | `GET` | `/api/v3/workspaces/{id}/actors` |
| [Unbind from Workspace](/features/memorylake/api-reference/actors/unbind-actor) | `DELETE` | `/api/v3/workspaces/{id}/actors/{actorId}` |
# Unbind Actor from Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/unbind-actor
Remove an actor's binding from a workspace
```
DELETE /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}
```
Removes an actor's binding from a workspace. The actor itself is not deleted and can be re-bound later. After unbinding, the actor can no longer participate in new conversations within this workspace.
**Permission required:** `workspace_actor:delete`
### Path Parameters
Workspace ID
Actor ID to unbind from the workspace
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-7k8m9n0p1q2r/actors/act-a1b2c3d4e5f6' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully"
}
```
# Update Actor
Source: https://docs.memorylake.ai/features/memorylake/api-reference/actors/update-actor
Update an actor's display name, description, or metadata
```
PATCH /openapi/memorylake/api/v3/actors/{id}
```
Updates a single actor. Only the fields you include in the request body are changed; omitted fields remain untouched.
**Permission required:** `actor:modify`
### Path Parameters
Actor ID
### Request Body
Updated display name.
Updated description.
Replaces the actor's tags outright -- the list you send becomes the complete set. Send `[]` to remove every tag, or omit the field to leave the current tags untouched.
Updated metadata. Replaces the entire metadata object -- merge locally before sending if you want to preserve existing keys.
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/api/v3/actors/act-a1b2c3d4e5f6' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"display_name": "Alice Chen (VIP)",
"tags": ["vip", "enterprise"],
"metadata": {
"tier": "enterprise",
"region": "us-west",
"account_manager": "bob@example.com"
}
}'
```
### Response
Actor ID
Caller-defined external identifier
Human-readable display name
Actor description
Labels attached to the actor. Empty when the actor has none
Caller-defined metadata
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "actor-8d093c0578ffeb19f8fa10ea28ee9362",
"custom_id": "user-ext-001",
"actor_type": "HUMAN",
"display_name": "Alice Chen (VIP)",
"tags": ["vip", "enterprise"],
"description": "Primary end user for the mobile app",
"metadata": {
"tier": "enterprise",
"region": "us-west",
"account_manager": "bob@example.com"
},
"created_at": "2025-03-10T08:00:00Z",
"updated_at": "2025-06-15T11:20:00Z"
}
}
```
# Create Agent
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/create-agent
Create a new agent definition with its initial configuration
```
POST /openapi/memorylake/api/v3/agents
```
Creates a new agent with the specified configuration. You provide a name and custom identifier, and optionally attach a description, model, capabilities, policies, subagents, and other settings. The agent is created at version 1.
**Permission required:** `agent:create`
### Request Body
Agent name
Your own identifier for this agent — the one it already has in your system. Must be unique within your tenant. Pass `by_custom_id=true` on later requests to address the agent by it instead of by `id`. See [Your own identifiers](/features/memorylake/api-reference/overview#your-own-identifiers).
Agent description
Whether the platform hosts the agent's runtime. `INTERNAL` (the default) runs the agent here and supports versions, forking and A2A. `EXTERNAL` registers memory only — the agent runs on your side, so every runtime field below (`system_prompt`, `model`, `model_settings`, `capabilities`, `policies`, `output`, `runtime_bindings`, `subagents`, `skills`) is ignored.
Arbitrary key-value pairs for storing additional agent information
Model to use for the agent (e.g. `gpt-4o`, `claude-sonnet-4-20250514`)
List of capability identifiers the agent supports (e.g. `tool_use`, `memory_read`, `memory_write`)
Execution policies that constrain agent behavior
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for the agent
Output mode (`text` or `json`)
JSON Schema that the agent's output must conform to when mode is `json`
Subagent definitions to attach to this agent
Subagent name
Execution mode: `fork` or `swarm`
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
System prompt used to instruct the agent
Model-specific settings such as temperature and max tokens
Runtime binding configuration for tools and data sources
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "Support Assistant",
"custom_id": "support-assistant-v1",
"description": "Handles customer support inquiries using knowledge base",
"metadata": {
"team": "customer-success",
"tier": "production"
},
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text"
},
"subagents": [
{
"name": "ticket-creator",
"mode": "fork",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
}
}'
```
### Response
Unique agent identifier
Agent name
Agent description
Arbitrary key-value pairs for storing additional agent information
Current active version number
Model used by the agent
List of capability identifiers the agent supports
Execution policies that constrain agent behavior
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for the agent
Output mode
JSON Schema for structured output
Subagent definitions attached to this agent
Subagent name
Execution mode: `fork` or `swarm`
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills attached to this agent
Skill identifier
Skill version number
Custom identifier for external system integration
Actor identifier associated with this agent
Latest version number available for this agent
System prompt used to instruct the agent
Model-specific settings such as temperature and max tokens
Runtime binding configuration for tools and data sources
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"name": "Support Assistant",
"description": "Handles customer support inquiries using knowledge base",
"metadata": {
"team": "customer-success",
"tier": "production"
},
"version": 1,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "fork",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [],
"custom_id": "support-assistant-v1",
"actor_id": "actor-9ad7a492416c6a8197f42a64b0a4a2d2",
"latest_version": 1,
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-03-10T09:00:00Z",
"updated_at": "2025-03-10T09:00:00Z"
}
}
```
# Get Agent
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/get-agent
Retrieve an agent by ID or custom ID
```
GET /openapi/memorylake/api/v3/agents/{id}
```
Retrieves a single agent. By default, the `id` path parameter is matched against the internal agent ID. Set `by_custom_id=true` to look up the agent by its custom identifier instead.
**Permission required:** `agent:read`
### Path Parameters
Agent identifier. Interpreted as the internal ID by default, or as the custom ID when `by_custom_id` is `true`.
### Query Parameters
When `true`, the `id` path parameter is matched against the agent's `custom_id` instead of its internal `id`.
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents/agt_r8k2m1n3' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique agent identifier
Agent name
Agent description
Arbitrary key-value pairs for storing additional agent information
Current active version number
Model used by the agent
List of capability identifiers the agent supports
Execution policies that constrain agent behavior
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for the agent
Output mode
JSON Schema for structured output
Subagent definitions attached to this agent
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills attached to this agent
Skill identifier
Skill version number
Custom identifier for external system integration
Actor identifier associated with this agent
Latest version number available for this agent
System prompt used to instruct the agent
Model-specific settings such as temperature and max tokens
Runtime binding configuration for tools and data sources
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"name": "Support Assistant",
"description": "Handles customer support inquiries using knowledge base",
"metadata": {
"team": "customer-success",
"tier": "production"
},
"version": 3,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "delegate",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 2
}
],
"custom_id": "support-assistant-v1",
"actor_id": "actor-9ad7a492416c6a8197f42a64b0a4a2d2",
"latest_version": 3,
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-03-10T09:00:00Z",
"updated_at": "2025-04-22T14:30:00Z"
}
}
```
# List Agents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/list-agents
Returns a paginated list of agents with optional name search
```
GET /openapi/memorylake/api/v3/agents
```
Returns a paginated list of all agents in your account. You can search by name with `name_fuzzy` and control pagination with `page_size` and `continuation_token`.
**Permission required:** `agent:read` — rows you cannot open are left out of the list rather than the list being refused
### Query Parameters
Number of agents to return per page
Token from a previous response to fetch the next page of results
Fuzzy match on agent name
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of agent objects
Unique agent identifier
Agent name
Agent description
Arbitrary key-value pairs for storing additional agent information
Current active version number
Model used by the agent (e.g. `gpt-4o`, `claude-sonnet-4-20250514`)
List of capability identifiers the agent supports
Execution policies that constrain agent behavior
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for the agent
Output mode (e.g. `text`, `json`)
JSON Schema that the agent's output must conform to when mode is `json`
Subagent definitions attached to this agent
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills attached to this agent
Skill identifier
Skill version number
Custom identifier for external system integration
Actor identifier associated with this agent
Latest version number available for this agent
System prompt used to instruct the agent
Model-specific settings such as temperature and max tokens
Runtime binding configuration for tools and data sources
Creation timestamp
Last update timestamp
Token to retrieve the next page of results. Absent when there are no more pages.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"name": "Support Assistant",
"description": "Handles customer support inquiries using knowledge base",
"metadata": {
"team": "customer-success",
"tier": "production"
},
"version": 3,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "delegate",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 2
}
],
"custom_id": "support-assistant-v1",
"actor_id": "actor-9ad7a492416c6a8197f42a64b0a4a2d2",
"latest_version": 3,
"system_prompt": "You are a helpful support assistant...",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-03-10T09:00:00Z",
"updated_at": "2025-04-22T14:30:00Z"
}
],
"continuation_token": "eyJsYXN0SWQiOiJhZ3RfcjhrMm0xbjMifQ"
}
}
```
# Overview
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/overview
Agents are AI agent definitions with versioning, workspace binding, and A2A protocol support
An **Agent** is a configurable AI agent definition in MemoryLake. Each agent has a model, system prompt, capabilities, and execution policies. When you create an agent, MemoryLake automatically generates an [Actor](/features/memorylake/api-reference/actors/overview) identity for it — because actors are the subject of memory, and agents need to accumulate knowledge just like human users do.
## Key Concepts
### Versioning
Agent configuration is versioned. When you change the model, system prompt, or policies, you [create a new version](/features/memorylake/api-reference/agents/create-agent-version) rather than modifying the existing one. This gives you a history of configurations and the ability to roll back.
Identity fields (name, description, metadata) are updated in place via [Update Agent](/features/memorylake/api-reference/agents/update-agent) — they don't create a new version.
### Workspace Binding
Agents are created globally, then [bound](/features/memorylake/api-reference/agents/bind-agent) to specific workspaces. An agent can only operate within workspaces it is bound to.
### Agent Memory
An agent accumulates facts of its own — what it has learned, and how it is meant to behave. They
live on the agent, read by its agent id within a workspace:
```
/api/v3/workspaces/{workspaceId}/agents/{agentId}/facts
```
The operations match the ones for a person's facts exactly — list, read, add, update, forget,
resolve conflicts — so [Actor Facts](/features/memorylake/api-reference/facts/list-actor-facts)
documents the shapes for both. For how agent facts sit alongside the other scopes, see
[Memories](/features/memorylake/memories/overview).
### A2A Protocol
MemoryLake agents are accessible via the standard [A2A (Agent-to-Agent) protocol](/features/memorylake/api-reference/a2a/overview). Use any A2A-compatible client to send messages to an agent, with MemoryLake's `metadata.memorylake` extension providing memory context (actor identity, project bindings, model overrides).
## Endpoints
| Operation | Method | Path |
| - | - | - |
| [List Agents](/features/memorylake/api-reference/agents/list-agents) | `GET` | `/api/v3/agents` |
| [Create Agent](/features/memorylake/api-reference/agents/create-agent) | `POST` | `/api/v3/agents` |
| [Get Agent](/features/memorylake/api-reference/agents/get-agent) | `GET` | `/api/v3/agents/{id}` |
| [Update Agent](/features/memorylake/api-reference/agents/update-agent) | `PATCH` | `/api/v3/agents/{id}` |
| [Delete Agent](/features/memorylake/api-reference/agents/delete-agent) | `DELETE` | `/api/v3/agents/{id}` |
| [Create Version](/features/memorylake/api-reference/agents/create-agent-version) | `POST` | `/api/v3/agents/{id}/versions` |
| [Bind to Workspace](/features/memorylake/api-reference/agents/bind-agent) | `POST` | `/api/v3/workspaces/{id}/agents` |
# API Authentication
Source: https://docs.memorylake.ai/features/memorylake/api-reference/authentication
Authenticate your API requests to MemoryLake services
## Authentication
All API requests require an API key passed via the `Authorization` header.
### Obtaining an API Key
1. Navigate to a project in the MemoryLake console
2. Go to the **API Keys** tab
3. Click **"Create API Key"**
4. Copy the generated secret (format: `sk_xxxxxx`)
The API key secret is shown only once at creation. Store it securely — it cannot be retrieved again.
### What a Key Can Do
A key is bound to exactly one team — the team it was created under. Nothing in a request can change that: there is no team parameter, and no header overrides it. If you belong to several teams, you hold one key per team, and you govern a team with that team's key.
Within its team, a key acts with its creator's role. This matters most on the [Management API](/features/management-api/overview), whose endpoints are authorized against what that person may do in the console — a member's key reads the team roster, an owner's key can also change it. If the creator loses a permission or leaves the team, their keys lose it too. A key that authenticates but lacks the required permission gets `403` with `ACCESS_DENIED`.
For automation that only needs to read, prefer a key created by a low-privilege member — or one issued for a [virtual member](/features/management-api/members/create-member). That is the cleanest way to limit what a leaked key can do.
### Using API Keys
Include the API key in the `Authorization` header:
```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```
### Example Request
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws_abc123' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json'
```
```javascript Node.js theme={null}
const response = await fetch(
'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws_abc123',
{
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
}
}
);
const data = await response.json();
```
```python Python theme={null}
import requests
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
response = requests.get(
'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws_abc123',
headers=headers
)
data = response.json()
```
### Response
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "ws-8001856949ad4f6a5b6226f415ffa877",
"name": "My Workspace",
"description": "Research workspace"
}
}
```
```json Error (401) theme={null}
{
"success": false,
"message": "Invalid or missing API key",
"error_code": "UNAUTHORIZED"
}
```
## Error Responses
### 401 Unauthorized
Returned when the API key is missing or invalid:
```json theme={null}
{
"success": false,
"message": "Unauthorized access",
"error_code": "UNAUTHORIZED"
}
```
**Solutions**:
* Verify API key is included in Authorization header
* Check header format: `Bearer YOUR_KEY`
* Ensure key hasn't been deleted
* Generate new key if lost
### 403 Forbidden
Returned when authentication is valid but the API key lacks sufficient permissions:
```json theme={null}
{
"success": false,
"message": "Access denied to this resource",
"error_code": "FORBIDDEN"
}
```
**Solutions**:
* Verify project ID is correct
* Check API key is for the correct project
* Ensure resource exists
## Security Best Practices
* Store API keys in environment variables
* Never commit keys to version control
* Use secrets management services
* Rotate keys periodically
* Create separate keys per environment
* Use descriptive names for keys
* Delete unused keys promptly
* Monitor key usage
* Always use HTTPS
* Don't log API keys
* Implement request timeouts
* Handle errors gracefully
## Next Steps
Start with the core APIs
Handle API errors
# Batch Get Messages
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/batch-get-messages
Retrieve multiple messages by their entry IDs
```
POST /openapi/memorylake/api/v3/conversations/{conversationId}/messages/batch-get
```
Retrieves multiple messages from a conversation in a single request. Pass a list of message entry IDs and receive the corresponding messages. This is more efficient than calling Get Message individually when you need several specific messages.
**Permission required:** `workspace:conv_read`
### Path Parameters
Conversation identifier
### Request Body
List of message entry IDs to retrieve. Maximum 100 entries per request.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-4f42addb6cb69d6ee7de2451cb590e06/messages/batch-get' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"entry_ids": [
"msg_3f4a5b6c7d8e9f0a",
"msg_9e4b2c3d5f6a7b8c"
]
}'
```
### Response
Array of message objects matching the requested entry IDs
Unique message identifier
Array of content blocks
Block type: `TEXT`, `FILE`, `IMAGE`, `THINKING`, `TOOL_USE`, `TOOL_RESULT`
Text content (present when `block_type` is `TEXT`)
Drive resource URI (present when `block_type` is `IMAGE`)
MIME type (present when `block_type` is `IMAGE`)
Arbitrary key-value metadata attached to the message
Caller-provided timestamp (ISO 8601)
ID of the conversation this message belongs to
Position of this message within the conversation
ID of the actor who sent this message
Creation timestamp
```json Success (200) theme={null}
{
"success": true,
"data": [
{
"id": "msg_3f4a5b6c7d8e9f0a",
"content": [
{
"block_type": "TEXT",
"text": "Can you summarize last quarter's revenue numbers?"
}
],
"metadata": {},
"timestamp": "2025-06-01T14:10:00Z",
"conversation_id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"sequence_no": 3,
"actor_id": "actor-93688d5ec8d2e98701be3d5554cbc455",
"created_at": "2025-06-01T14:10:05Z"
},
{
"id": "msg_9e4b2c3d5f6a7b8c",
"content": [
{
"block_type": "TEXT",
"text": "Q1 revenue was $12.5M, up 15% from the previous quarter."
}
],
"metadata": {},
"timestamp": "2025-06-01T14:10:30Z",
"conversation_id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"sequence_no": 4,
"actor_id": "actor-9831773f1353358f4196b22505d879e0",
"created_at": "2025-06-01T14:10:32Z"
}
]
}
```
# Create Conversation
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/create-conversation
Create a new conversation in a workspace
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/memories/conversations
```
Creates a new conversation within a workspace. A conversation groups related messages together so MemoryLake can extract structured facts from the exchange. You must attach exactly one read-write project via `rw_project_ids` — this is the project where extracted facts and memory are stored.
**Permission required:** `workspace:conv_create` on the workspace, plus one set per participant you name — on each project in `rw_project_ids`: `project:mem_add`, `project:doc_add`, `project:mem_search` and `project:doc_search`; on each actor in `actor_ids`: `workspace_actor:fact_add` and `workspace_actor:fact_search`; on each agent in `agent_ids`: `workspace_agent:fact_add` and `workspace_agent:fact_search`. A conversation both writes memories and reads them back, which is why each participant needs the add and the search half.
### Path Parameters
Workspace identifier
### Request Body
Your own identifier for this conversation — the one it already has in your system. Must be unique within your tenant. Pass `by_custom_id=true` on later requests to address the conversation by it instead of by `id`. See [Your own identifiers](/features/memorylake/api-reference/overview#your-own-identifiers).
Conversation kind: `DIRECT` (one-on-one) or `GROUP` (multi-participant).
Read-write project(s) the conversation reads context from and writes facts to. Exactly one project ID is required.
Actors participating in this conversation. At least one participant is required across `actor_ids` and `agent_ids`: a participant is what a message is attributed to and whose memory the conversation writes to, so a conversation without one can neither tell its participants apart nor build anyone's memory.
Agents taking part in the conversation.
Display name for the conversation
Arbitrary key-value metadata to attach to the conversation
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/memories/conversations' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"custom_id": "session-20250601-042",
"name": "Product Feedback Call",
"kind": "DIRECT",
"rw_project_ids": ["proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"],
"metadata": {
"channel": "zoom",
"language": "en"
},
"actor_ids": ["actor-93688d5ec8d2e98701be3d5554cbc455", "actor-9831773f1353358f4196b22505d879e0"]
}'
```
### Response
Unique conversation identifier
Display name for the conversation
Conversation kind: `DIRECT` or `GROUP`
Arbitrary key-value metadata attached to the conversation
Caller-defined unique identifier
Read-write project(s) this conversation reads/writes memory to
IDs of actors participating in the conversation
ID of the latest message in the conversation
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"name": "Product Feedback Call",
"kind": "DIRECT",
"metadata": {
"channel": "zoom",
"language": "en"
},
"custom_id": "session-20250601-042",
"rw_project_ids": ["proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"],
"actor_ids": ["actor-93688d5ec8d2e98701be3d5554cbc455", "actor-9831773f1353358f4196b22505d879e0"],
"current_message_id": null,
"created_at": "2025-06-01T14:00:00Z",
"updated_at": "2025-06-01T14:00:00Z"
}
}
```
# Append Conversation Message
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/create-message
Append a message to a conversation
```
POST /openapi/memorylake/api/v3/conversations/{conversationId}/messages
```
Appends a new message to a conversation. Each message contains one or more content blocks (text, file, or both) and is attributed to an actor. MemoryLake automatically processes new messages to extract structured facts.
**Permission required:** `workspace:conv_append`
### Path Parameters
Conversation identifier
### Request Body
Array of content blocks that make up the message body. Each block must include a `block_type` field.
Accepted `block_type` values: `TEXT`, `FILE`, `IMAGE`, `THINKING`, `TOOL_USE`, `TOOL_RESULT`.
**Text block:** `{ "block_type": "TEXT", "text": "message content" }`
**Image block:** `{ "block_type": "IMAGE", "uri": "drive://...", "mime_type": "image/png" }`
ID of the actor sending this message. Should reference an actor participating in the conversation.
Identifier of the agent that sent this message. Provide exactly one of `actor_id` or `agent_id`.
ISO 8601 timestamp for when the message originally occurred. Use this when ingesting historical conversations so MemoryLake preserves the original timeline.
Arbitrary key-value metadata to attach to the message
Caller-defined unique identifier for the message within the conversation
ID of the message that comes immediately before this one in the conversation — its predecessor. This is an ordering pointer, not a reply pointer: pass the previous message's ID even when the new message is not a reply to it. Order is declared by you, never guessed by the server.
Send `null` for the first message of a conversation, which has no predecessor. Every message after that must carry a real ID — the `id` returned when you appended the previous message, or the conversation's `current_message_id` when you resume an existing conversation.
That ID must still be the conversation's latest message when the request arrives. If it is not — a stale ID, or `null` on a conversation that already has messages — the append fails with `409` and nothing is written. Re-read `current_message_id` and retry with that value.
```bash Text message theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-4f42addb6cb69d6ee7de2451cb590e06/messages' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"content": [
{
"block_type": "TEXT",
"text": "Can you summarize last quarter'\''s revenue numbers?"
}
],
"custom_id": "msg-001",
"actor_id": "actor-93688d5ec8d2e98701be3d5554cbc455",
"parent_message_id": null,
"timestamp": "2025-06-01T14:10:00Z",
"metadata": {
"source": "web-app"
}
}'
```
```bash Image attachment theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-4f42addb6cb69d6ee7de2451cb590e06/messages' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"content": [
{
"block_type": "TEXT",
"text": "Here is the chart for your review."
},
{
"block_type": "IMAGE",
"uri": "drive://items/item_abc123/chart.png",
"mime_type": "image/png"
}
],
"custom_id": "msg-002",
"actor_id": "actor-9831773f1353358f4196b22505d879e0",
"parent_message_id": "msg_3f4a5b6c7d8e9f0a",
"timestamp": "2025-06-01T14:10:30Z"
}'
```
```bash Follow-up message theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-4f42addb6cb69d6ee7de2451cb590e06/messages' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"content": [
{
"block_type": "TEXT",
"text": "Good point — I'\''ve updated the figures in the attached version."
}
],
"custom_id": "msg-003",
"actor_id": "actor-93688d5ec8d2e98701be3d5554cbc455",
"parent_message_id": "msg_9e4b2c3d5f6a7b8c"
}'
```
### Response
Unique message identifier
Array of content blocks that make up the message body
Block type: `TEXT`, `FILE`, `IMAGE`, `THINKING`, `TOOL_USE`, `TOOL_RESULT`
Text content (present when `block_type` is `TEXT`)
Drive resource URI (present when `block_type` is `IMAGE`)
MIME type of the image (present when `block_type` is `IMAGE`)
Arbitrary key-value metadata attached to the message
Caller-provided timestamp for when the message originally occurred (ISO 8601)
ID of the conversation this message belongs to
Position of this message within the conversation
ID of the actor who sent this message
Creation timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "msg_3f4a5b6c7d8e9f0a",
"content": [
{
"block_type": "TEXT",
"text": "Can you summarize last quarter's revenue numbers?"
}
],
"metadata": {
"source": "web-app"
},
"timestamp": "2025-06-01T14:10:00Z",
"conversation_id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"sequence_no": 1,
"actor_id": "actor-93688d5ec8d2e98701be3d5554cbc455",
"created_at": "2025-06-01T14:10:05Z"
}
}
```
# Delete Conversation
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/delete-conversation
Permanently delete a conversation and all its messages
```
DELETE /openapi/memorylake/api/v3/workspaces/{workspaceId}/memories/conversations/{conversationId}
```
This is a destructive operation. The conversation and all its messages will be permanently removed.
Permanently deletes a conversation and all messages it contains. Facts that were previously extracted from the conversation's messages are not affected.
**Permission required:** `workspace:conv_delete`
### Path Parameters
Workspace identifier
Conversation identifier
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/memories/conversations/conv_7d2e3f4a5b6c7d8e' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Conversation deleted successfully"
}
```
# Get Conversation
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/get-conversation
Retrieve a conversation by ID or custom ID
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/memories/conversations/{conversationId}
```
Retrieves a single conversation by its ID. You can also look up a conversation by its `custom_id` by setting the `by_custom_id` query parameter to `true`.
**Permission required:** `workspace:conv_read`
### Path Parameters
Workspace identifier
Conversation ID, or the `custom_id` value if `by_custom_id` is `true`
### Query Parameters
When `true`, treat the `conversationId` path parameter as a `custom_id` lookup instead of the internal ID
```bash By ID theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/memories/conversations/conv_7d2e3f4a5b6c7d8e' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash By custom_id theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/memories/conversations/session-20250601-042?by_custom_id=true' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique conversation identifier
Display name for the conversation
Conversation kind: `DIRECT` or `GROUP`
Arbitrary key-value metadata attached to the conversation
Caller-defined unique identifier for external reference
Read-write project(s) this conversation reads/writes memory to
IDs of actors participating in the conversation
ID of the latest message in the conversation
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"name": "Product Feedback Call",
"kind": "DIRECT",
"metadata": {
"channel": "zoom",
"language": "en"
},
"custom_id": "session-20250601-042",
"rw_project_ids": ["proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"],
"actor_ids": ["actor-93688d5ec8d2e98701be3d5554cbc455", "actor_interviewer_alex"],
"current_message_id": "msg_9e4b2c3d5f6a7b8c",
"created_at": "2025-06-01T14:00:00Z",
"updated_at": "2025-06-01T14:32:00Z"
}
}
```
# List Conversations
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/list-conversations
Returns a paginated list of conversations in a workspace
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/memories/conversations
```
Returns a paginated list of conversations within a workspace. Use continuation tokens to iterate through large result sets.
**Permission required:** `workspace:conv_read`
### Path Parameters
Workspace identifier
### Query Parameters
Number of conversations to return per page
Token from a previous response to fetch the next page of results
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/memories/conversations?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of conversation objects
Unique conversation identifier
Display name for the conversation
Conversation kind: `DIRECT` or `GROUP`
Arbitrary key-value metadata attached to the conversation
Caller-defined unique identifier for external reference
Read-write project(s) this conversation reads/writes memory to
IDs of actors participating in the conversation
ID of the latest message in the conversation
Creation timestamp
Last update timestamp
Token to retrieve the next page. `null` when there are no more results.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "conv-b03d4e0bf663000c7bafdc724a11eb3f",
"name": "Onboarding Session",
"kind": "DIRECT",
"metadata": {
"channel": "web",
"language": "en"
},
"custom_id": "session-20250601-001",
"rw_project_ids": ["proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"],
"actor_ids": ["actor-93688d5ec8d2e98701be3d5554cbc455", "actor-9831773f1353358f4196b22505d879e0"],
"current_message_id": "msg_9e4b2c3d5f6a7b8c",
"created_at": "2025-06-01T09:15:00Z",
"updated_at": "2025-06-01T09:42:00Z"
}
],
"continuation_token": "eyJsYXN0X2lkIjoiY29udl84ZjNhMWIyYzRkNWU2ZjdhIn0"
}
}
```
# List Messages
Source: https://docs.memorylake.ai/features/memorylake/api-reference/conversations/list-messages
Returns a paginated list of messages in a conversation
```
GET /openapi/memorylake/api/v3/conversations/{conversationId}/messages
```
Returns a paginated list of messages within a conversation, ordered by sequence number. Use `continuation_token` to page through the full history.
**Permission required:** `workspace:conv_read`
### Path Parameters
Conversation identifier
### Query Parameters
Number of messages to return per page
Token from a previous response to fetch the next page of results
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-4f42addb6cb69d6ee7de2451cb590e06/messages?page_size=50' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of message objects
Unique message identifier
Array of content blocks that make up the message body
Block type: `TEXT`, `FILE`, `IMAGE`, `THINKING`, `TOOL_USE`, `TOOL_RESULT`
Text content (present when `block_type` is `TEXT`)
Arbitrary key-value metadata attached to the message
Caller-provided timestamp for when the message originally occurred (ISO 8601)
ID of the conversation this message belongs to
Position of this message within the conversation, starting at 1
ID of the actor who sent this message
Creation timestamp
Token to retrieve the next page. `null` when there are no more results.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "msg_1a2b3c4d5e6f7a8b",
"content": [
{
"block_type": "TEXT",
"text": "Hi, I'd like to learn more about your enterprise plan."
}
],
"metadata": {},
"timestamp": "2025-06-01T14:05:00Z",
"conversation_id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"sequence_no": 1,
"actor_id": "actor-93688d5ec8d2e98701be3d5554cbc455",
"created_at": "2025-06-01T14:05:12Z"
},
{
"id": "msg_9e4b2c3d5f6a7b8c",
"content": [
{
"block_type": "TEXT",
"text": "Of course! Our enterprise plan includes dedicated support, custom integrations, and advanced analytics. Would you like me to walk you through the details?"
}
],
"metadata": {},
"timestamp": "2025-06-01T14:05:30Z",
"conversation_id": "conv-4f42addb6cb69d6ee7de2451cb590e06",
"sequence_no": 2,
"actor_id": "actor-9831773f1353358f4196b22505d879e0",
"created_at": "2025-06-01T14:05:35Z"
}
],
"continuation_token": null
}
}
```
# Overview
Source: https://docs.memorylake.ai/features/memorylake/api-reference/core-memory/overview
The essential APIs for feeding and querying memories in MemoryLake
MemoryLake turns your documents and conversations into searchable, structured memories. These four APIs are the core of that capability.
## How It Works
Before using the core APIs, create the required resources:
1. [Create a Workspace](/features/memorylake/api-reference/workspaces/create-workspace) — the namespace that isolates your data
2. [Create an Actor](/features/memorylake/api-reference/actors/create-actor) — the identity representing your end user
3. [Create a Project](/features/memorylake/api-reference/v3-projects/create-project) — the container for documents, conversations, and facts
Import knowledge into a project through two channels:
* **Documents** — upload files to the [Library](/features/memorylake/api-reference/library/overview), then [import them](/features/memorylake/api-reference/v3-documents/import-documents) into a project. MemoryLake indexes the content for semantic search.
* **Conversations** — [create a conversation](/features/memorylake/api-reference/conversations/create-conversation), then [append messages](/features/memorylake/api-reference/conversations/create-message). MemoryLake automatically extracts structured facts from the exchange.
[Search](/features/memorylake/api-reference/search/search-memories) across all memory sources in a workspace using natural language. Results include matched document passages and extracted facts.
## Core APIs
Import files from the Library into a project for indexing.
Start a new conversation in a project to capture interactions.
Add a message to a conversation. Facts are extracted automatically.
Query documents and facts across a workspace with natural language.
# Batch Forget Actor Facts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/batch-forget-actor-facts
Mark multiple actor-level facts as forgotten in a single request
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/facts/forget
```
Marks multiple actor-level facts as forgotten (expired) in a single request. Like [Forget Actor Fact](/features/memorylake/api-reference/facts/forget-actor-fact), this is a soft delete -- facts remain available for audit purposes but are excluded from future retrievals and searches.
**Permission required:** `workspace_actor:fact_delete` on a person's memories, or `workspace_agent:fact_delete` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
### Request Body
Array of fact IDs to forget
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/actors/actor_5e4d3c2b1a0f/facts/forget' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
"fact-11a0e057d09877c9c492633fd60424fc",
"fact-9e6e9b323824eb264c1165994af65c1e",
"fact_9h8g7f6e5d4c"
]
}'
```
### Response
Returns an empty `data` object on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Forget Actor Fact
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/forget-actor-fact
Mark an actor-level fact as forgotten without deleting it
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/facts/{factId}/forget
```
Marks an actor-level fact as forgotten (expired) without permanently deleting it. The fact remains available for audit purposes but is excluded from future retrievals and searches. To forget multiple actor facts at once, use [Batch Forget Actor Facts](/features/memorylake/api-reference/facts/batch-forget-actor-facts).
**Permission required:** `workspace_actor:fact_delete` on a person's memories, or `workspace_agent:fact_delete` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
Fact ID to forget
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/actors/actor_5e4d3c2b1a0f/facts/fact-11a0e057d09877c9c492633fd60424fc/forget' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Returns an empty `data` object on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Get Actor Fact
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/get-actor-fact
Returns the content and metadata of a single actor-level fact
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/facts/{factId}
```
Returns the content and metadata of a single fact scoped to an actor.
**Permission required:** `workspace_actor:fact_read` on a person's memories, or `workspace_agent:fact_read` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
Fact ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/actors/actor_5e4d3c2b1a0f/facts/fact_4c5d6e7f8a9b' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
Relevance score
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "fact-11a0e057d09877c9c492633fd60424fc",
"fact": "User's primary programming language is Python",
"metadata": {
"category": "skills",
"confidence": "high"
},
"expired": false,
"score": 0.92,
"expiration_date": null,
"created_at": "2025-05-20T10:00:00Z",
"updated_at": "2025-05-20T10:00:00Z"
}
}
```
# List Actor Facts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/list-actor-facts
Returns a paginated list of facts for a specific actor
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/facts
```
Returns a paginated list of facts scoped to a specific actor. Actor facts are what the subject has accumulated across every project in the workspace. The id may be a person's or an agent's; the facts read the same either way.
**Permission required:** `workspace_actor:fact_read` on a person's memories, or `workspace_agent:fact_read` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
### Query Parameters
Number of facts to return per page. Range: 1–200.
Token from a previous response to fetch the next page of results
Filter facts by content substring
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/actors/actor_5e4d3c2b1a0f/facts?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of fact objects
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
Relevance score
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
Token to retrieve the next page. `null` when there are no more results.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "fact-11a0e057d09877c9c492633fd60424fc",
"fact": "User's primary programming language is Python",
"metadata": {
"category": "skills",
"confidence": "high"
},
"expired": false,
"score": 0.92,
"expiration_date": null,
"created_at": "2025-05-20T10:00:00Z",
"updated_at": "2025-05-20T10:00:00Z"
},
{
"id": "fact-9e6e9b323824eb264c1165994af65c1e",
"fact": "User works at a fintech startup with 50 employees",
"metadata": {
"category": "work"
},
"expired": false,
"score": 0.85,
"expiration_date": "2026-05-20T10:00:00Z",
"created_at": "2025-06-01T16:45:00Z",
"updated_at": "2025-06-01T16:45:00Z"
}
],
"continuation_token": "eyJsYXN0X2lkIjoiZmFjdF8xYTJiM2M0ZDVlNmYifQ"
}
}
```
# List Workspace Facts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/list-workspace-facts
Returns facts across projects and actors in a workspace
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/memories/facts
```
Returns facts across the given projects and/or actors in a workspace, newest first. Each fact is annotated with the project or actor it belongs to, so you can query knowledge workspace-wide without calling each project or actor endpoint separately.
At least one `project_ids` or `actor_ids` entry is required, and the two combined must reference at most 50 distinct projects/actors.
**Permission required:** one per kind of id you name — `project:mem_read` on each project in `project_ids`, `workspace_actor:fact_read` on each actor in `actor_ids`, and `workspace_agent:fact_read` on each agent in `agent_ids`. Naming something you may not read refuses the whole request; the list is not filtered down to what you can see.
### Path Parameters
Workspace ID
### Query Parameters
Project IDs to include; comma-separated (e.g. `proj-a,proj-b`)
Actor IDs to include; comma-separated (e.g. `actor-a,actor-b`)
Agent IDs whose facts to return; comma-separated.
Filter facts by content substring
Number of facts to return per page. Range: 1–200.
Token from a previous response to fetch the next page of results
```bash Facts from two projects theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/memories/facts?project_ids=proj_def456,proj_ghi789' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Facts from a project and an actor theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/memories/facts?project_ids=proj_def456&actor_ids=act-a1b2c3d4e5f6' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Filter by content theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/memories/facts?project_ids=proj_def456&fact_fuzzy=deadline' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of fact objects
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
The project or actor this fact belongs to
Owner type: `project` or `actor`
Owner ID: a project ID when `type` is `project`, an actor ID when `type` is `actor`
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
Token to retrieve the next page. `null` when there are no more results.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "fact-2fe07aee0058d141c744685a2d7272be",
"fact": "Project deadline was moved to June 2025",
"metadata": {
"category": "planning"
},
"expired": false,
"owner": {
"type": "project",
"id": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"
},
"expiration_date": null,
"created_at": "2025-06-10T14:30:00Z",
"updated_at": "2025-06-10T14:30:00Z"
},
{
"id": "fact-044bdc2ffcf8c7915aa9e79d5a10efd4",
"fact": "User prefers dark mode in all applications",
"metadata": {
"category": "preferences"
},
"expired": false,
"owner": {
"type": "actor",
"id": "actor-8d093c0578ffeb19f8fa10ea28ee9362"
},
"expiration_date": null,
"created_at": "2025-06-12T09:15:00Z",
"updated_at": "2025-06-12T09:15:00Z"
}
],
"continuation_token": null
}
}
```
# Update Actor Fact
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/update-actor-fact
Update the text or metadata of an existing actor-level fact
```
PATCH /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/facts/{factId}
```
Updates the text or metadata of an existing actor-level fact. You can modify the fact content, its metadata, or both.
**Permission required:** `workspace_actor:fact_modify` on a person's memories, or `workspace_agent:fact_modify` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
Fact ID
### Request Body
Updated fact text
Updated key-value metadata to attach to the fact
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/actors/actor_5e4d3c2b1a0f/facts/fact_4c5d6e7f8a9b' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"fact": "User is proficient in Python and TypeScript",
"metadata": {
"category": "skills",
"confidence": "high",
"verified": true
}
}'
```
### Response
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
Relevance score
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "fact-11a0e057d09877c9c492633fd60424fc",
"fact": "User is proficient in Python and TypeScript",
"metadata": {
"category": "skills",
"confidence": "high",
"verified": true
},
"expired": false,
"score": 0.92,
"expiration_date": null,
"created_at": "2025-05-20T10:00:00Z",
"updated_at": "2025-06-22T08:30:00Z"
}
}
```
# Create Item
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/create-item
Create a folder, or register a file after uploading its chunks
```
POST /openapi/memorylake/api/v1/drives/items
```
One endpoint, two modes — the `item_type` field selects which:
* **Folder** (`item_type: "folder"`) — creates an empty folder in the Library.
* **File** (`item_type: "file"`) — registers a file whose bytes are already in storage from a completed chunked upload. You must have called [Create Upload](/features/memorylake/api-reference/library/create-upload) first and collected every chunk's `ETag`.
Pick the tab below that matches the item type you're creating. Required fields differ by mode.
`parent_item_id` accepts the alias `MY_SPACE` (your workspace root). Pass it directly instead of looking up the root ID. You can also pass any folder's `item_id` to nest deeper.
**Permission required:** [`drive:item_add`](/features/team-collaboration/permission-reference#upload-and-create-files) · `service`
**Workflow note (file mode):** Calling this in `item_type: "file"` mode is step 2 of the Library upload flow; step 1 is [Create Upload](/features/memorylake/api-reference/library/create-upload) (same permission). If you then need the file to appear inside a project, call [Import Documents](/features/memorylake/api-reference/v3-documents/import-documents) — that additionally requires [`project:doc_add`](/features/team-collaboration/permission-reference#add-a-document-to-a-project).
### Request Body
Must be `"folder"`.
Parent folder — `MY_SPACE` or any folder's `item_id`.
Folder name, e.g. `Q2 Reports`.
Behavior if the name already exists in `parent_item_id`:
* `rename` *(default)* — append a numeric suffix (`Q2 Reports_1`).
* `deny` — fail with `409 DRIVE_ITEM_CONFLICT`.
Extended attributes — a `string → string` map for caller-defined metadata.
This call finalizes an upload you opened earlier — it does not transfer bytes. Before you reach here you should have:
1. Called [Create Upload](/features/memorylake/api-reference/library/create-upload) with `file_size` and received an `upload_id` + one pre-signed URL per chunk.
2. PUT every chunk to its URL and saved the `ETag` header of each response.
Must be `"file"`.
Parent folder — `MY_SPACE` or any folder's `item_id`.
File name, e.g. `report.pdf`.
Reference to the completed chunked upload.
The `upload_id` returned by [Create Upload](/features/memorylake/api-reference/library/create-upload).
One entry per uploaded chunk. Include every chunk, in order.
Chunk number (1-based). Must match the `number` from the upload session.
`ETag` header value returned when you PUT that chunk.
Behavior if the name already exists in `parent_item_id`:
* `rename` *(default)* — append a numeric suffix (`report_1.pdf`).
* `deny` — fail with `409 DRIVE_ITEM_CONFLICT`.
* `overwrite` — overwrite the existing file's content in the Library. The existing `item_id` is **preserved**.
* `replace` — delete the existing file and create a new one. A **new `item_id`** is issued; prior references to the old ID become stale.
`overwrite` only replaces the file bytes stored in the Library — it does **not** re-process or re-index any project documents that were previously imported from the file. To propagate new content into a project, call [Import Documents](/features/memorylake/api-reference/v3-documents/import-documents) again after the overwrite (or use a fresh file).
Extended attributes — a `string → string` map for caller-defined metadata.
```bash Create folder theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"item_type": "folder",
"parent_item_id": "MY_SPACE",
"name": "Q2 Reports"
}'
```
```bash Create file theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"item_type": "file",
"parent_item_id": "MY_SPACE",
"name": "report.pdf",
"from": {
"upload_id": "upl-abc123def456",
"part_etags": [
{ "number": 1, "etag": "d41d8cd98f00b204e9800998ecf8427e" },
{ "number": 2, "etag": "f6e5d4c3b2a10987f6e5d4c3b2a10987" }
]
}
}'
```
### Response
The response shape is the same for folders and files.
Drive resource URI of the created item
ID of the resulting item. With `overwrite`, this equals the existing file's `item_id` (preserved). With `replace`, `rename`, or a fresh creation, a new `item_id` is issued.
Effective name. Differs from the requested `name` when `rename` produced an auto-suffix.
```json Success (200) theme={null}
{
"success": true,
"data": {
"uri": "drive://items/sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"name": "report.pdf"
}
}
```
Always read `name` from the response. With the default `rename` strategy, the server may have appended a suffix — the returned `name` is what you should display and store.
# Create Upload
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/create-upload
Create a chunked upload session and receive pre-signed PUT URLs for each chunk
```
POST /openapi/memorylake/api/v1/drives/items/upload
```
Creates a chunked upload session. The response contains an `upload_id` and one pre-signed `PUT` URL per chunk. You then upload each chunk directly to its URL, save the returned `ETag`, and finally call [Create Item](/features/memorylake/api-reference/library/create-item) with `item_type: "file"` and `from: { upload_id, part_etags }` to materialize the file in the Library.
This endpoint only reserves storage and returns URLs — it does not move any bytes. The file is not visible in the Library until Create Item succeeds.
**Permission required:** [`drive:item_add`](/features/team-collaboration/permission-reference#upload-and-create-files) · `service`
**Workflow note:** This is step 1 of the Library upload flow. Step 2 is [Create Item](/features/memorylake/api-reference/library/create-item) (same permission). To then attach the file to a project, call [Import Documents](/features/memorylake/api-reference/v3-documents/import-documents), which additionally requires [`project:doc_add`](/features/team-collaboration/permission-reference#add-a-document-to-a-project).
### Request Body
Total file size in bytes. Minimum `1`. The server uses this to decide the chunk layout — number of parts and each part's byte range.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/upload' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"file_size": 10485760
}'
```
### Response
Upload token. Pass back inside `from.upload_id` when creating the file item.
Array of chunks to upload, in order
Chunk number (1-based)
Number of bytes to PUT for this chunk
Pre-signed PUT URL for this chunk
```json Success (200) theme={null}
{
"success": true,
"data": {
"upload_id": "upl-abc123def456",
"part_items": [
{
"number": 1,
"size": 5242880,
"upload_url": "https://storage.example.com/upload?partNumber=1&uploadId=upl-abc123def456"
},
{
"number": 2,
"size": 5242880,
"upload_url": "https://storage.example.com/upload?partNumber=2&uploadId=upl-abc123def456"
}
]
}
}
```
## Uploading chunks
After this call returns, `PUT` each chunk to its `upload_url`. The response to every PUT contains an `ETag` header — you must collect all of them, in order, to complete the upload.
```bash theme={null}
# Read part 1's bytes and PUT them
curl -X PUT 'https://storage.example.com/upload?partNumber=1&uploadId=upl-abc123def456' \
--data-binary @part1.bin -D -
# → ETag: "d41d8cd98f00b204e9800998ecf8427e"
```
Do not send an `Authorization` header when PUTing to `upload_url` — the URL is already pre-signed. Sending bearer auth may cause the PUT to be rejected by the storage backend.
Pre-signed URLs expire. Finish uploading all chunks and call Create Item promptly after creating the upload session. If URLs expire before you finalize, simply create a new upload session and restart.
## Next Step
Finalize the upload by creating a `file` item that references this upload's `upload_id` and the collected `part_etags`.
# Delete Item
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/delete-item
Delete a file or folder from the Library (recursive for folders)
```
DELETE /openapi/memorylake/api/v1/drives/items/{item_id}
```
Permanently deletes a file or folder. Deleting a folder also deletes **everything inside it**, recursively.
This is destructive and irreversible. If the item is a folder, every file and subfolder under it is removed. Confirm with the user before calling this endpoint.
Deleting a file that is referenced by one or more project documents does not automatically remove those documents. Call [Delete Documents](/features/memorylake/api-reference/v3-documents/delete-documents) first if you want the documents to disappear from a project.
**Permission required:** [`drive:item_delete`](/features/team-collaboration/permission-reference#delete-files) · `service`
### Path Parameters
Concrete item ID to delete. Your workspace root (`MY_SPACE`) cannot be deleted.
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully"
}
```
# Delete Item Xattrs
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/delete-item-xattrs
Remove specific extended attribute keys from a Library item
```
DELETE /openapi/memorylake/api/v1/drives/items/{item_id}/xattrs?key={comma-separated-keys}
```
Removes one or more extended attribute keys from a Library file or folder. Only the keys you list are removed; any other xattrs on the item stay where they are.
This is irreversible. The listed xattr values are gone after the call. The item itself is **not** affected — only the listed metadata keys.
System-reserved xattr keys cannot be deleted; including them in the `key` list is rejected. The system root folders (`My Space`, `WPS Space`, `Lark Space`) refuse xattr deletion entirely and return `403`.
**Permission required:** [`drive:item_modify`](/features/team-collaboration/permission-reference#edit-your-files) · `service`
### Path Parameters
ID of the file or folder to remove xattrs from.
### Query Parameters
Comma-separated list of xattr keys to delete, e.g. `key=tenant_id,review_status`. At least one key is required.
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5/xattrs?key=tenant_id,review_status' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully"
}
```
To verify which xattrs remain on the item afterwards, call [Get Item](/features/memorylake/api-reference/library/get-item) — its response includes the current `x_attrs` map.
# Get Item
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/get-item
Look up a file or folder in the Library by its ID
```
GET /openapi/memorylake/api/v1/drives/items/{item_id}
```
Returns metadata for a single Library item. Use this to inspect a file before importing it into a project, to resolve `MY_SPACE` into a concrete ID, or to check whether an item exists.
**Permission required:** [`drive:item_read`](/features/team-collaboration/permission-reference#read-your-files) · `service`
### Path Parameters
Item ID. Pass `MY_SPACE` to look up your workspace root without needing its concrete ID.
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/MY_SPACE' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Drive resource URI
Item ID
Item name
Item type: `file` or `directory`
File size in bytes (files only)
ETag for the item
Parent item ID
Creation timestamp
Last update timestamp
Extended attributes (string → string map)
```json Success (200) theme={null}
{
"success": true,
"data": {
"item": {
"uri": "drive://items/sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"name": "report.pdf",
"type": "file",
"size": 10485760,
"etag": "d41d8cd98f00b204e9800998ecf8427e",
"parent_item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:root",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"x_attrs": {}
}
}
}
```
# List Items
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/list-items
List the files and folders directly under a folder in the Library
```
GET /openapi/memorylake/api/v1/drives/items/{item_id}/children
```
Returns the items (files and folders) directly under a folder. Uses cursor pagination: if `continuation_token` is returned, pass it back on the next request to fetch the next page. When the token is absent from the response, you've reached the end.
**Permission required:** [`drive:item_read`](/features/team-collaboration/permission-reference#read-your-files) · `service`
### Path Parameters
Parent folder. Pass `MY_SPACE` for your workspace root, or any folder's `item_id` to list its contents.
### Query Parameters
Items per page, 1–50. Defaults to 50 when omitted.
Token returned by the previous call. Omit on the first request.
```bash First page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/MY_SPACE/children?page_size=50' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Next page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/MY_SPACE/children?page_size=50&continuation_token=Y6Wa982_Jj_A9-Kw40' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of library items
Drive resource URI
Item ID
Item name
Item type: `file` or `directory`
File size in bytes (files only)
ETag for the item
Parent item ID
Creation timestamp
Last update timestamp
Extended attributes (string → string map)
Token for the next page. Absent or `null` when this is the last page.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"uri": "drive://items/sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"name": "Reports",
"type": "directory",
"parent_item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:root",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"x_attrs": {}
},
{
"uri": "drive://items/sc-5c6bf0f82d624a20a6fa4696997bdd46:2a8cf1e93f634b31b7",
"item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:2a8cf1e93f634b31b7",
"name": "report.pdf",
"type": "file",
"size": 10485760,
"etag": "d41d8cd98f00b204e9800998ecf8427e",
"parent_item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:root",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"x_attrs": {}
}
],
"continuation_token": "Y6Wa982_Jj_A9-Kw40"
}
}
```
### Iterating every page
```python theme={null}
import requests
BASE = "https://app.memorylake.ai/openapi/memorylake/api/v1"
HEADERS = {"Authorization": "Bearer sk_xxxxxx"}
def list_all(parent_id: str):
token = None
while True:
params = {"page_size": 50}
if token:
params["continuation_token"] = token
resp = requests.get(
f"{BASE}/drives/items/{parent_id}/children",
headers=HEADERS, params=params,
).json()["data"]
yield from resp["items"]
token = resp.get("continuation_token")
if not token:
break
```
# Overview
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/overview
Manage files and folders in the Library — the storage layer behind MemoryLake projects
## What is the Library?
The **Library** is a unified file system that holds every file MemoryLake can see. Project documents are always created by referencing a file that already lives in the Library.
Your top-level writable folder is **`MY_SPACE`** — treat it as the root of your workspace. Every file or folder you create is placed under `MY_SPACE` (directly or nested inside a subfolder).
A typical integration flow looks like this:
Use the alias `MY_SPACE` to target your workspace root directly, or pass the `item_id` of any subfolder you've created under it.
Chunked upload: [create an upload session](/features/memorylake/api-reference/library/create-upload), PUT each chunk, then [create the file item](/features/memorylake/api-reference/library/create-item).
Call [Import Documents](/features/memorylake/api-reference/v3-documents/import-documents) with the `item_id` returned from the previous step.
## Base URL
```
https://app.memorylake.ai/openapi/memorylake
```
## Item ID Aliases
Anywhere an `item_id` is accepted, you can pass the alias `MY_SPACE` instead of a concrete ID.
`MY_SPACE` always resolves to your workspace root. Pass it directly whenever you would otherwise have to look up the root folder — for example as `parent_item_id` when creating a top-level file or folder.
You don't need to call [Get Item](/features/memorylake/api-reference/library/get-item) to discover your root folder first — just use `MY_SPACE`.
## Uploading a File (End-to-End)
File uploads are chunked. You receive one pre-signed PUT URL per chunk, upload each chunk, then finalize by creating a `file` item that references the upload.
`POST /api/v1/drives/items/upload` with `file_size` in bytes. Returns an `upload_id` and a list of `part_items` — one pre-signed URL per chunk.
`PUT` each chunk's bytes to its `upload_url`. Save the `ETag` header from each response — you need them all.
`POST /api/v1/drives/items` with `item_type: "file"` and `from: { upload_id, part_etags }`. Returns the new `item_id`.
### Python example
```python theme={null}
import os, requests
BASE = "https://app.memorylake.ai/openapi/memorylake/api/v1"
HEADERS = {"Authorization": "Bearer sk_xxxxxx"}
def upload_file_to_library(path: str, parent_item_id: str = "MY_SPACE") -> str:
"""Upload a local file into the Library and return its item_id."""
size = os.path.getsize(path)
# 1. Create upload session — get pre-signed URLs
init = requests.post(
f"{BASE}/drives/items/upload",
headers={**HEADERS, "Content-Type": "application/json"},
json={"file_size": size},
).json()["data"]
# 2. PUT each chunk; collect ETags
part_etags = []
with open(path, "rb") as f:
for part in init["part_items"]:
chunk = f.read(part["size"])
resp = requests.put(part["upload_url"], data=chunk)
part_etags.append({"number": part["number"], "etag": resp.headers["ETag"]})
# 3. Create the file item
created = requests.post(
f"{BASE}/drives/items",
headers={**HEADERS, "Content-Type": "application/json"},
json={
"item_type": "file",
"parent_item_id": parent_item_id,
"name": os.path.basename(path),
"from": {"upload_id": init["upload_id"], "part_etags": part_etags},
},
).json()["data"]
return created["item_id"]
```
## Name Conflicts
When creating a file or folder, pick a conflict strategy on the request:
| Strategy | Behavior | `item_id` |
| - | - | - |
| `rename` *(default)* | Append `_N` suffix (`report_1.pdf`). Always succeeds. | New |
| `deny` | Return `409 DRIVE_ITEM_CONFLICT` if the name is taken. | — |
| `overwrite` | File-only. Overwrite the existing file's content in place. | **Preserved** |
| `replace` | File-only. Delete the existing file and create a new one. | New |
`overwrite` and `replace` are not aliases. `overwrite` keeps the existing `item_id`; `replace` issues a new one. Neither option re-processes project documents that were already imported from the file — rerun [Import Documents](/features/memorylake/api-reference/v3-documents/import-documents) if you need the new content indexed.
## Endpoints
Look up a file or folder by `item_id`.
Page through the contents of a folder.
Start a chunked upload session and get pre-signed URLs.
Create a folder, or finalize an upload as a file item.
Delete a file or folder (recursive for folders).
# Set Item Xattrs
Source: https://docs.memorylake.ai/features/memorylake/api-reference/library/set-item-xattrs
Attach or update custom key-value metadata on a Library item
```
PUT /openapi/memorylake/api/v1/drives/items/{item_id}/xattrs
```
Stores your own string key-value pairs (extended attributes, or *xattrs*) on a Library file or folder. Use this to tag items with metadata your application cares about — for example a tenant ID, a workflow status, or a content classification — without changing the file itself.
The call **merges** with whatever xattrs the item already has: keys you send are added or overwritten; keys already on the item that you don't send are left alone. To remove a key, call [Delete Item Xattrs](/features/memorylake/api-reference/library/delete-item-xattrs).
The system reserves a few internal xattr keys it manages on its own. Sending values for those keys has no effect — they're silently filtered. The system root folders (`My Space`, `WPS Space`, `Lark Space`) refuse xattr writes entirely and return `403`.
**Permission required:** [`drive:item_modify`](/features/team-collaboration/permission-reference#edit-your-files) · `service`
### Path Parameters
ID of the file or folder to set xattrs on.
### Request Body
Map of `string → string` to upsert onto the item. Each entry is one extended attribute. An empty map is allowed but a no-op.
```bash cURL theme={null}
curl -X PUT 'https://app.memorylake.ai/openapi/memorylake/api/v1/drives/items/sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5/xattrs' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"x_attrs": {
"tenant_id": "acme-corp",
"review_status": "approved"
}
}'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully"
}
```
To read back the current xattrs on an item, call [Get Item](/features/memorylake/api-reference/library/get-item) — its response includes the full `x_attrs` map.
# MemoryLake API Reference
Source: https://docs.memorylake.ai/features/memorylake/api-reference/overview
Complete API documentation for MemoryLake — turn documents and conversations into searchable, structured memories
## API Overview
The MemoryLake API lets you feed documents and conversations into a project, automatically extract structured facts, and search across all memory sources with natural language. Use it to build AI applications with long-term memory.
## Base URL
```
https://app.memorylake.ai/openapi/memorylake
```
## Authentication
All API requests require a Bearer token in the `Authorization` header. See [Authentication](/features/memorylake/api-reference/authentication) for details.
## API Sections
The 3 essential APIs: import documents, append conversation messages, and search memories.
File storage — upload and manage files before importing them into projects.
Create and manage workspaces — the top-level namespace for data isolation.
Manage participant identities and their associated facts.
Define AI agents with versioning and A2A protocol support.
Manage projects and their documents, conversations, and facts.
## Common Patterns
### Response Format
All responses follow this structure:
```json theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
// Response payload
}
}
```
Error responses:
```json theme={null}
{
"success": false,
"message": "Error description",
"error_code": "ERROR_CODE"
}
```
### Your own identifiers
Every resource you create has two identifiers. `id` is minted here — a prefix and 32 hex characters,
like `actor-7b5470549febfaca2acc5a3ebcaa2138`. `custom_id` is the one you bring: the identifier this
thing already has in your system.
Setting it means you do not have to store our id next to your record. Create an actor with the user
id your application already uses, and from then on you can address that actor by it:
```bash theme={null}
# create with the id your system already has
curl -X POST .../api/v3/actors \
-d '{"custom_id": "user-4471", "display_name": "Jane"}'
# and reach it by that id afterwards, with by_custom_id=true
curl .../api/v3/actors/user-4471?by_custom_id=true
```
**A `custom_id` must be unique within your tenant**, per kind of resource — two actors cannot share
one, though an actor and a project may. Deleting a resource frees its `custom_id` for reuse.
### Pagination
List endpoints use continuation-token pagination:
**Query Parameters**:
* `page_size`: Number of items per page
* `continuation_token`: Token from a previous response to fetch the next page
When the response `continuation_token` is `null`, there are no more pages.
### Timestamps
All timestamps use ISO 8601 format:
```
2024-01-15T10:30:00Z
```
## Next Steps
Start with the core APIs — see the workflow and prerequisites
Set up your API credentials
# Search Memories
Source: https://docs.memorylake.ai/features/memorylake/api-reference/search/search-memories
Search across all memory sources in a workspace using natural language
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/memories/search
```
Searches across all memory sources in a workspace — documents and facts — using a natural language query. Results are grouped by source type so you can present each category separately or merge them in your UI. Use the optional filters to narrow results to specific projects, actors, or memory types.
**Permission required:** `workspace:memory_search` on the workspace, plus one per thing you name — on each project in `project_ids`: `project:mem_search` and `project:doc_search`; on each actor in `actor_ids`: `workspace_actor:fact_search`; on each agent in `agent_ids`: `workspace_agent:fact_search`. Naming something you may not search refuses the whole request.
### Path Parameters
Workspace identifier
### Request Body
Natural language search query
Limit search to specific projects. When omitted, all projects in the workspace are searched.
Limit search to memories associated with specific actors
Limit search to memories belonging to specific agents.
Filter results by memory type. Accepted values: `document`, `fact`. When omitted, all types are searched.
Maximum number of results to return per source type
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/memories/search' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"query": "What were the quarterly revenue figures?",
"project_ids": ["proj-b93e8d95a8705bcc4ec42a65ba4cc7f8"],
"memory_types": ["document", "fact"],
"top_k": 10
}'
```
### Response
Document search results, grouped by source document
Document identifier
Display name of the document
Original file name
Summary of the document
Source type of the document (e.g. `upload`, `connector`)
Worksheet name, if the document is a workbook
Matched content items within the document
Fact search results
Fact identifier
The fact text
Relevance score
Additional metadata associated with the fact
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"documents": [
{
"document_id": "doc-8ef7fb1915709b68aa2e8628f0fb9aab",
"document_name": "Q1 2024 Financial Report",
"file_name": "q1_2024_report.pdf",
"document_summary": "Quarterly financial report covering revenue, expenses, and projections for Q1 2024.",
"source_type": "upload",
"sheet_name": null,
"items": [
{
"text": "Q1 2024 revenue reached $12.5M, a 15% increase over Q4 2023.",
"range": "p8"
}
]
}
],
"facts": [
{
"id": "fact-bd3fcc4661d8942d0f84fb633de5cc59",
"fact": "Company quarterly revenue for Q1 2024 was $12.5M",
"score": 0.92,
"metadata": {},
"created_at": "2024-04-01T09:00:00Z",
"updated_at": "2024-04-01T09:00:00Z"
}
]
}
}
```
# Get Actor Memory Conflict
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-conflicts/get-actor-conflict
Retrieve the full details of a single memory conflict among an actor's facts
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/memories/conflicts/{conflictId}
```
Returns the complete record for a single conflict, including the fact snapshots captured at detection time, any document excerpts involved, and the resolution record if the conflict has been resolved.
**Permission required:** `workspace_actor:fact_conflict_read` on a person's memories, or `workspace_agent:fact_conflict_read` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
Conflict ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/actors/actor-8d093c0578ffeb19f8fa10ea28ee9362/memories/conflicts/conf-def456' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Conflict identifier
Short title describing the conflict
Detailed explanation of the contradiction
Conflict category: `m2m` (fact vs. fact) or `m2d` (fact vs. document)
Whether the conflict has been resolved
Resolution record. Present only when the conflict has been resolved; `null` otherwise.
Resolution record identifier
Strategy that was applied: `keep_fact`, `trust_fact`, `trust_document`, or `dismiss`
The fact kept when `strategy` is `keep_fact`
IDs of the facts forgotten as part of the resolution
When the conflict was resolved
Whether an involved fact changed after the conflict was detected
Conflict type: `logical` or `knowledge`
IDs of the facts involved in the conflict
Snapshots of the involved facts at detection time
Fact identifier
Fact text at detection time
Document excerpts cited by a fact-vs-document conflict
The conflicting excerpt text
ID of the document this excerpt belongs to
Display name of the document
When the conflict was first detected
When the conflict was last updated
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conf-def456",
"name": "Contradicting dietary preference",
"description": "One fact states the user is vegetarian; another says their favorite dish is steak.",
"category": "m2m",
"resolved": true,
"resolve": {
"id": "res-1a2b3c4d",
"strategy": "keep_fact",
"keep_fact_id": "fact-4d89ead72a591e8c6abbf68f99edf5e2",
"forgotten_fact_ids": ["fact-91263517847b3371a69814787441263f"],
"created_at": "2025-01-21T09:15:00Z"
},
"stale": false,
"conflict_type": "logical",
"fact_ids": ["fact-4d89ead72a591e8c6abbf68f99edf5e2", "fact-91263517847b3371a69814787441263f"],
"fact_snapshots": [
{
"fact_id": "fact-4d89ead72a591e8c6abbf68f99edf5e2",
"fact_text": "User is vegetarian"
},
{
"fact_id": "fact-91263517847b3371a69814787441263f",
"fact_text": "User's favorite dish is steak"
}
],
"file_chunks": [],
"created_at": "2025-01-20T14:30:00Z",
"updated_at": "2025-01-21T09:15:00Z"
}
}
```
To resolve this conflict, call [Resolve Actor Memory Conflict](/features/memorylake/api-reference/v3-conflicts/resolve-actor-conflict) with the strategy you want to apply.
# List Actor Memory Conflicts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-conflicts/list-actor-conflicts
Returns a paginated list of memory conflicts among an actor's facts
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/memories/conflicts
```
When MemoryLake extracts facts about an actor, it compares new facts against the actor's existing facts. If a contradiction is detected, it is recorded as a **memory conflict**. Use this endpoint to list an actor's conflicts, newest first, so you can surface them to users for review.
You can filter by resolution status to show only unresolved conflicts that need attention, or only resolved ones for audit purposes. For conflicts within a project's knowledge, use [List Memory Conflicts](/features/memorylake/api-reference/v3-conflicts/list-conflicts) instead.
**Permission required:** `workspace_actor:fact_conflict_read` on a person's memories, or `workspace_agent:fact_conflict_read` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
### Query Parameters
Filter by resolution status. Pass `true` for resolved conflicts only, `false` for unresolved only. Omit to return both.
Number of conflicts to return per page. Range: 1–100.
Token from a previous response to fetch the next page of results
```bash Unresolved conflicts theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/actors/actor-8d093c0578ffeb19f8fa10ea28ee9362/memories/conflicts?resolved=false&page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash All conflicts theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/actors/actor-8d093c0578ffeb19f8fa10ea28ee9362/memories/conflicts?page_size=50' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of conflict objects
Conflict identifier
Short title describing the conflict
Detailed explanation of the contradiction
Conflict category: `m2m` (fact vs. fact) or `m2d` (fact vs. document)
Whether the conflict has been resolved
Resolution record. Present only when the conflict has been resolved; `null` otherwise. See [Get Actor Memory Conflict](/features/memorylake/api-reference/v3-conflicts/get-actor-conflict) for the full structure.
Whether an involved fact changed after the conflict was detected. Stale conflicts may no longer be accurate.
Conflict type: `logical` or `knowledge`
IDs of the facts involved in the conflict
Snapshots of the involved facts at detection time
Fact identifier
Fact text at detection time
Document excerpts cited by a fact-vs-document conflict
The conflicting excerpt text
ID of the document this excerpt belongs to
Display name of the document
When the conflict was first detected
When the conflict was last updated
Token to retrieve the next page of results. Absent when there are no more pages.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "conf-def456",
"name": "Contradicting dietary preference",
"description": "One fact states the user is vegetarian; another says their favorite dish is steak.",
"category": "m2m",
"resolved": false,
"resolve": null,
"stale": false,
"conflict_type": "logical",
"fact_ids": ["fact-4d89ead72a591e8c6abbf68f99edf5e2", "fact-91263517847b3371a69814787441263f"],
"fact_snapshots": [
{
"fact_id": "fact-4d89ead72a591e8c6abbf68f99edf5e2",
"fact_text": "User is vegetarian"
},
{
"fact_id": "fact-91263517847b3371a69814787441263f",
"fact_text": "User's favorite dish is steak"
}
],
"file_chunks": [],
"created_at": "2025-01-20T14:30:00Z",
"updated_at": "2025-01-20T14:30:00Z"
}
],
"continuation_token": null
}
}
```
# Resolve Actor Memory Conflict
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-conflicts/resolve-actor-conflict
Apply a resolution strategy to a memory conflict among an actor's facts
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/actors/{actorId}/memories/conflicts/{conflictId}/resolve
```
Applies a resolution strategy to a conflict. You can keep a designated fact, trust one side of a fact-vs-document conflict, or dismiss the conflict as a false positive.
**Permission required:** `workspace_actor:fact_conflict_resolve` on a person's memories, or `workspace_agent:fact_conflict_resolve` on an agent's — whichever the id belongs to
### Path Parameters
Workspace ID
Actor ID
Conflict ID
### Request Body
Resolution strategy to apply:
| Strategy | What it does |
| - | - |
| `keep_fact` | Keep the fact designated by `keep_fact_id` and forget the other conflicting facts |
| `trust_fact` | Trust the fact side of a fact-vs-document conflict |
| `trust_document` | Trust the document side of a fact-vs-document conflict; conflicting facts are forgotten or rewritten |
| `dismiss` | Mark the conflict as resolved without changing any facts |
ID of the fact to keep. Required when `strategy` is `keep_fact`.
```bash Keep a fact theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/actors/actor-8d093c0578ffeb19f8fa10ea28ee9362/memories/conflicts/conf-def456/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "keep_fact",
"keep_fact_id": "fact-4d89ead72a591e8c6abbf68f99edf5e2"
}'
```
```bash Dismiss theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/actors/actor-8d093c0578ffeb19f8fa10ea28ee9362/memories/conflicts/conf-def456/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "dismiss"
}'
```
### Response
Conflict identifier
Whether the conflict is now resolved
Applied resolution strategy
Resolution record identifier
IDs of the facts forgotten as part of the resolution
IDs of the facts rewritten as part of the resolution
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conf-def456",
"resolved": true,
"strategy": "keep_fact",
"resolve_id": "res-1a2b3c4d",
"forgotten_fact_ids": ["fact-91263517847b3371a69814787441263f"],
"updated_fact_ids": []
}
}
```
# Import Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-documents/import-documents
Import files from the Library into a project as documents
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/documents
```
Imports one or more Library files into a project as documents. MemoryLake processes each file asynchronously -- indexing its content for semantic search and memory extraction. You can check progress with [Get Document](/features/memorylake/api-reference/v3-documents/get-document).
**Permission required:** `project:doc_add`
Files must already exist in the Library before you can import them. Use the [Library API](/features/memorylake/api-reference/library/overview) to upload files first.
### Path Parameters
Workspace ID that owns the project.
Project to import documents into.
### Body Parameters
Array of Library item IDs to import. Each ID must reference an existing file in the Library.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-a1b2c3d4e5f6/projects/proj-7g8h9i0j1k2l/memories/documents' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"drive_item_ids": [
"sc-5c6bf0f82d624a20a6fa4696997bdd46:2a8cf1e93f634b31b7",
"sc-5c6bf0f82d624a20a6fa4696997bdd46:9f3de2a71c844a52c1"
]
}'
```
### Response
Number of files successfully imported.
Number of files that failed to import.
Number of files skipped because they were already imported into this project.
Per-file import results.
Outcome for this file: `success`, `failed`, or `duplicate`.
Library item ID that was processed.
Document ID assigned to the imported file. Present when `result` is `success`.
When `true`, the `details` array has been truncated. This can happen when importing a very large batch.
```json Success (200) theme={null}
{
"success": true,
"data": {
"success_count": 1,
"failure_count": 0,
"duplicate_count": 1,
"details": [
{
"result": "success",
"drive_item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:2a8cf1e93f634b31b7",
"document_id": "doc-3451335835b6cda07544335dc13e6183"
},
{
"result": "duplicate",
"drive_item_id": "sc-5c6bf0f82d624a20a6fa4696997bdd46:9f3de2a71c844a52c1",
"document_id": "doc-fee71e3c6471ef95ab0a52d8e2722520"
}
],
"details_truncated": false
}
}
```
# Create Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/workspaces/create-workspace
Create a new workspace with a name and optional metadata
```
POST /openapi/memorylake/api/v3/workspaces
```
Creates a new workspace. Each workspace requires a `custom_id` that you define, which serves as a stable external identifier you can use to reference the workspace in your own systems.
**Permission required:** `workspace:create`
### Request Body
Workspace name
Your own identifier for this workspace — the one it already has in your system. Must be unique within your tenant. Pass `by_custom_id=true` on later requests to address the workspace by it instead of by `id`. See [Your own identifiers](/features/memorylake/api-reference/overview#your-own-identifiers).
Workspace description
Arbitrary key-value metadata to attach to the workspace
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "My Research Workspace",
"custom_id": "research-ws-001",
"description": "Central workspace for research documents and notes",
"metadata": {
"team": "research",
"priority": "high"
}
}'
```
### Response
Unique workspace identifier
Workspace name
Workspace description
Arbitrary key-value metadata attached to the workspace
Caller-defined unique identifier for external reference
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "ws-fe314186ccd18cde04d6af48a5afd79f",
"name": "My Research Workspace",
"description": "Central workspace for research documents and notes",
"metadata": {
"team": "research",
"priority": "high"
},
"custom_id": "research-ws-001",
"created_at": "2025-03-10T08:30:00Z",
"updated_at": "2025-03-10T08:30:00Z"
}
}
```
# Delete Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/workspaces/delete-workspace
Permanently delete a workspace
```
DELETE /openapi/memorylake/api/v3/workspaces/{id}
```
This is a destructive operation. The workspace and all its associated data will be permanently removed.
Permanently deletes a workspace by its ID.
**Permission required:** `workspace:delete`
### Path Parameters
Workspace ID
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws_abc123def456' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully"
}
```
# Get Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/workspaces/get-workspace
Retrieve workspace details by ID or custom ID
```
GET /openapi/memorylake/api/v3/workspaces/{id}
```
Retrieves a workspace by its internal ID or by its `custom_id`. To look up a workspace using your caller-defined `custom_id`, set the `by_custom_id` query parameter to `true` and pass the custom ID as the path parameter.
**Permission required:** `workspace:read`
### Path Parameters
Workspace identifier. Pass the internal workspace ID, or the `custom_id` value when `by_custom_id` is set to `true`.
### Query Parameters
Set to `true` to look up the workspace by `custom_id` instead of the internal ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws_abc123def456' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique workspace identifier
Workspace name
Workspace description
Arbitrary key-value metadata attached to the workspace
Caller-defined unique identifier for external reference
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "ws-fe314186ccd18cde04d6af48a5afd79f",
"name": "My Research Workspace",
"description": "Central workspace for research documents and notes",
"metadata": {
"team": "research",
"priority": "high"
},
"custom_id": "research-ws-001",
"created_at": "2025-03-10T08:30:00Z",
"updated_at": "2025-03-15T12:00:00Z"
}
}
```
# List Workspaces
Source: https://docs.memorylake.ai/features/memorylake/api-reference/workspaces/list-workspaces
Returns a paginated list of workspaces with optional filtering
```
GET /openapi/memorylake/api/v3/workspaces
```
Returns a paginated list of workspaces accessible to the authenticated user. You can filter results by name using fuzzy search and control pagination with continuation tokens.
**Permission required:** `workspace:read` — rows you cannot open are left out of the list rather than the list being refused
### Query Parameters
Number of workspaces to return per page
Token from a previous response to fetch the next page of results
Fuzzy filter by workspace name (partial match)
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of workspace objects
Unique workspace identifier
Workspace name
Workspace description
Arbitrary key-value metadata attached to the workspace
Caller-defined unique identifier for external reference
Creation timestamp
Last update timestamp
Token to retrieve the next page. `null` when there are no more results.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "ws-fe314186ccd18cde04d6af48a5afd79f",
"name": "My Research Workspace",
"description": "Central workspace for research documents and notes",
"metadata": {
"team": "research",
"priority": "high"
},
"custom_id": "research-ws-001",
"created_at": "2025-03-10T08:30:00Z",
"updated_at": "2025-03-15T12:00:00Z"
}
],
"continuation_token": "eyJsYXN0X2lkIjoid3NfYWJjMTIzZGVmNDU2In0"
}
}
```
# Overview
Source: https://docs.memorylake.ai/features/memorylake/api-reference/workspaces/overview
Workspaces are the top-level namespace for data isolation in MemoryLake
A **Workspace** is the top-level organizational boundary in MemoryLake. It acts as a namespace that isolates all data within it — projects, documents, conversations, and facts are all scoped to a workspace.
## When to Use Workspaces
Create separate workspaces to isolate data between different tenants, teams, or environments. Everything inside a workspace is invisible to other workspaces.
Common patterns:
* **Multi-tenant apps** — one workspace per customer
* **Environment separation** — separate workspaces for development, staging, and production
* **Team isolation** — one workspace per business unit
## Relationships
```
Workspace
├── Projects (knowledge containers)
│ ├── Documents
│ ├── Conversations → Facts (project-scoped)
│ └── Project Facts
├── Actor bindings (who can participate)
│ └── Actor Facts (per-user memory)
└── Agent bindings (which agents are available)
```
* [Actors](/features/memorylake/api-reference/actors/overview) and [Agents](/features/memorylake/api-reference/agents/overview) are created globally, then **bound** to a workspace to operate within it.
* [Projects](/features/memorylake/api-reference/v3-projects/overview) live inside a workspace and hold the actual memory data.
* [Search](/features/memorylake/api-reference/search/search-memories) operates at the workspace level, querying across all projects within it.
## Endpoints
| Operation | Method | Path |
| - | - | - |
| [List Workspaces](/features/memorylake/api-reference/workspaces/list-workspaces) | `GET` | `/api/v3/workspaces` |
| [Create Workspace](/features/memorylake/api-reference/workspaces/create-workspace) | `POST` | `/api/v3/workspaces` |
| [Get Workspace](/features/memorylake/api-reference/workspaces/get-workspace) | `GET` | `/api/v3/workspaces/{id}` |
| [Update Workspace](/features/memorylake/api-reference/workspaces/update-workspace) | `PATCH` | `/api/v3/workspaces/{id}` |
| [Delete Workspace](/features/memorylake/api-reference/workspaces/delete-workspace) | `DELETE` | `/api/v3/workspaces/{id}` |
# Update Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/workspaces/update-workspace
Update an existing workspace's name, description, or metadata
```
PATCH /openapi/memorylake/api/v3/workspaces/{id}
```
Updates an existing workspace. Only the fields you include in the request body are updated; omitted fields remain unchanged.
**Permission required:** `workspace:modify`
### Path Parameters
Workspace ID
### Request Body
Updated workspace name
Updated workspace description
Updated key-value metadata. Replaces the existing metadata object entirely.
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws_abc123def456' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "My Updated Workspace",
"description": "Updated workspace description"
}'
```
### Response
Unique workspace identifier
Updated workspace name
Updated workspace description
Arbitrary key-value metadata attached to the workspace
Caller-defined unique identifier for external reference
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "ws-fe314186ccd18cde04d6af48a5afd79f",
"name": "My Updated Workspace",
"description": "Updated workspace description",
"metadata": {
"team": "research",
"priority": "high"
},
"custom_id": "research-ws-001",
"created_at": "2025-03-10T08:30:00Z",
"updated_at": "2025-03-20T09:15:00Z"
}
}
```
# External Connectors
Source: https://docs.memorylake.ai/features/memorylake/connectors/overview
Mount external document services like WPS and Lark into your MemoryLake library
## Overview
MemoryLake Connectors let you mount external document services directly into your library. Browse files from WPS and Lark without leaving MemoryLake, and associate them with projects so your AI assistants can use them as context.
## What Are Connectors?
Connectors are integrations that:
* **Mount external document libraries** into your personal library as a dedicated space (e.g. "WPS Space", "Lark Space")
* **Use OAuth authentication** for secure access — your password never leaves the external service
* **Provide read-only access** to external content (browse, download, associate with projects)
* **Load content lazily** — folders fetch their contents from the external service as you expand them
Connectors are available in your **personal space only**. In team and organization workspaces, external connectors are disabled by policy — the cards appear but cannot be connected.
## Available Connectors
**Status**: Available
Connect your WPS account and browse your document libraries as "WPS Space".
**Status**: Available
Connect your Lark account and browse your documents as "Lark Space". Same flow as WPS.
**Status**: Coming Soon
**Status**: Coming Soon
**Status**: Coming Soon
**Status**: Coming Soon
Connector availability can vary by deployment. The Connectors section in your console always shows what is enabled for your environment.
## How Connectors Work
Click a connector card in the Connectors section.
A popup window opens the service's login page. Sign in and approve MemoryLake's read-only access.
Once connected, a dedicated space (e.g. "WPS Space") appears in your library tree. Expand folders to browse — contents are fetched from the external service on demand.
If the external service's authorization expires, expanding the space prompts you to re-authorize — reconnecting takes one OAuth round trip.
## Connector Capabilities
### What You Can Do
* **Browse** external document structures in your library tree
* **Download** files from external services
* **Associate** external documents with projects (so AI assistants get their content as context)
### Limitations
* **Read-Only**: You cannot upload, edit, or delete external content through MemoryLake
* **Personal space only**: Connectors are disabled in team and organization workspaces
* **Freshness**: Changes in the external service appear when you re-expand or refresh the folder
* **File Types**: Project processing covers MemoryLake-supported formats
To modify files in external services, use the native application. MemoryLake provides convenient read access and integration with your projects.
## Common Use Cases
Access documents from multiple services in one place. Browse WPS and Lark libraries alongside your MemoryLake files without switching applications.
Associate external documents with a MemoryLake project. AI assistants connected via MCP or the OpenClaw plugin can then search and read that content — without you re-uploading anything.
Preview and download external content before migrating it into MemoryLake. Test project workflows against mounted content before committing to a full import.
## Next Steps
Step-by-step guide to connecting your WPS or Lark account
# WPS Integration
Source: https://docs.memorylake.ai/features/memorylake/connectors/wps-integration
Connect your WPS account and browse your document libraries inside MemoryLake
## Overview
WPS (Kingsoft Office) integration lets you browse your WPS documents directly within MemoryLake. This guide walks through the setup — Lark (Feishu) works [the same way](#lark-feishu-works-the-same-way).
## Prerequisites
* An active WPS account
* You are working in your **personal space** — connectors are disabled in team and organization workspaces
## Step-by-Step Setup
Navigate to the Connectors section in MemoryLake and click the WPS connector card.
A popup window opens WPS's authorization page. Sign in with your WPS credentials and approve the access request.
Ensure pop-ups are enabled for MemoryLake. The OAuth flow uses a popup window; the result is passed back to the console automatically when you finish.
MemoryLake requests read-only access. We cannot modify or delete your WPS documents, and your WPS password never leaves WPS.
Once connected, a **WPS Space** node appears in your library tree. Expand it to browse your WPS documents — folder contents are fetched from WPS on demand as you expand them.
The "WPS Space" folder appears in your library and expands to show your WPS content.
## Working with WPS Documents
* **Browse**: navigate WPS folders like regular MemoryLake folders.
* **Download**: download copies of WPS files for local use (changes to local copies don't sync back).
* **Associate with projects**: open a project → Files → add documents → navigate into WPS Space and select files or folders. AI assistants connected to the project can then read that content.
WPS-mounted content is **read-only** — you can browse, download, and associate it with projects, but not upload, edit, rename, move, or delete through MemoryLake.
To modify WPS documents, use the WPS application directly. Changes appear in MemoryLake when you re-expand or refresh the folder.
## Reconnecting
If your WPS authorization expires, expanding WPS Space prompts you to re-authorize — one OAuth round trip and you're back. To disconnect entirely, use the connector card's disconnect action; this unmounts WPS Space and revokes MemoryLake's access.
Disconnecting removes the WPS mount. WPS files associated with projects will become inaccessible to those projects until you reconnect.
## Lark (Feishu) Works the Same Way
The Lark connector follows exactly the same flow: click the **Lark** connector card, sign in through the popup, and a **Lark Space** node appears in your library tree with the same read-only browsing, download, and project-association capabilities.
## Troubleshooting
**Solutions**:
* Enable pop-ups for the MemoryLake domain
* Check browser popup blocker settings
* Try a different browser, or temporarily disable extensions
Connectors are only available in your personal space. If you are in a team or organization workspace, switch to your personal space. If it is still unavailable, the connector may not be enabled for your deployment.
Contents are fetched when folders expand. Collapse and re-expand the folder, or refresh the page, to pick up changes made in the external service.
## Security & Privacy
* **OAuth 2.0**: industry-standard secure authorization
* **Read-Only**: MemoryLake cannot modify your WPS content
* **Revocable**: disconnect anytime from the connector card
* **No Password Storage**: your WPS password never leaves WPS
## Next Steps
Learn about other available connectors
Associate external documents with projects
# Actors & Memory
Source: https://docs.memorylake.ai/features/memorylake/core-concepts/actors-and-memory
How actors provide per-user identity and cross-project memory in MemoryLake
## What is an Actor?
An actor is a participant identity in MemoryLake. Every person or AI assistant that takes part in conversations gets an actor, and MemoryLake uses that identity to associate facts with the right participant.
Actors are the **subject** of memory. When MemoryLake extracts a fact like "Jane prefers concise answers," it attaches that fact to Jane's actor. The fact then follows Jane across every project in the workspace -- if she switches from the support bot to the product assistant, her preferences are already known.
### Actor types
MemoryLake supports two actor types:
| Type | Description | Example |
| - | - | - |
| `HUMAN` | A real person interacting with your application | An end user, a team member |
| `ASSISTANT` | An AI agent or bot | A customer support agent, a coding assistant |
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/actors \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane",
"type": "HUMAN"
}'
```
### Actors and agents
When you create an **Agent** in MemoryLake (an AI agent definition with a model, system prompt, and capabilities), an Actor is automatically generated for it. This means agents accumulate memory too -- the system can learn which tools an agent uses most, which patterns it follows, and what context it needs.
You do not need to create an actor manually for agents. The actor is created as part of the agent lifecycle.
## Two Scopes of Memory
MemoryLake extracts facts from conversations and stores them at two scopes:
### Project Facts
Project facts are knowledge extracted from conversations that applies to the project as a whole. These facts are not tied to any specific actor.
**Examples of project facts:**
* "The billing feature targets Q3 launch"
* "The team uses PostgreSQL for the database"
* "Support tickets should be escalated after 24 hours"
Project facts are scoped to a single project and appear in search results when you query that project's workspace.
### Actor Facts
Actor facts are knowledge associated with a specific person or assistant. These facts follow the actor across all projects within a workspace.
**Examples of actor facts:**
* "Jane prefers concise answers"
* "Jane works at Acme Corp as a product manager"
* "Jane uses dark mode in all her apps"
Actor facts are what make MemoryLake's per-user memory work. Regardless of which project Jane interacts with, her preferences and context are available.
Both fact types are extracted automatically from conversations. You do not need to manually categorize facts -- MemoryLake determines the appropriate scope during extraction.
## How Per-User Memory Works
Here is a practical example. Imagine Jane interacts with three different projects in the same workspace:
```
Workspace: "Acme Corp"
Project: "Support Bot"
Jane says: "I prefer email over chat for follow-ups"
-> Actor Fact: "Jane prefers email over chat for follow-ups"
Project: "Product Assistant"
Jane says: "I manage the billing team"
-> Actor Fact: "Jane manages the billing team"
Project: "Engineering Docs"
Jane searches for billing-related architecture docs
-> The assistant already knows Jane manages billing (from her actor facts)
```
When Jane moves to a new project, the assistant can query her actor facts and immediately know:
* She prefers email over chat
* She manages the billing team
* She prefers concise answers
* She uses dark mode
This happens automatically. You submit messages with Jane's `actor_id`, and MemoryLake handles the rest.
### Binding actors to workspaces
For an actor's facts to be accessible within a workspace, the actor must be **bound** to that workspace. Binding tells MemoryLake that this actor participates in this workspace's projects.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/{workspace_id}/actors/{actor_id}/bind \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY"
```
Bind actors to a workspace before submitting conversations. This ensures facts are correctly associated and searchable from the start.
See the [Bind Actor API reference](/features/memorylake/api-reference/actors/bind-actor) for details.
## Managing Facts
You have full control over the facts MemoryLake extracts. For both project facts and actor facts, you can:
* **List** all facts to see what MemoryLake has learned
* **Get** a specific fact by ID
* **Update** a fact to correct or refine it
* **Forget** a fact to remove it permanently
* **Batch forget** multiple facts at once
This is useful for data privacy (removing a user's facts when they request deletion), correcting inaccurate extractions, or managing the knowledge base over time.
Forgetting a fact is permanent. The fact is deleted and cannot be recovered. Use batch forget carefully.
## Best Practices
**One actor per real identity.** Do not create multiple actors for the same person. Memory only works when facts accumulate on a single actor identity.
**Include `actor_id` in user messages.** When you submit messages to a conversation, include the `actor_id` on messages from the user. This is how MemoryLake knows which actor to associate facts with.
**Use HUMAN for people, ASSISTANT for bots.** The type distinction helps MemoryLake understand the conversation dynamics and extract facts more accurately.
**Bind before you converse.** Bind actors to a workspace before submitting conversations. This ensures facts are properly indexed and searchable.
## Next Steps
Understand how conversations become structured facts
Learn about the resource hierarchy that actors live within
Full API reference for actor operations
API reference for listing and managing actor facts
# Memory Pipeline
Source: https://docs.memorylake.ai/features/memorylake/core-concepts/memory-pipeline
How MemoryLake processes conversations and documents into searchable, structured memories
## The Core Flow
MemoryLake has two input channels -- documents and conversations -- that feed into a unified search index. Here is how data flows through the system:
```
Input Channels Processing Output
-------------- ---------- ------
Documents -----> Indexing ------+
(files from |
the Library) +----> Unified Search Index
|
Conversations -> Fact --------+
(messages) Extraction
|
+-> Project Facts
+-> Actor Facts
```
Both channels contribute to the same search results. When you query a workspace, MemoryLake searches across document content and extracted facts together, returning the most relevant results regardless of source.
## Document Memory
Document memory comes from files you import into a project from the Library. MemoryLake indexes the content for semantic search, so you can find relevant passages using natural language queries.
### How it works
Upload files to the MemoryLake Library using the [Library API](/features/memorylake/api-reference/library/overview). The Library is your central file store -- it holds the original files independent of any project.
Import documents from the Library into a project using the [Import Documents API](/features/memorylake/api-reference/v3-documents/import-documents). This tells MemoryLake to index the file's content for that project.
MemoryLake processes the document asynchronously -- parsing the content, chunking it, and building a semantic index. Once complete, the document's content is searchable.
### Supported formats
MemoryLake supports common document formats including PDF, Word (`.docx`), Excel (`.xlsx`), PowerPoint (`.pptx`), plain text, Markdown, and images.
For best results, use well-structured documents with clear headings and sections. MemoryLake uses the document structure to produce better search results.
## Conversation Memory
Conversation memory comes from user-assistant exchanges that you submit to a project. This is where MemoryLake's automatic fact extraction happens.
### How it works
Create a conversation in a project to group related messages together.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/{workspace_id}/memories/conversations \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "planning-001",
"kind": "DIRECT",
"rw_project_ids": ["{project_id}"],
"name": "Planning session"
}'
```
Submit messages to the conversation one at a time. Include the `actor_id` so MemoryLake can associate facts with the right participant, and name each message's predecessor with `parent_message_id` — `null` for the first message, the `id` returned by the previous append for every message after it.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/{conversation_id}/messages \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "msg-001",
"actor_id": "actor-7b5470549febfaca2acc5a3ebcaa2138",
"parent_message_id": null,
"content": [{"block_type": "TEXT", "text": "We decided to use React for the frontend. Launch target is March."}]
}'
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/{conversation_id}/messages \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "msg-002",
"actor_id": "actor-7ffb42d393202e284c930ec756806f4f",
"parent_message_id": "{id_returned_for_msg_001}",
"content": [{"block_type": "TEXT", "text": "Got it. I will note that the frontend uses React with a March launch target."}]
}'
```
MemoryLake analyzes the messages and extracts structured facts:
* **Project Fact:** "The frontend uses React"
* **Project Fact:** "Launch target is March"
* **Actor Fact (Jane):** context about Jane's involvement in the decision
Facts are extracted asynchronously, typically within a few seconds of submitting messages.
### What gets extracted
MemoryLake identifies and extracts several types of knowledge from conversations:
| Category | Examples |
| - | - |
| **Preferences** | "I prefer dark mode," "Send me weekly summaries" |
| **Decisions** | "We chose PostgreSQL," "The deadline is Q3" |
| **Personal context** | "I manage the billing team," "I work at Acme Corp" |
| **Goals and plans** | "We are targeting 10K users by launch," "Next sprint focuses on auth" |
| **Relationships** | "Sarah is the engineering lead," "The billing team reports to me" |
## How Search Unifies Both Channels
When you search a workspace, MemoryLake queries across both document content and extracted facts in a single request:
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/{workspace_id}/memories/search \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "What technology stack are we using?"}'
```
The response includes results from both channels:
```json theme={null}
{
"success": true,
"data": {
"documents": [
{
"document_id": "doc-0b86666c0e4be4be1ee456ea63509310",
"document_name": "Tech Stack Overview",
"items": [
{"text": "...our backend runs on Node.js with PostgreSQL..."}
]
}
],
"facts": [
{
"id": "fact-18b616c73c16f87fb84561b0a3f2bc17",
"fact": "The frontend uses React",
"score": 0.95
},
{
"id": "fact-190ec75793105e8f5cb3f1b2fe3042a6",
"fact": "The team chose PostgreSQL for the database",
"score": 0.88
}
]
}
}
```
The result merges facts extracted from conversations with passages found in documents. From the caller's perspective, it is one query, one result set.
See the [Search API reference](/features/memorylake/api-reference/search/search-memories) for the full set of search parameters and options.
## Documents vs. Conversations: When to Use Each
Both channels feed the same search index, but they serve different purposes:
| Use documents when... | Use conversations when... |
| - | - |
| You have existing files (PDFs, docs, wikis) | You are capturing real-time interactions |
| The information is static or changes infrequently | The information evolves through dialogue |
| You want full-text search over long-form content | You want automatic fact extraction |
| You are building a knowledge base from existing materials | You are building per-user memory over time |
Most applications use both channels. Import your existing documentation as documents, and submit ongoing user interactions as conversations. MemoryLake searches across both seamlessly.
## Structuring Messages for Better Extraction
The quality of extracted facts depends on how messages are written. Here are some best practices:
**Be explicit.** "I prefer email notifications" extracts better than "yeah email is fine I guess."
**State facts directly.** "Our deadline is March 15" produces a clear, useful fact. Vague statements like "we should probably aim for mid-March" produce less precise extractions.
**Include context.** "We chose React for the frontend because of team expertise" gives MemoryLake more to work with than just "React."
**Use the `actor_id` field.** Always include the actor ID on user messages. Without it, MemoryLake cannot associate personal facts with the right actor.
**Send complete exchanges.** Include both user and assistant messages. The full context of the conversation helps MemoryLake extract more accurate and relevant facts.
Do not include sensitive information (passwords, API keys, secrets) in conversation messages. Facts are extracted and stored persistently. Treat conversation content the same way you would treat data written to a database.
## Next Steps
See the full end-to-end flow in action
Deep dive into per-user memory with actors
API reference for creating conversations and messages
API reference for searching across documents and facts
# Workspaces & Projects
Source: https://docs.memorylake.ai/features/memorylake/core-concepts/workspaces-and-projects
Understand the resource hierarchy -- workspaces for data isolation, projects for organizing knowledge
## Workspaces
A workspace is the top-level namespace in MemoryLake. It provides complete data isolation -- actors, projects, documents, conversations, and facts within one workspace are invisible to another.
You can think of a workspace as a tenant. If you are building a multi-tenant application, each of your customers gets their own workspace. If you are a single team, you might use one workspace for production and another for development.
### What a workspace contains
```
Workspace
+-- Actors (participant identities bound to this workspace)
+-- Agents (AI agent definitions bound to this workspace)
+-- Projects
+-- Documents
+-- Conversations + Messages
+-- Project Facts
```
Every resource in MemoryLake belongs to a workspace. When you search, you search within a workspace. When an actor accumulates facts, those facts live within the workspace where the conversations happened.
### Creating a workspace
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production",
"description": "Production workspace for customer-facing agents"
}'
```
See the [Workspaces API reference](/features/memorylake/api-reference/workspaces/overview) for the full set of workspace operations.
## Projects
A project is a knowledge container within a workspace. It holds the three types of content that MemoryLake works with:
* **Documents** -- files imported from the Library, indexed for semantic search
* **Conversations** -- user-assistant message exchanges
* **Project Facts** -- structured knowledge extracted from conversations, scoped to this project
### When to create a project
Create a project for each distinct knowledge domain, use case, or application. Some examples:
| Scenario | Project structure |
| - | - |
| A customer support bot | One project per product line or knowledge domain |
| A personal assistant | One project per user, or one shared project with actor-level memory |
| A research tool | One project per research topic or dataset |
| A coding assistant | One project per repository or codebase |
Projects are lightweight. It is better to create multiple focused projects than one large project with mixed content. Smaller, focused projects produce better search results.
### Creating a project
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/{workspace_id}/projects \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Customer Support - Billing",
"description": "Knowledge base for billing-related support queries"
}'
```
See the [Projects API reference](/features/memorylake/api-reference/v3-projects/overview) for the full set of project operations.
## Workspaces vs. Projects
Use this decision guide to choose the right level of separation:
| Need | Use |
| - | - |
| **Data isolation between tenants** | Separate workspaces |
| **Different environments** (dev, staging, prod) | Separate workspaces |
| **Different knowledge domains** within the same tenant | Separate projects in one workspace |
| **Per-user memory** that follows the user across domains | One workspace with multiple projects (actors carry facts across projects) |
| **Shared search** across multiple knowledge sources | Multiple projects in one workspace (search is workspace-scoped) |
Search operates at the workspace level. If you need to search across multiple knowledge domains in a single query, put those domains in separate projects within the same workspace.
### Multi-tenant patterns
For multi-tenant applications, the most common pattern is **one workspace per tenant**:
```
Your Application
+-- Workspace: "Acme Corp"
| +-- Project: "Engineering Docs"
| +-- Project: "Support Knowledge Base"
|
+-- Workspace: "Globex Inc"
+-- Project: "Product Docs"
+-- Project: "Internal Wiki"
```
This guarantees that Acme Corp's data is never visible to Globex Inc, and vice versa. Each workspace has its own actors, so user memory is also isolated between tenants.
### Single-tenant patterns
For single-team or single-application use cases, you typically use **one workspace with multiple projects**:
```
Workspace: "My Team"
+-- Project: "Product Knowledge"
+-- Project: "Engineering Runbooks"
+-- Project: "Customer Feedback"
```
Actors in this workspace can accumulate facts across all three projects. When Jane asks a question in the "Product Knowledge" project and later interacts with the "Engineering Runbooks" project, her actor facts from both interactions are available.
## Next Steps
Learn how actors provide per-user memory across projects
Understand how conversations become structured facts
Full API reference for workspace operations
Full API reference for project operations
# File & Folder Operations
Source: https://docs.memorylake.ai/features/memorylake/document-management/file-folder-operations
Create folders, upload files, rename, move, delete, and organize your document hierarchy
## Overview
This guide covers all the essential operations for managing files and folders in MemoryLake. You'll learn how to create, upload, organize, and maintain your document collection.
## Creating Folders
### Basic Folder Creation
You can create a new folder in several ways:
* Click the "New Folder" button in the toolbar
* Right-click on a folder in the tree and select "New Folder"
* Right-click in the empty space to create at root level
Type a descriptive name for your folder and press Enter or click Save.
Use clear, descriptive names that indicate the folder's contents. Good examples: "Q1-Reports", "Research-Papers", "Meeting-Notes".
The new folder appears in the tree immediately. You can now add files or create subfolders within it.
## Uploading Files
### Single File Upload
Click the "Upload" button in the toolbar to open the file picker.
Choose a single file from your computer. Supported formats include PDF, Microsoft Word, Excel, PowerPoint, text/Markdown, and images.
Watch the upload progress in the task panel. The file appears in your tree once the upload completes.
### Multiple File Upload
In the file picker, hold Ctrl (Windows/Linux) or Cmd (Mac) and click multiple files.
Or use Shift-click to select a range of files.
Click "Open" to start uploading all selected files concurrently.
The upload panel shows progress for each file individually. Files are uploaded up to 3 at a time.
### Folder Upload
In the upload dialog, look for "Upload Folder".
Choose a folder from your computer. All files and subdirectories within it will be queued.
MemoryLake automatically recreates the folder structure in your drive, maintaining the hierarchy.
Verify that the folder structure matches your local directory. All subfolders and files should be in the correct locations.
### Drag-and-Drop Upload
The quickest way to upload files:
1. **Open File Explorer/Finder** on your computer
2. **Navigate to Your Files** - find the files you want to upload
3. **Drag to MemoryLake** - drag and drop files directly onto the tree view
4. **Drop on Target Folder** - drop onto a specific folder to upload there, or on empty space for root
Drag multiple files at once for batch uploading.
## Renaming Items
### Rename Files or Folders
Right-click on the file or folder and select "Rename" from the context menu.
The name becomes editable. Type the new name.
Press Enter to save or Escape to cancel. The item updates immediately in the tree.
## Moving Items
### Drag-and-Drop Move
The most intuitive way to move files and folders:
1. **Click and Hold** on the item you want to move
2. **Drag to Destination** folder
3. **Drop** when the target folder is highlighted
4. **Verify** the item now appears in the new location
### Move via Dialog
For more precise control:
Right-click the item and select "Move" from the context menu.
In the move dialog, browse the tree to find the destination folder.
Click on the destination folder and click "Move" to complete the operation.
The item immediately appears in its new location and is removed from the old location.
### Move Behavior
* **Folders**: Moving a folder moves all its contents
* **Permissions**: Moving doesn't affect project associations
* **Comments**: Comments move with the item
## Downloading Files
### Download Single File
Click on a file in the tree to select it.
Right-click and select "Download" or click the download button in the toolbar.
Your browser will download the file to your default downloads folder.
## Deleting Items
### Delete Files or Folders
Click on the file or folder you want to remove.
Right-click and select "Delete".
A confirmation dialog appears. Review the item name and click "Delete" to confirm.
Deletion is permanent and cannot be undone. Deleted items are not moved to a recycle bin.
The item disappears from the tree immediately.
### Deleting Folders with Contents
When you delete a folder:
* **All Contents Deleted**: All files and subfolders are permanently removed
* **Confirmation Required**: Extra confirmation for non-empty folders
## Best Practices
* Create a logical folder hierarchy before uploading
* Group related documents together
* Use consistent naming conventions
* Keep folder structures reasonably flat (3-5 levels)
* Use folder upload to preserve directory structure
* Upload related files together
* Use drag-and-drop for quick uploads
* Monitor upload progress for large files
* Regularly review and remove unused files
* Keep folder names descriptive and current
* Use comments to add context to files
* Download important files as backups
## Next Steps
Add rich context to your files with Markdown comments
# Comments
Source: https://docs.memorylake.ai/features/memorylake/document-management/metadata-comments
Add rich Markdown comments to your documents with live preview
## Overview
Add contextual information to your documents using Markdown-formatted comments. Provide context that helps both humans and AI understand your content.
## Markdown Comments
### Comment System Overview
MemoryLake's comment system uses Markdown, allowing you to create rich, formatted notes for any file or folder.
**Features**:
* **Markdown Formatting**: Headers, lists, bold, italic, code blocks, links
* **Live Preview**: See rendered output as you type
* **Auto-Save**: Draft protection prevents data loss
### Creating Comments
Select a file or folder and open the comment panel (usually on the right side).
Use the Markdown editor to compose your comment. You can use:
* `# Headers` for structure
* `**bold**` and `*italic*` for emphasis
* `- Lists` for organization
* `` `code` `` for technical terms
* `[links](url)` for references
The live preview pane shows how your Markdown will render.
Use the preview to verify formatting before saving, especially for complex Markdown with tables or code blocks.
Click "Save" to store your comment with the file.
### Markdown Syntax Reference
Here's a quick reference for common Markdown formatting:
#### Headers
```markdown theme={null}
# H1 Header
## H2 Header
### H3 Header
```
#### Text Formatting
```markdown theme={null}
**Bold text**
*Italic text*
~~Strikethrough~~
`Inline code`
```
#### Lists
```markdown theme={null}
Unordered list:
- Item 1
- Item 2
- Nested item
Ordered list:
1. First item
2. Second item
3. Third item
```
#### Links and Images
```markdown theme={null}
[Link text](https://example.com)

```
#### Code Blocks
````markdown theme={null}
```javascript
function example() {
return "Code with syntax highlighting";
}
```
````
#### Blockquotes
```markdown theme={null}
> This is a quoted text
> It can span multiple lines
```
#### Tables
```markdown theme={null}
| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Data 1 | Data 2 | Data 3 |
| Data 4 | Data 5 | Data 6 |
```
### Comment Examples
```markdown theme={null}
# Research Paper: Q1 2024 Analysis
## Summary
This paper analyzes market trends for Q1 2024 with focus on:
- Consumer behavior shifts
- Competitive landscape changes
- Budget allocation recommendations
## Key Findings
1. **Consumer Spending**: Up 15% YoY
2. **Market Share**: Gained 3 percentage points
3. **ROI**: Exceeded targets by 12%
## Related Documents
- [Budget Planning](/path/to/budget.xlsx)
- [Previous Quarter Analysis](/path/to/q4-analysis.pdf)
## Next Steps
- Review with leadership team
- Incorporate feedback
- Finalize recommendations
```
```markdown theme={null}
# Project: Website Redesign
## Project Overview
Complete redesign of the company website with modern UX and improved conversion rates.
**Timeline**: Q1-Q2 2024
**Budget**: $150,000
**Team**: 8 members
## Folder Contents
- `/design` - Mockups and design files
- `/requirements` - Requirements documents
- `/research` - User research and competitive analysis
## Important Notes
⚠️ All designs must be approved by marketing before development
💡 Prioritize mobile-first approach
✅ Accessibility compliance required (WCAG 2.1 AA)
```
```markdown theme={null}
# Dataset: Customer Survey Results 2024
## Data Description
Survey responses from 1,500 customers collected in January 2024.
**Format**: CSV
**Columns**: 45
**Rows**: 1,500
## Key Columns
- `customer_id` - Unique identifier
- `satisfaction_score` - 1-10 scale
- `nps_score` - Net Promoter Score
- `comments` - Free-text feedback
## Data Quality
- ✅ All required fields populated
- ✅ Validated against schema
- ⚠️ 23 rows have missing optional fields
## Usage Notes
Use this data for:
1. Satisfaction trend analysis
2. NPS calculation and tracking
3. Identifying improvement areas
**Do not** share externally without anonymization.
```
## Comment Management
### Editing Comments
To modify an existing comment:
1. Select the file or folder
2. Open the comment panel
3. Edit the Markdown text
4. Save changes
### Deleting Comments
To remove a comment entirely:
1. Open the comment editor
2. Delete all text
3. Click "Save"
Deleting comments is permanent and cannot be undone. Consider adding a "DEPRECATED" header instead if you might need the information later.
## Best Practices
**Do**:
* Be concise but complete
* Use headers to organize long comments
* Include context others might not have
* Link to related documents
* Update comments when content changes
**Don't**:
* Write novel-length comments (keep it scannable)
* Include sensitive information in comments on shared files
* Duplicate information that's in the file itself
* Leave outdated comments
* Use `#` headers to create structure
* Lists make content scannable
* **Bold** key terms for quick identification
* Code blocks for technical content
* Tables for structured data
* Links to connect related documents
* Use headers in hierarchical order (H1, then H2, not H1 then H3)
* Provide descriptive link text (not "click here")
* Add alt text for any images
* Keep language clear and simple
* Use lists for better screen reader support
## Integration with Projects
Comments enhance project workflows:
* **Project Context**: Comments provide context when documents are associated with projects
* **AI Understanding**: AI models accessing via MCP servers can read comments to understand document purpose
* **Team Collaboration**: Comments help team members understand document relationships and history
* **Search**: Comments are searchable, making documents easier to find
## Next Steps
Learn basic file and folder operations
Link documents to projects
Manage files programmatically via API
# Document Management
Source: https://docs.memorylake.ai/features/memorylake/document-management/overview
Store, organize, and manage files and folders with hierarchical navigation and comments
## Overview
MemoryLake's Document Management system provides a powerful, intuitive interface for organizing your files and folders. Built on a hierarchical file system with advanced features, it combines the familiarity of traditional file browsers with modern cloud storage capabilities.
You'll encounter documents in two places in the console:
* **Library** (sidebar → Advanced → Library): your full personal file store, with the folder tree, comments, and connector spaces
* **Project Files tab**: the documents associated with a specific project, with their processing status — see [Document Association](/features/memorylake/project-management/document-association)
## Core Capabilities
Create folders, upload files, rename, move, delete, and organize your document hierarchy with drag-and-drop support.
Add rich Markdown-formatted comments to any file or folder for enhanced context.
## Key Features
### Hierarchical Organization
* **Unlimited Nesting**: Create folders within folders with no depth limit
* **Visual Tree Structure**: See your entire document hierarchy at a glance
* **Folder Expansion**: Expand and collapse folders to focus on relevant content
* **Breadcrumb Navigation**: Always know where you are in your document tree
### File Upload & Management
* **Multiple Upload Methods**:
* Single file selection
* Multiple file selection
* Entire folder upload with structure preservation
* Drag-and-drop from your desktop
* **Reliable Upload**:
* Handles files of any size
* Multiple files can be uploaded together
* Real-time progress tracking
* Resume capability if interrupted
* **Supported File Types**:
* Documents: PDF, Microsoft Word
* Spreadsheets: Microsoft Excel, CSV, TSV
* Presentations: Microsoft PowerPoint
* Text: Plain text, Markdown
* Images: PNG, JPEG, GIF, BMP, WebP, TIFF
MemoryLake automatically handles large file uploads reliably.
### File Operations
All standard file operations are supported:
* **Create**: New folders anywhere in your hierarchy
* **Read**: Download files for local viewing
* **Update**: Rename files and folders, move items
* **Delete**: Remove files and folders with confirmation
### Comments
* **Markdown Comments**: Add rich-text comments with formatting, lists, and links
* **Live Preview**: See your Markdown rendered in real-time
* **Auto-Save**: Draft protection prevents data loss
### Tree View Features
* **Resizable Interface**: Adjust the tree panel width to suit your workflow
* **Context Menu**: Right-click access to operations
## Common Workflows
1. Create a project folder structure (e.g., "Research/Topic/Sources")
2. Upload documents using folder upload to preserve structure
3. Add Markdown comments to key documents with summaries or insights
4. Associate the folder with a project for AI access
1. Create folders for each team or department
2. Upload shared documents and resources
3. Add Markdown comments to tag documents by category or status
4. Associate the right folders with team projects so members' assistants share the context
1. Organize documents by topic in a clear folder structure
2. Add rich Markdown comments explaining context and relationships
3. Upload related documents in batches
4. Create projects that group related documents
5. Generate MCP server keys for AI access to your knowledge base
1. Download document structure from external service
2. Use folder upload to import with structure intact
3. Verify all files uploaded successfully via progress tracking
4. Add metadata and comments as needed
5. Connect external service directly via connectors for future sync
## Supported File Formats
MemoryLake parses and indexes the following document types:
* **PDF** — portable document format
* **Microsoft Word** — Word documents and templates
* **Microsoft Excel** — Excel workbooks and templates, plus CSV and TSV data
* **Microsoft PowerPoint** — PowerPoint presentations and templates
* **Text and Markdown** — plain text and Markdown notes
* **Images** — PNG, JPEG, GIF, BMP, WebP, and TIFF
## Security & Permissions
* **User Isolation**: Your drive is private to your account
* **Project Sharing**: Share access via project association and MCP servers
## Performance
MemoryLake is optimized for handling large document collections efficiently, ensuring smooth operation even with thousands of files.
## Integration with Other Features
Document Management integrates seamlessly with other MemoryLake features:
* **Projects**: Associate documents with projects for organization
* **Connectors**: Mount external document services into your tree
* **Integrations**: Provide AI assistants and agents with search access to your documents
* **Memories**: Link memories to specific documents for context
## Getting Started
Ready to start organizing your documents? Choose a guide below:
Learn the basics of creating folders, uploading files, and organizing your content.
Enhance your documents with rich Markdown comments.
## Best Practices
* Use clear, descriptive folder names
* Group related documents together
* Avoid excessive nesting (3-5 levels is optimal)
* Create a consistent structure across similar projects
* Use descriptive names that indicate content
* Include dates in ISO format (YYYY-MM-DD) when relevant
* Avoid special characters that may cause issues
* Be consistent within a project or folder
* Add comments to documents that need context
* Use Markdown formatting for readability
* Include links to related documents
* Update comments when document purpose changes
* Upload folders in batches rather than individual files
* Use folder upload to preserve structure
* Leverage lazy loading by not expanding all folders at once
* Clean up unused files regularly
Start with a simple folder structure and expand as needed. It's easier to add complexity than to simplify an overly complex structure later.
# Slack integration
Source: https://docs.memorylake.ai/features/memorylake/im-channels/slack
Connect a workspace's memory to Slack: DM the bot, or add it to a channel and @-mention it
## Overview
The Slack integration connects an agent from one **workspace** to your own Slack app. Once it is set up, your team never has to open the console to ask a question:
* DM the bot, or @-mention it in a channel, and get answers grounded in your team's memory
* Answers **stream in segments** — a "thinking…" placeholder appears immediately, then the content refreshes piece by piece
* Send it a document or a screenshot, then ask follow-up questions about the content
* Every exchange becomes memory, so nobody has to explain the same thing twice
The bot answers from the project memory you designate — not from a general-purpose model's generic knowledge.
Nothing on the Slack side requires a review cycle — one person can finish the setup in about ten minutes. Just remember to **Reinstall** the app whenever you change scopes or event subscriptions.
## Before you start
* The **owner** or **admin** role in your team (members can neither see nor edit integrations)
* A workspace with at least one project
* At least one agent **linked to that workspace** (done on the workspace's Agents tab)
* An account that can create apps in the target workspace (most workspaces allow everyone; if app installs require admin approval in your company, the install step will need an admin)
* A test channel (optional but recommended)
If the workspace page has **no IM tab**, either this deployment has not enabled IM channels, or your role is member. Check with your team admin.
## Part 1: create the app in Slack
Everything in this part happens at [api.slack.com/apps](https://api.slack.com/apps). The goal is to obtain two values: the **Bot User OAuth Token** (starts with `xoxb-`) and an **App-Level Token** (starts with `xapp-`).
The recommended path is creating the app **from a manifest**: paste one JSON blob and the scopes, event subscriptions, DM entrance and Socket Mode are all configured at once — nothing to forget.
Open [api.slack.com/apps](https://api.slack.com/apps) → **Create New App** → select **From a manifest** → **Continue** → pick the workspace to install into → paste the JSON below into the config box → review the scopes and events → **Create**.
```json theme={null}
{
"display_information": {
"name": "MemoryLake Assistant"
},
"features": {
"bot_user": {
"display_name": "memorylake",
"always_online": true
},
"app_home": {
"home_tab_enabled": false,
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": false
}
},
"oauth_config": {
"scopes": {
"bot": [
"app_mentions:read",
"im:history",
"chat:write",
"files:read",
"users:read"
]
}
},
"settings": {
"event_subscriptions": {
"bot_events": [
"app_mention",
"message.im",
"tokens_revoked",
"app_uninstalled"
]
},
"org_deploy_enabled": false,
"socket_mode_enabled": true,
"token_rotation_enabled": false
}
}
```
The two names follow different rules: `display_information.name` is the **display name** your colleagues see — change it to something the team will recognize; `features.bot_user.display_name` becomes the bot's **username** for @-mentions and only accepts lowercase letters, digits, hyphens and underscores — anything else fails with "The display\_name cannot be converted to a username".
**Manifest-to-settings mapping** (for review, or for manual setup):
| Manifest field | Manual location | Purpose |
| - | - | - |
| `oauth_config.scopes.bot` | OAuth & Permissions → Bot Token Scopes | The 5 permissions for messaging, file reading and name lookup |
| `settings.event_subscriptions.bot_events` | Event Subscriptions → Subscribe to bot events | 4 events; the last two (`tokens_revoked`, `app_uninstalled`) keep the connection status in sync when credentials are revoked — **do not drop them** |
| `features.app_home.messages_tab_*` | App Home → Show Tabs → Messages Tab | The DM entrance; `read_only_enabled: false` means "allow sending messages" — missing it leaves the DM input box disabled |
| `settings.socket_mode_enabled` | Socket Mode → Enable Socket Mode | Receive events over a long-lived connection, no public callback URL needed |
| `settings.token_rotation_enabled: false` | — | Rotating tokens (`xoxe`-prefixed) are incompatible with the integration's static-credential model; creation would be rejected |
`users:read` is strictly optional: without it, every person in the console's Actors list shows as a `U08J5K7UXH6`-style id and the bot cannot answer "who am I" — everything else works. It is included in the manifest; keep it.
The manifest cannot cover App-Level Tokens — this step is manual: after the app is created, go to **Basic Information** → scroll to **App-Level Tokens** → **Generate Token and Scopes** → name it, select the **`connections:write`** scope, and copy the generated `xapp-` value.
You can view this token again in the same place at any time.
**OAuth & Permissions** (or **Install your app** on Basic Information) → **Install to Workspace** → authorize.
After installing, the **Bot User OAuth Token** (`xoxb-`) appears at the top of the OAuth & Permissions page. Copy it.
**Every time you later change scopes or event subscriptions (via manifest or manually), come back here and click Reinstall to Workspace** — changes do not take effect otherwise. There is no review step; it is effective immediately.
## Part 2: create the integration in the console
In the [MemoryLake console](https://app.memorylake.ai), go to **MemoryLake → Workspaces**, open the target workspace, switch to the **IM** tab, and click **Get started**.
Pick **Slack** as the platform.
| Field | What to paste |
| - | - |
| **Bot User OAuth Token** | Starts with `xoxb-`, from the OAuth & Permissions page |
| **App-Level Token** | Starts with `xapp-`, from Socket Mode / Basic Information |
Then click **Next: agent & memory**.
No app ID is needed — the identity (workspace + bot) is derived automatically when the server validates the token, and shows up on the integration card afterwards.
One Slack app installed in **one Slack workspace** can back only one integration; installing the same app into **another workspace** creates a distinct identity, which can back another integration. Conflicts are shown as a banner at the top of the form.
| Field | Notes |
| - | - |
| **Name** | Only for telling integrations apart in the console; pre-filled, editable |
| **Agent** | Answers Slack-side messages. Only agents **linked to the current workspace** are listed |
| **Read-write project** (required) | The project the bot reads from and writes memory into |
| **Extra read-only projects** (optional) | Projects the bot may search but never writes to |
**The read-write project is an authorization decision.** Everyone who can reach this bot writes memory into that project and can read what is already there. Pick a project meant for team sharing — not the one holding sensitive material.
Click **Create & connect**. The integration is enabled by default; the server validates the Bot User OAuth Token first, then opens the long-lived connection to Slack.
The status badge on the integration card reads **Connected**, and the app identity shows a `T…:U…` composite value.
If creation is rejected with "Bot User OAuth Token validation failed", the token was mispasted or revoked. If the status later reads "Invalid credentials — check the Bot User OAuth Token / App-Level Token", re-check both values in the edit dialog.
## Part 3: verify and start using it
### Direct messages
Members find the app under **Apps** in Slack's sidebar and just ask — no @ needed.
A "thinking…" placeholder appears first, then the answer refreshes in segments. The **(edited) marker** on the message is normal — streaming works by editing the same message in place.
### Channels
First **add the bot to the channel** (`/invite @botname`, or follow the prompt when you mention it), then **@-mention it with your question**.
The answer lands **in a thread under your question**, keeping the channel itself uncluttered. The first time the bot is mentioned in a channel it appends a one-line capability note; it never repeats it.
**Follow-ups inside a thread must also @-mention the bot.** This is how Slack works: messages that do not mention the bot are never delivered to it. It also means the bot cannot see any other conversation in the channel.
### Sending documents and screenshots
* **DM**: just send the file or image, then ask about it
* **Channel**: **put the file and the @-mention in the same message** (attach the file, type "@bot + your question", send together)
A file posted to a channel **on its own (without a mention) never reaches the bot** — Slack does not deliver it. File and mention must share one message.
### Sessions and context
* **DMs are continuous**: context never expires, even overnight. To start fresh, send **`new`** (just that word, no slash)
* **Channels are per-thread**: one thread is one topic, follow-ups inside it keep full context with **no expiry** — coming back to the same thread a day later still works. For a new topic, start a new thread (mention the bot at the channel level again)
* Inside a thread, **each person's context is isolated** — several people mentioning the bot in one thread do not bleed into each other
* Files sent in a DM **never expire** and stay attached to the session; `new` clears them. Files sent in a channel stay usable in that thread for about 30 minutes
**Why `new` and not `/new`?** The Slack client intercepts anything starting with `/` as a slash command — the message is never sent. So the reset word in Slack has no slash: send `new` in a DM (any capitalization, as the entire message), or `@bot new` inside a thread.
### Who is who
Each Slack user maps to a distinct **actor** in MemoryLake; personal memory attaches to the right person, while memory written into the project is shared.
With the `users:read` scope in place, actors show real names and the bot can answer "who am I".
### What the bot cannot handle yet
Voice and video messages get an explicit "can't process this yet" reply rather than silence. Users from **Slack Connect shared channels who belong to external organizations** are silently ignored — they consume none of your quota and write nothing into your memory.
## Managing an existing integration
| Action | Where & notes |
| - | - |
| **Disable / enable** | The switch on the integration card; takes effect immediately |
| **Rotate a token** | Edit → the "Replace" button next to the field → paste the new value and save. Fields without "Replace" clicked are left untouched — you can rotate just one of the two |
| **Change the agent** | Edit → Agent. **Resets all in-flight sessions** under this integration |
| **Adjust memory scope** | Edit → read-write / read-only projects. Effective immediately |
| **Delete** | Card menu → Delete. Also removes session records, actor mappings and session attachments. **Irreversible** |
**The integration's identity (installed workspace + bot) cannot be changed after creation.** Pasting a token from a different workspace during editing is rejected. To switch workspaces, delete and recreate.
## FAQ
The **App Home Messages Tab is not fully enabled**. In the app config, go to **App Home → Show Tabs**, enable the **Messages Tab** and check "Allow users to send Slash commands and messages from the messages tab" — both. No reinstall needed; refresh the Slack client.
Check in order:
* **Is the bot in the channel?** `/invite @botname`
* **Is `app_mention` subscribed**, and did you **Reinstall** after adding it?
* **Was it a thread reply without a mention?** Thread follow-ups must mention the bot — unmentioned messages are never delivered
* **Is the integration disabled?** (a disabled integration replies "the bot is currently unavailable")
The Slack client intercepted the `/` prefix as a slash command — the message never left your input box.
The reset word in Slack has **no slash**: send `new` in a DM, or `@bot new` inside a thread.
Slack scope and event changes only take effect after **Reinstall to Workspace**: app config → OAuth & Permissions → Reinstall to Workspace. No review step; effective immediately.
Add the `users:read` scope, then **Reinstall**.
**Existing actors do not rename themselves.** The name is written once, when a person first talks to the bot — adding the scope only affects **new** users. To fix an existing one, delete their actor entry; it is recreated on their next message.
With `tokens_revoked` and `app_uninstalled` subscribed, the integration turns red **within seconds**, with the reason spelled out. Without them, the status may stay green for hours (until the connection happens to rebuild) — which is why the setup insists on all four events.
Note that revoking the Bot User OAuth Token **uninstalls the app** — the bot disappears from the workspace. To recover: app config → OAuth & Permissions → **Reinstall to Workspace** (this issues a **new** token), then edit the integration and replace just the Bot User OAuth Token (the App-Level Token is unaffected).
Slack rejected our connection. Almost always one of:
* A token was mispasted (extra whitespace, missing characters)
* The Bot User OAuth Token was revoked, or the app was reinstalled (reinstalling issues a **new** token while the console still holds the old one)
* The App-Level Token was deleted
Edit the integration, click "Replace" next to the affected field, paste the new value, save — it reconnects immediately.
This is a Slack-side boundary: we stream by editing the same message in place (hence the (edited) marker), Slack has no typewriter animation for edits, and it rate-limits message updates. The first \~12 seconds refresh every 0.5s, then it slows down — content completeness is unaffected.
Two app shapes are currently unsupported:
* **Token rotation** (`xoxe`-prefixed tokens): they expire every 12 hours, incompatible with the static-credential model. Disable rotation and take a fresh token.
* **Enterprise Grid org-wide installs**: install per workspace (Install to Workspace, not org-wide) and create one integration per workspace.
Count by **installation**: one app installed in one Slack workspace backs exactly one integration. Installing the same app into another Slack workspace creates a distinct identity, which can back another integration.
If you want one bot to reach several projects' memory, add those projects as **read-only projects** on the same integration instead.
Access is decided entirely on the **Slack side** — we deliberately do not add a second allowlist:
* **DMs**: anyone in the workspace where the app is installed
* **Channels**: whoever is in a channel the bot has been added to
* **Slack Connect external users**: always ignored — no quota use, no memory writes
Two layers:
* **Conversation context is per-person.** In the same thread, A's exchange never appears in B's context.
* **Project memory is shared.** Whatever lands in the read-write project is searchable by everyone who can reach the bot — that is the point of the feature, and why the read-write project is an authorization decision.
Two different situations:
* **"Your account quota is exhausted…"** — the team's plan quota ran out. It does **not** recover on its own; contact the admin to top up or upgrade.
* **"We're handling many requests, please retry shortly."** — momentary load on our side, not you sending too fast. Just retry.
Session records, the Slack-user-to-actor mappings, and session attachment references — irreversibly.
**Memory already written into projects and ingested files are not deleted** — they belong to the project, not the integration.
For a temporary pause, use the switch on the card instead of deleting.
# Connect via MCP
Source: https://docs.memorylake.ai/features/memorylake/mcp-servers/creating-api-keys
Connect Claude Code, Codex, Cursor, and other MCP clients to MemoryLake with standard OAuth2
MemoryLake runs a **remote MCP server** that any MCP-capable client can connect to over HTTP. Authorization uses standard **OAuth2** — you never paste a secret into a config file, and you choose which workspace and boundary the client may access on the consent screen.
## Server URL
```text theme={null}
https://app.memorylake.ai/memorylake/mcp/v2
```
The console shows this URL with a copy button at **Integrations → MCP**, along with ready-made commands per client.
The connect page is scope-less: there is no project picker. You pick the workspace and boundary during the OAuth consent step, so one client connection can be re-authorized to a different scope without editing any config.
## Connect Your Client
```bash theme={null}
claude mcp add --transport http --scope user memorylake https://app.memorylake.ai/memorylake/mcp/v2
```
Claude Code opens the MemoryLake consent screen on first use. Approve it, choose your workspace and boundary, and the tools appear.
Add the server to your Codex configuration:
```toml theme={null}
[mcp_servers.memorylake]
url = "https://app.memorylake.ai/memorylake/mcp/v2"
```
Then sign in:
```bash theme={null}
codex mcp login memorylake
```
```json theme={null}
{
"mcpServers": {
"memorylake": {
"url": "https://app.memorylake.ai/memorylake/mcp/v2"
}
}
}
```
Restart the client; it will prompt for OAuth authorization on first connection.
Any client that supports remote MCP servers over HTTP with OAuth2 works. Point it at the server URL above — no API key, no custom headers. The client performs the standard OAuth2 authorization-code flow and stores the resulting token itself.
## What Connected Clients Can Do
Once authorized, the client gets tools for searching and analyzing the content in scope:
| Tool | What it does |
| - | - |
| `search_memory` | Hybrid keyword + semantic search across memories and documents |
| `fetch_memory` | Fetch detailed metadata and download links for specific results |
| `get_memorylake_metadata` | Overview — file counts by type, spreadsheet sheet names, document stats |
| `create_memory_code_runner` / `run_memory_code` | Sandboxed Python (pandas, numpy, …) over the files in scope, with state persisting across calls |
| `nl_query_database` | Natural-language SQL over a connected database, where one is configured |
OpenAI-protocol clients are automatically served simplified `search` / `fetch` variants of the same tools — one endpoint adapts to the client.
These tools read and analyze; they do not modify or delete your documents and memories.
## Managing Access
* **Re-scope**: re-run the OAuth flow to authorize a different workspace or boundary — no config change needed.
* **Revoke**: remove the authorization from the console; the client's token stops working immediately.
* **Token lifetime**: access tokens are short-lived and refreshed automatically by the client.
Earlier versions of MemoryLake used a v1 MCP endpoint with a project-scoped key embedded in the URL (`…/mcp/v1?apikey=…`). That flow has been retired from the console in favor of OAuth2. The v1 endpoint remains available for backward compatibility, but new integrations should use the v2 URL above.
## Troubleshooting
Confirm the URL ends in `/mcp/v2` and the client is configured for a **remote HTTP** MCP server (not a local command). Make sure the client supports OAuth2 for MCP — older clients that only accept static tokens cannot use the v2 endpoint.
Check that you completed workspace and boundary selection on the consent screen. Re-run the client's MCP login to retry.
The authorized scope may point at an empty project. Confirm in the console that the workspace and project you selected actually contain documents or memories.
MCP availability depends on your deployment. If **Integrations → MCP** is missing, contact [support@memorylake.ai](mailto:support@memorylake.ai).
# OpenClaw Plugin Reference
Source: https://docs.memorylake.ai/features/memorylake/mcp-servers/openclaw-plugin
memorylake-openclaw — configuration, automatic behaviors, tools, CLI, and skills
The `memorylake-openclaw` plugin connects OpenClaw (and QClaw) agents to MemoryLake. This page is the configuration and capability reference; for a narrative walkthrough see the [Coding Agents scenario](/scenarios/coding-agents).
## Installation
The console's **Integrations → OpenClaw** card generates this pre-filled:
```bash theme={null}
curl -fsSL https://app.memorylake.ai/memorylake-openclaw/install.sh | bash -s -- \
--project-id --api-key sk-... --host https://app.memorylake.ai
```
Windows PowerShell: use `install.ps1` from the same host. The script writes the plugin config, sets `tools.profile` to `"full"` (required; it asks first if you've customized it), and restarts the gateway. Environment variables `MEMORYLAKE_API_KEY` / `MEMORYLAKE_PROJECT_ID` / `MEMORYLAKE_HOST` can replace the flags.
```bash theme={null}
openclaw plugins install memorylake-openclaw
openclaw gateway restart
```
Then add to `~/.openclaw/openclaw.json` (QClaw: `~/.qclaw/openclaw.json`):
```json5 theme={null}
{
"plugins": {
"entries": {
"memorylake-openclaw": {
"enabled": true,
"config": {
"apiKey": "${MEMORYLAKE_API_KEY}", // env interpolation supported
"projectId": "proj-...",
"host": "https://app.memorylake.ai"
}
}
}
}
}
```
## Configuration Reference
| Key | Default | Notes |
| - | - | - |
| `apiKey` | — | **Required.** MemoryLake API key (`sk-…`); supports `${ENV_VAR}` interpolation |
| `projectId` | — | **Required.** Project the agent reads/writes |
| `host` | `https://app.memorylake.ai` | Your MemoryLake host |
| `autoRecall` | `true` | Inject recall instructions each user turn |
| `autoCapture` | `true` | Report conversation turns for server-side extraction |
| `autoUpload` | `true` | Upload files shared in chat to the project |
| `topK` | `5` | Results per retrieval |
| `searchThreshold` | `0.3` | Minimum relevance score |
| `rerank` | `true` | Rerank retrieval results |
| `webSearchIncludeDomains` / `webSearchExcludeDomains` / `webSearchCountry` / `webSearchTimezone` | — | Constraints for `advanced_web_search` |
Unknown config keys are rejected with an error — don't add custom fields. Config **hot-reloads**: changes to key, project, host, or retrieval settings take effect without a gateway restart.
### Per-agent / per-directory override
`{workspace}/.memorylake/config.json` overrides the global config for sessions in that directory — typically a different `projectId` per client or codebase. The bundled `agent-memorylake-config` skill sets this up conversationally.
## Automatic Behaviors
* **Auto-Recall** — injects instructions (plus a per-turn reminder) directing the agent to call `retrieve_context` before answering each user message, and announces the project's subscribed Open Data categories at session start. Model-driven recall keeps latency low while ensuring fresh context.
* **Auto-Capture** — after each successful user turn, new conversation messages (deduplicated via a per-session watermark) are sent to MemoryLake, where extraction decides what to store, update, or merge. Tool outputs are not captured.
* **Auto-Upload** — files you share in chat are detected and uploaded to the project asynchronously (deduplicated against prior uploads); the agent is never blocked waiting.
## Agent Tools
| Tool | Purpose |
| - | - |
| `retrieve_context` | One call searches **memories and documents** in parallel and returns user context, preferences, history, and document excerpts — plus any unresolved memory conflicts |
| `memory_store` | Explicitly store a fact (text, optional user id and metadata) |
| `memory_list` | List a user's memories |
| `memory_forget` | Delete a memory by id |
| `document_download` | Download a project document to the workspace (`.memorylake/downloads/`) |
| `advanced_web_search` | Web search under the configured domain/country constraints — registered as **optional**, off unless the agent explicitly allows it |
| `open_data_search` | Search curated datasets by category: research/academic (arXiv, PubMed…), clinical trials, drug databases, financial markets, company fundamentals (SEC), economic data (FRED, World Bank), patents (USPTO) |
## CLI
```bash theme={null}
openclaw memorylake search "" [--limit n] # search memories from the terminal
openclaw memorylake upload [--project-id id] # file, directory, or archive
openclaw memorylake stats # project stats
```
`upload` accepts single files, directories (500-file guardrail against accidental `node_modules` uploads), and archives — zip/tar/tgz/7z/bz2/rar/xz are auto-extracted and uploaded with concurrency, skipping `.DS_Store`-style junk.
## Bundled Skills
| Skill | Purpose |
| - | - |
| `memorylake-upload` | Upload files/archives/directories and associate them with the project |
| `memorylake-api` | Fallback: discover and call any MemoryLake REST endpoint from the live OpenAPI spec |
| `migrate-memories-to-memorylake` | Import memories and conversation history from existing agent session files |
| `agent-memorylake-config` | Write per-directory config overrides |
## Companion: Models Plugin
`memorylake-models-openclaw` (separate plugin) registers MemoryLake [Model Router](/features/model-router/overview) as an OpenClaw **model provider** — one `sk-…` key for all supported LLMs:
```bash theme={null}
openclaw plugins install memorylake-models-openclaw
openclaw memorylake setup # interactive: validates key, lists models, sets default
# or: choose "Memorylake AI" in `openclaw onboard`
# or headless: export MEMORYLAKE_API_KEY=sk-...
```
Models are fetched live from `GET /v1/models`; the plugin writes an OpenAI-compatible provider entry (`https://app.memorylake.ai/v1`) into your OpenClaw config.
## Privacy & Telemetry
The plugin talks only to your configured `host`. Usage telemetry is **opt-in** — nothing is reported unless you explicitly configure a telemetry key.
## Troubleshooting
* **Tools missing** → ensure `tools.profile` is `"full"` and the gateway was restarted after install.
* **401 errors** → key invalid/expired; update `apiKey` (hot-reloads, no restart needed).
* **Wrong project receiving memories** → check for a per-directory `.memorylake/config.json` overriding your global `projectId`.
# Integrations Overview
Source: https://docs.memorylake.ai/features/memorylake/mcp-servers/overview
Bring MemoryLake memory into your agents and apps — OpenClaw plugins, REST API, and the MCP server
## Overview
Memory is only useful where you work. MemoryLake offers several integration paths, all reading and writing the same memory pool:
| Integration | Status | Best for |
| - | - | - |
| **OpenClaw plugin** | ✅ Available | Coding agents with automatic recall, capture, and file upload |
| **QClaw plugin** | ✅ Available | Same plugin, QClaw runtime (`~/.qclaw/openclaw.json`) |
| **Hermes Agent** | ✅ Available | One-line install of a memory-connected agent (macOS) |
| **REST API** | ✅ Available | Full programmatic control from any language |
| **MCP server (OAuth2)** | ✅ Available | Claude Code, Codex, Cursor, Claude Desktop, and any OAuth2-capable MCP client |
| **Chrome extension, chat-history import** | 🔜 Coming soon | Guided setup per client |
Open **Integrations** in the [console](https://app.memorylake.ai) sidebar to see what's enabled for your account — each available card generates setup commands pre-filled with your project id and API key.
## OpenClaw / QClaw Plugin
The richest integration: install once and your agent gains **Auto-Recall** (retrieves relevant memories and document context before answering), **Auto-Capture** (durable facts from each conversation are stored and merged in the background), and **Auto-Upload** (files you share in chat land in your project automatically) — plus explicit memory tools and a CLI.
Configuration, tools, CLI, skills, and per-agent scoping.
The end-to-end walkthrough with day-to-day examples.
## REST API
Everything the console does, programmatically: projects, document upload/search, memory add/search/trace/forget, and conflict resolution.
* **Base URL**: `https://app.memorylake.ai/openapi/memorylake`
* **Auth**: `Authorization: Bearer sk-…` ([create a key](/authentication))
* **Live spec**: `https://app.memorylake.ai/openapi/memorylake/api-docs/open-api`
The console's **Integrations → API** card also generates an AI-ready prompt describing the endpoints, so you can hand your agent the API surface directly. Full documentation in the [API Reference](/features/memorylake/api-reference/overview).
## MCP Server
MemoryLake runs a **remote MCP server** (Model Context Protocol over HTTP, authorized with standard OAuth2) at:
```text theme={null}
https://app.memorylake.ai/memorylake/mcp/v2
```
Connect Claude Code with one command — `claude mcp add --transport http --scope user memorylake ` — or point Codex, Cursor, or Claude Desktop at the same URL. You pick the workspace and boundary on the OAuth consent screen, so no secret ever lands in a config file. See [Connect via MCP](/features/memorylake/mcp-servers/creating-api-keys) for per-client setup.
Connected clients get search and analysis tools over the memories and documents in scope:
| Tool | What it does |
| - | - |
| `search_memory` | Hybrid keyword + semantic search across the project's memories and documents |
| `fetch_memory` | Fetch detailed metadata and download links for specific results |
| `get_memorylake_metadata` | Project overview — file counts by type, spreadsheet sheet names, document stats |
| `create_memory_code_runner` / `run_memory_code` | Sandboxed Python (pandas, numpy, …) for analyzing project files, with state persisting across calls |
| `nl_query_database` | Natural-language SQL over connected databases (where configured) |
OpenAI-protocol clients (like ChatGPT) are automatically served simplified `search` / `fetch` variants of the same tools — one endpoint adapts to the client.
## Which Integration Should I Use?
* **You use an MCP-capable client** (Claude Code, Codex, Cursor, Claude Desktop) → MCP. One command, OAuth2, nothing to store.
* **You want automatic memory in a coding agent** → OpenClaw/QClaw plugin. Auto-recall, auto-capture, and auto-upload beat manual tool calls.
* **You're building a product** → REST API (generally available) or [Memory Router](/features/memory-router/overview) (private preview) for call-level memory.
* **You want MemoryLake's models too** → add the [Model Router](/features/model-router/overview) — same key, OpenAI-compatible endpoint, plus the `memorylake-models-openclaw` plugin for OpenClaw.
## Next Steps
Install, configure, and master the agent plugin
Per-client setup for Claude Code, Codex, Cursor, and Desktop
# Memory Best Practices
Source: https://docs.memorylake.ai/features/memorylake/memories/best-practices
How to get accurate, useful long-term memory out of conversations, documents, and agents
MemoryLake extracts memories automatically — you don't write them by hand. Best practice is therefore less about *authoring* and more about *feeding the system well* and *keeping it honest*. Here's what works.
## Feeding Memory Well
### Say facts explicitly when they matter
Extraction is good at picking up clear statements and decisions, and appropriately skips small talk. When something must be remembered, state it plainly:
* ✅ *"Remember: the budget cap for Q1 is \$75K, hard limit."*
* ✅ *"We decided to use PostgreSQL — better JSON support and the team knows it."*
* ⚠️ *"Yeah let's maybe go with the second option I guess"* — ambiguous references extract poorly. Name the thing.
### Include the why, not just the what
A decision with rationale is a far more useful memory than a bare conclusion. *"We chose PostgreSQL over MySQL for JSON support and team expertise"* lets a future assistant answer *"why Postgres?"* — not just *"which database?"*
### Upload the source document, don't paraphrase it
If knowledge lives in a file, upload the file. Document content is parsed and indexed with higher fidelity than a chat summary of it, and memories extracted from it carry a trace to the actual source.
### Correct out loud
When something changes, say so explicitly — *"The launch moved from October 15 to November 1"* — rather than just mentioning the new date in passing. Explicit corrections update or conflict-flag the old memory instead of leaving two versions in play.
## Scoping: the Highest-Leverage Decision
Retrieval is scoped to projects. Well-scoped projects mean relevant recall; kitchen-sink projects mean noise.
* **One project per context** — per client, per initiative, per life domain. Not one giant "Everything" project.
* **Use per-agent config for multi-client work** — the OpenClaw plugin's per-directory `.memorylake/config.json` pins each working folder to its own project, so client A's facts never surface in client B's session. See [Coding Agents](/scenarios/coding-agents).
* **Split when retrieval gets noisy** — if answers start citing irrelevant context, your project is probably covering two contexts. Split it.
## Keeping Memory Honest
### Review conflicts promptly
Conflicts are memory's immune system — but only if someone resolves them. Check the project's **Conflicts** tab when the assistant seems uncertain about a fact, and after any burst of corrections. In teams, make sure someone holds the resolve permission and owns the habit.
### Audit with traces
Before trusting a surprising assertion, open the memory's **Source Trace** — you'll see exactly which conversation or document produced it. This is also the fastest way to debug *why* an assistant believes something wrong: find the memory, trace it, then edit or forget it.
### Prune deliberately
* **Edit** memories whose details drifted (titles, numbers, names)
* **Forget** memories that are obsolete or should never have been captured — deletion is permanent and takes effect everywhere
* Don't over-prune: dedup and merging already handle repetition; delete for *wrongness*, not tidiness
## For Teams
* **Establish what belongs in shared memory** — decisions, policies, client facts: yes. Personal working notes: keep in personal space. The workspace boundary is the individual/organizational memory line.
* **Assign conflict ownership** — a project without a conflict-resolver accumulates stale facts silently.
* **Lean on permissions, not caution** — if only leads should delete memories, remove `mem_delete` from other roles rather than relying on convention. See the [Permission Reference](/features/team-collaboration/permission-reference).
## For Builders (API)
* **Send full conversation turns** to add-memory (`infer: true`) and let extraction decide what's durable — pre-filtering usually loses context that improves extraction quality.
* **Use `user_id`** so memories attribute to the right end user.
* **Set `infer: false`** only when you're storing an already-curated fact verbatim.
* **Expose trace and forget to your users** — "why do you know this?" and "forget this" build trust and cover compliance.
* **Check conflicts programmatically** if your product asserts facts — see [Conflicts API](/features/memorylake/api-reference/memories/list-memory-conflicts).
## Common Mistakes
| ❌ Mistake | ✅ Instead |
| - | - |
| One giant project for everything | One project per context; retrieval stays sharp |
| Pasting a doc's contents into chat | Upload the document itself |
| Correcting facts implicitly | State corrections explicitly so old memory gets updated/conflicted |
| Ignoring the Conflicts tab | Review after corrections; assign an owner in teams |
| Deleting memories to "clean up" | Edit or forget only what's wrong — merging already handles duplicates |
| Trusting a weird assertion blindly | Open its source trace first |
## Next Steps
Extraction, retrieval, traces, and conflicts in depth
See these practices applied end to end
# Memories
Source: https://docs.memorylake.ai/features/memorylake/memories/overview
How MemoryLake extracts, stores, retrieves, and maintains long-term memories — traces, conflicts, and management
## Overview
Memories are the heart of MemoryLake: structured, durable facts distilled from your conversations and documents. Unlike a chat log (noisy, unbounded) or a document chunk (raw text), a memory is an *extracted* statement worth keeping — deduplicated, searchable, traceable to its source, and checked for consistency.
## Where Memories Come From
Playground chats and agent sessions are analyzed automatically — durable facts are extracted, merged with what's already known, and stored. Transcripts stay transcripts; facts become memories.
Uploaded files are parsed and indexed; key content becomes retrievable memory alongside conversational facts.
Store a memory deliberately — via the API (`add memory`), agent tools (`memory_store`), or by telling the assistant "remember this".
Connected agents (OpenClaw and friends) report conversation turns in the background; the server decides what to store, update, or merge.
## What Makes a Memory Trustworthy
### Source Traces
Every memory keeps a trace back to its origin — the conversation turn or document it was extracted from. Open any memory in the console and check its **Source Trace** tab, or fetch it via the [trace API](/features/memorylake/api-reference/memories/get-memory-trace). When an assistant asserts something, you can always answer *"how do you know that?"*
### Conflict Detection
When a new memory contradicts an existing one — a moved deadline, a changed policy, a corrected fact — MemoryLake doesn't silently keep both or overwrite blindly. It raises a **conflict**:
1. The conflicting pair appears in the project's **Conflicts** tab
2. A reviewer (anyone with the resolve permission) picks what's true
3. Memory stays current, and the resolution is deliberate rather than accidental
Conflicts are also exposed via [API](/features/memorylake/api-reference/memories/list-memory-conflicts), and agent tools surface unresolved conflicts alongside retrieval results so assistants can flag uncertainty instead of asserting stale facts.
### Deduplication & Merging
Repeating yourself doesn't create ten copies of the same fact — extraction merges new information into existing memories where they overlap, and updates them when details change.
## Retrieving Memories
* **Console**: browse and search in the **Memories** page (workspace-wide) or a project's Memories tab — including a word-frequency visualization for a quick sense of what a project knows
* **Semantic search**: hybrid keyword + embedding retrieval, scoped to a project or workspace — the same engine behind the Playground, agent tools, and the [search API](/features/memorylake/api-reference/memories/search-memories)
* **Automatic recall**: connected assistants retrieve relevant memories before answering — you don't query anything by hand
## Managing Memories
### Browse & Inspect
The Memories views support search, filtering, pagination, and bulk selection. Click any memory for details: full content, metadata, and source trace.
### Edit
Open a memory and edit its content when a fact needs refinement. Edits take effect immediately in future retrieval.
### Forget (Delete)
Forgetting a memory is permanent — it is removed from all future retrieval for every connected assistant and API client.
Delete from the memory's action menu (or the [forget API](/features/memorylake/api-reference/memories/forget-memory)). This is also your "right to be forgotten" mechanism when building user-facing products.
## Individual and Organizational Memory
The same machinery serves two different kinds of knowledge:
| | Individual memory | Organizational memory |
| - | - | - |
| Belongs to | A person (across all their tools) | A team workspace |
| Examples | Preferences, personal facts, working style | Policies, decisions, domain facts, client history |
| Governance | Private to you | Roles + fine-grained permissions per action |
| Typical worry | "Will my tools remember me?" | "Will knowledge survive people leaving?" |
Both flow through extraction → trace → conflict-checking → retrieval; the difference is scope and governance. See the [Personal AI Memory](/scenarios/personal-ai-memory) and [Team Knowledge Base](/scenarios/team-knowledge-base) scenarios.
### Which subject a fact belongs to
Individual memory has two subjects, not one — a person and an agent both accumulate their own facts,
and both keep them across every project in a workspace. Organizational memory is the third: it stays
with the project, whoever contributed it.
Which subject a fact belongs to is what decides where you read it back:
* **A person** — *"Jane prefers dark mode"*
* **An agent**, read by its agent id — *"This agent answers in French"*
* **A project** — *"Q1 revenue was \$12.5M"*
People and agents have the same shape: anything you can do with a person's facts you can do with an
agent's. See [Actor Facts](/features/memorylake/api-reference/facts/list-actor-facts) for the request
and response shapes, which both use.
## Working with Memories Programmatically
```bash theme={null}
# Feed a conversation — facts are extracted from the messages you append
POST /api/v3/workspaces/{workspaceId}/memories/conversations
POST /api/v3/conversations/{conversationId}/messages
# Import documents into a project
POST /api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/documents
# Search across documents and facts in one call
POST /api/v3/workspaces/{workspaceId}/memories/search
# Browse and manage extracted facts
GET /api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts
POST /api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts/{factId}/forget
# List / resolve conflicts
GET /api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/conflicts
POST /api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/conflicts/{conflictId}/resolve
```
All paths are relative to `https://app.memorylake.ai/openapi/memorylake`. Start with [Core Memory Operations](/features/memorylake/api-reference/core-memory/overview) for the end-to-end flow.
Earlier project-scoped `api/v1` and `api/v2` memory endpoints remain available for existing integrations and are documented under **Deprecated** in the API reference. New integrations should use the v3 paths above.
## Next Steps
Get better memories out of conversations, documents, and agents
Bring memory recall into your agents and apps
Manage memories programmatically
# Overview
Source: https://docs.memorylake.ai/features/memorylake/overview
Turn documents and conversations into searchable, structured memories for AI applications
## What is MemoryLake?
MemoryLake is a memory platform for AI applications. You feed it documents and conversations, and it automatically extracts structured facts that your agents and applications can search and retrieve. Think of it as long-term memory for AI -- persistent, queryable, and organized by who said what.
MemoryLake is built around three pillars:
Import files into a project. MemoryLake indexes them for semantic search so your AI can find relevant content across your entire knowledge base.
Submit user-assistant conversations. MemoryLake automatically extracts structured facts -- preferences, decisions, context -- and associates them with the right actors.
Query across both documents and facts with a single natural language search. Get the most relevant information regardless of how it entered the system.
## Resource Model
MemoryLake organizes data in a clear hierarchy:
```
Workspace (data isolation boundary)
|
+-- Actors (participant identities -- HUMAN or ASSISTANT)
| +-- Actor Facts (per-user memory, follows the actor across projects)
|
+-- Projects (knowledge containers)
+-- Documents (imported files, indexed for search)
+-- Conversations
| +-- Messages (user-assistant exchanges)
+-- Project Facts (extracted knowledge, scoped to this project)
```
**Workspaces** provide data isolation -- like tenants. Each workspace has its own actors, projects, and search index.
**Actors** represent participants. Every human user or AI assistant gets an actor identity. Facts about an actor follow them across all projects in the workspace.
**Projects** are knowledge containers. A project holds documents, conversations, and the facts extracted from them. You typically create one project per use case, domain, or application.
## How It Works
You bring data into a project through two channels: import documents from the Library, or submit conversations via the API. Both channels feed the same project.
MemoryLake processes your content automatically. Documents are indexed for semantic search. Conversations are analyzed to extract structured facts -- things like user preferences, stated goals, decisions, and context.
Query the workspace with natural language. MemoryLake searches across both document content and extracted facts, returning the most relevant results in a single response.
## Working in the Console
The API is one way in; the console is the other. Everything above is also available as a product surface:
Chat with memory in the Playground, upload files, and review what was extracted — no code.
The Library: folder hierarchies, uploads, comments, and supported formats.
Browse, search, trace, and resolve conflicts in extracted memories.
Create projects, associate documents, and navigate the project dashboard.
Mount WPS and Lark document libraries into your personal library.
MCP over OAuth2, the OpenClaw agent plugin, and REST API access.
## Scenarios
One private memory shared by every AI tool you use.
Governed organizational memory that outlives personnel changes.
Auto-recall, auto-capture, and auto-upload for OpenClaw agents.
Per-user long-term memory in your own product.
## Get Started
Create a workspace, submit a conversation, and search your memories in 5 minutes.
Understand the resource hierarchy and when to use multiple workspaces vs. multiple projects.
Learn how actors provide per-user memory that follows users across projects.
Understand how conversations become structured facts and how search unifies everything.
# Associating Documents with Projects
Source: https://docs.memorylake.ai/features/memorylake/project-management/document-association
Add documents to a project's context — by upload, drag-and-drop, or from your library
## Overview
A document must be associated with a project for its content to appear in that project's retrieval. There are three ways to get documents in — and the same file can serve several projects at once.
## Ways to Add Documents
### Upload directly
In the project's **Files** tab, drag files (or whole folders — structure preserved) onto the page, or use the upload button. Files land in your Library and are associated with the project in one step.
### Attach in chat
Attach a file to a Playground message (or share one with a connected agent — the OpenClaw plugin auto-uploads it). It's uploaded into the project's context automatically.
### Associate from your Library
Already uploaded elsewhere, or mounted via a [connector](/features/memorylake/connectors/overview)?
Navigate to the project and click **Add documents**.
A dialog shows your Library as a tree with checkboxes — select individual files, whole folders (all contents included; half-checked means partially selected), or a mix. Connector spaces (WPS Space, Lark Space) appear here too.
Selected items associate with the project and enter processing.
Documents appear in the Files tab with a processing status.
## Processing Status
| Status | Meaning |
| - | - |
| **Pending** | Queued for parsing and indexing |
| **Running** | Being processed |
| **Okay** | Content is searchable in this project |
| **Error** | Processing failed — open for details |
## Removing Documents
Disassociating a document (remove action in the Files tab) takes it out of this project's context. **The file itself stays in your Library** — and in any other projects it's associated with. Deleting a file from the Library, by contrast, removes it everywhere.
## Best Practices
* Associate only what belongs to the project's purpose — focused projects retrieve better
* Use folder association to bring in related files at once
* Check processing status after adding; content isn't retrievable until `okay`
* Review and remove outdated documents periodically — stale sources produce stale answers
## Next Steps
The Library: uploads, folders, and file operations
What happens to content after processing
# Workspaces & Projects
Source: https://docs.memorylake.ai/features/memorylake/project-management/overview
Organize memory into workspaces and projects — the containers that scope retrieval, access, and integrations
## Overview
MemoryLake organizes knowledge in a two-level hierarchy: **workspaces** contain **projects**. Workspaces are the top-level container (your personal space has a default one; teams create more); projects are focused bodies of knowledge inside them — the unit you point an AI at.
```text theme={null}
Workspace
├── Project A ← documents + memories + open data + integrations
├── Project B
├── Agents ← AI assistants operating in this workspace
└── Memory ← workspace-wide memory view
```
## What is a Project?
A project is:
* **A retrieval scope** — searches, Playground context, and agent recall operate within a project, so contexts don't bleed into each other
* **A container** for documents, extracted memories, and Open Data subscriptions
* **An integration unit** — agent plugins and MCP keys connect to one project
* **A permission boundary** — in teams, access can be granted per project
A default workspace (with a first project) is provisioned automatically when you sign up — you only manage this hierarchy explicitly when your usage grows.
## The Project Dashboard
Open a project (console → **Workspaces** → workspace → project) to find its tabs:
| Tab | What's there |
| - | - |
| **Files** | Associated documents with processing status; add by upload, drag-and-drop, or from your Library |
| **Open Data** | Curated industry datasets this project subscribes to |
| **Memories** | Extracted memories — search, edit, forget, word-frequency view, source traces |
| **Conflicts** | Contradictory memories awaiting resolution |
| **Integrations** | Connect agents and API access scoped to this project |
See [Project Dashboard](/features/memorylake/project-management/project-dashboard) for details.
## Core Guides
Navigate tabs, monitor processing, manage the project.
Link documents from your library into projects.
## How to Slice Projects
* **Personal**: one per life/work context — "Health", "Home purchase", "Side project". Ask: *should an assistant answering about X ever cite Y?* If no, separate projects.
* **Team**: one per initiative, client, or domain — "Q3 launch", "Customer X", "Compliance 2026". Project-level permissions let you grant a contractor exactly one project.
* **Builders**: commonly one project per end user (or tenant) — see [Build Apps with Memory](/scenarios/ai-apps-with-memory).
## Common Use Cases
Group papers, notes, and data files in one project; subscribe research Open Data; connect your agent. Questions get answered from exactly this corpus.
One project per client. The OpenClaw plugin's per-directory config pins each client's working folder to its project — memories never cross clients.
Projects per domain ("Pricing", "Legal", "Onboarding") inside a shared workspace, with per-project permissions where needed.
## Getting Started
In your workspace, create a project with a clear name and purpose description.
Upload files in the Files tab, associate existing Library documents, subscribe Open Data categories.
Use the Playground scoped to this project — memories extract automatically. Review them in the Memories tab.
From the Integrations tab, install the OpenClaw plugin or set up API access for this project.
# Project Dashboard
Source: https://docs.memorylake.ai/features/memorylake/project-management/project-dashboard
Navigate a project's tabs — files, open data, memories, conflicts, and integrations
## Dashboard Overview
Open a project via **Workspaces → your workspace → project**. The project detail page organizes everything into tabs; which tabs you see depends on your permissions (and enabled features).
## Files Tab
The project's associated documents:
* **Add content**: drag-and-drop upload, folder upload, or associate existing documents from your Library
* **Processing status** per document: `pending` → `running` → `okay` (or `error` with details) — content becomes searchable once processing completes
* **Remove**: disassociating a document removes it from the project's context; the file stays in your Library
## Open Data Tab
Subscribe the project to curated industry datasets — research/academic, clinical, financial, economic, patents, and more. Subscribed categories become searchable by the Playground and connected agents alongside your own content.
## Memories Tab
The project's extracted memories:
* **Search and filter** with live counts; switch to the **word-frequency view** for a quick sense of what the project knows
* **Inspect** any memory — content, metadata, and the **Source Trace** tab showing where it came from
* **Edit** or **forget** memories; bulk-select for cleanup
## Conflicts Tab
Contradictory memories land here instead of silently coexisting. Review each conflict and resolve it — see [Memories](/features/memorylake/memories/overview#conflict-detection). (Requires the conflict-resolve permission in team spaces.)
## Integrations Tab
Connect this specific project to your tools: OpenClaw / QClaw / Hermes setup with pre-filled commands, and API access details. See the [Integrations Overview](/features/memorylake/mcp-servers/overview).
## Editing Project Details
Project name and description can be edited from the project page. Deleting a project removes its memories and document associations (library files remain).
## Next Steps
Add documents to the project
How extraction, traces, and conflicts work
Connect agents and apps
# Quick Start
Source: https://docs.memorylake.ai/features/memorylake/quickstart
Get started with MemoryLake in 5 minutes -- create a workspace, submit a conversation, and search your memories
This guide walks you through the core MemoryLake workflow using the API. By the end, you will have created a workspace, submitted a conversation, and searched the extracted memories.
## Prerequisites
* A MemoryLake account with an API key (see [Authentication](/authentication))
* `curl` installed (or any HTTP client)
All examples use the base URL `https://app.memorylake.ai/openapi/memorylake`. Replace `YOUR_API_KEY` with your actual API key in every request.
## End-to-End Walkthrough
Log in to the [MemoryLake Console](https://app.memorylake.ai) and generate an API key from your account settings. You will use this key in the `Authorization` header for all API calls.
```bash theme={null}
export MEMORYLAKE_API_KEY="YOUR_API_KEY"
```
A workspace is the top-level container for all your data. Create one to get started.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "ws-quickstart-001",
"name": "My First Workspace",
"description": "Testing MemoryLake memory extraction"
}'
```
```json Response theme={null}
{
"success": true,
"data": {
"id": "ws-8001856949ad4f6a5b6226f415ffa877",
"custom_id": "ws-quickstart-001",
"name": "My First Workspace",
"description": "Testing MemoryLake memory extraction",
"created_at": "2026-07-09T10:00:00Z"
}
}
```
Save the workspace `id` -- you will need it in subsequent steps.
An actor represents a participant in conversations. Create one for the human user whose memory you want to track.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/actors \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "jane-001",
"display_name": "Jane"
}'
```
```json Response theme={null}
{
"success": true,
"data": {
"id": "actor-7b5470549febfaca2acc5a3ebcaa2138",
"custom_id": "jane-001",
"display_name": "Jane",
"created_at": "2026-07-09T10:01:00Z"
}
}
```
Bind the actor to your workspace so MemoryLake can associate facts with this actor across all projects in the workspace. See [Bind Actor](/features/memorylake/api-reference/actors/bind-actor) for details.
A project is a knowledge container within a workspace. It holds documents, conversations, and the facts extracted from them.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "proj-support-001",
"name": "Customer Support Bot",
"description": "Knowledge base for our support assistant"
}'
```
```json Response theme={null}
{
"success": true,
"data": {
"id": "proj-46582895f4e9b350c175f023be9aa61a",
"custom_id": "proj-support-001",
"name": "Customer Support Bot",
"description": "Knowledge base for our support assistant",
"workspace_id": "ws-8001856949ad4f6a5b6226f415ffa877",
"created_at": "2026-07-09T10:02:00Z"
}
}
```
Submit a conversation to the workspace. First, create the conversation, then add messages one at a time. MemoryLake automatically extracts structured facts from the messages.
Every message names its predecessor with `parent_message_id`: `null` for the first message, and the `id` the previous append returned for every message after it. That is how you declare the order of a conversation.
**Create the conversation:**
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/memories/conversations \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "conv-onboarding-001",
"kind": "DIRECT",
"rw_project_ids": ["proj-46582895f4e9b350c175f023be9aa61a"],
"name": "Onboarding chat with Jane"
}'
```
```json Response theme={null}
{
"success": true,
"data": {
"id": "conv-86d9f1d995a9c69bd8c2b0ce431d4903",
"custom_id": "conv-onboarding-001",
"kind": "DIRECT",
"rw_project_ids": ["proj-46582895f4e9b350c175f023be9aa61a"],
"name": "Onboarding chat with Jane",
"created_at": "2026-07-09T10:03:00Z"
}
}
```
**Append the first message (user):**
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-86d9f1d995a9c69bd8c2b0ce431d4903/messages \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "msg-001",
"actor_id": "actor-7b5470549febfaca2acc5a3ebcaa2138",
"parent_message_id": null,
"content": [
{
"block_type": "TEXT",
"text": "Hi, I am Jane. I work at Acme Corp as a product manager. I prefer concise answers and I use dark mode in all my apps."
}
]
}'
```
**Append the second message (assistant).** Its `parent_message_id` is the `id` that the first append returned:
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/conversations/conv-86d9f1d995a9c69bd8c2b0ce431d4903/messages \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"custom_id": "msg-002",
"actor_id": "actor-7b5470549febfaca2acc5a3ebcaa2138",
"parent_message_id": "msg_jkl345",
"content": [
{
"block_type": "TEXT",
"text": "Welcome Jane! I have noted your preferences. How can I help you today?"
}
]
}'
```
After you submit messages, MemoryLake processes them asynchronously. Facts are typically available within a few seconds.
Search across the workspace to find the facts that MemoryLake extracted from the conversation.
```bash theme={null}
curl -X POST https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/memories/search \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What are Jane preferences?"
}'
```
```json Response theme={null}
{
"success": true,
"data": {
"documents": [],
"facts": [
{
"id": "fact-18b616c73c16f87fb84561b0a3f2bc17",
"fact": "Jane prefers concise answers",
"score": 0.95,
"metadata": {},
"created_at": "2026-07-09T10:03:05Z",
"updated_at": "2026-07-09T10:03:05Z"
},
{
"id": "fact-190ec75793105e8f5cb3f1b2fe3042a6",
"fact": "Jane uses dark mode in all her apps",
"score": 0.92,
"metadata": {},
"created_at": "2026-07-09T10:03:05Z",
"updated_at": "2026-07-09T10:03:05Z"
},
{
"id": "fact-413914260fefa013b6dc0a4c5ff65baf",
"fact": "Jane works at Acme Corp as a product manager",
"score": 0.85,
"metadata": {},
"created_at": "2026-07-09T10:03:05Z",
"updated_at": "2026-07-09T10:03:05Z"
}
]
}
}
```
MemoryLake automatically extracted structured facts from the conversation and associated them with Jane's actor. These facts persist and are searchable across the workspace.
## Complete Python Example
Here is the full flow in a single Python script:
```python quickstart.py theme={null}
import requests
import time
BASE_URL = "https://app.memorylake.ai/openapi/memorylake/api/v3"
API_KEY = "YOUR_API_KEY"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
# 1. Create a workspace
workspace = requests.post(
f"{BASE_URL}/workspaces",
headers=headers,
json={
"custom_id": "ws-quickstart-001",
"name": "My First Workspace",
"description": "Testing MemoryLake memory extraction",
},
).json()
workspace_id = workspace["data"]["id"]
print(f"Workspace created: {workspace_id}")
# 2. Create an actor
actor = requests.post(
f"{BASE_URL}/actors",
headers=headers,
json={
"custom_id": "jane-001",
"display_name": "Jane",
},
).json()
actor_id = actor["data"]["id"]
print(f"Actor created: {actor_id}")
# 3. Create a project
project = requests.post(
f"{BASE_URL}/workspaces/{workspace_id}/projects",
headers=headers,
json={
"custom_id": "proj-support-001",
"name": "Customer Support Bot",
"description": "Knowledge base for our support assistant",
},
).json()
project_id = project["data"]["id"]
print(f"Project created: {project_id}")
# 4. Create a conversation
conversation = requests.post(
f"{BASE_URL}/workspaces/{workspace_id}/memories/conversations",
headers=headers,
json={
"custom_id": "conv-onboarding-001",
"kind": "DIRECT",
"rw_project_ids": [project_id],
"name": "Onboarding chat with Jane",
},
).json()
conversation_id = conversation["data"]["id"]
print(f"Conversation created: {conversation_id}")
# 5. Append messages (one at a time). Every message names its predecessor via
# parent_message_id; the first one has none, so it sends null.
first = requests.post(
f"{BASE_URL}/conversations/{conversation_id}/messages",
headers=headers,
json={
"custom_id": "msg-001",
"actor_id": actor_id,
"parent_message_id": None,
"content": [
{
"block_type": "TEXT",
"text": "Hi, I am Jane. I work at Acme Corp as a product manager. I prefer concise answers.",
}
],
},
).json()
requests.post(
f"{BASE_URL}/conversations/{conversation_id}/messages",
headers=headers,
json={
"custom_id": "msg-002",
"actor_id": actor_id,
"parent_message_id": first["data"]["id"],
"content": [
{
"block_type": "TEXT",
"text": "Welcome Jane! I have noted your preferences. How can I help you today?",
}
],
},
)
print("Messages submitted")
# 6. Wait for fact extraction
print("Waiting for fact extraction...")
time.sleep(5)
# 7. Search memories
results = requests.post(
f"{BASE_URL}/workspaces/{workspace_id}/memories/search",
headers=headers,
json={"query": "What are Jane preferences?"},
).json()
print("\nExtracted memories:")
for fact in results.get("data", {}).get("facts", []):
print(f" - {fact['fact']} (score: {fact['score']})")
```
## What You Built
In just a few minutes, you:
1. Created a **workspace** to isolate your data
2. Created an **actor** to represent a human user
3. Created a **project** to hold your knowledge
4. Submitted a **conversation** with messages
5. **Searched** and retrieved the automatically extracted facts
MemoryLake handled the hard part -- parsing the conversation, identifying facts, associating them with the right actor, and indexing everything for search.
## Next Steps
Learn when to use multiple workspaces vs. multiple projects
Understand how per-user memory works across projects
Dive deeper into how conversations become structured facts
Explore the full API for workspaces, actors, projects, and search
# Create API Key
Source: https://docs.memorylake.ai/features/model-router/getting-started/create-api-key
Learn how to create an API key to start using Model Router
## What is an API Key?
An API Key is your authentication credential for accessing Model Router — the same `sk-…` key that authenticates all of MemoryLake's programmatic surfaces. Which models a key can call is determined by your account's model-access group and any per-key model restrictions.
## How to Create an API Key
### Step 1: Navigate to API Keys
1. Log in to the [MemoryLake Console](https://app.memorylake.ai)
2. Click **API Keys** in the sidebar (or go directly to the [API Keys page](https://app.memorylake.ai/panel/token))
### Step 2: Create a New API Key
1. Click the create button
2. Configure the key:
* **Name**: for your own reference (e.g., "My Project API Key"), changeable later
* **Expiry**: Never / 7 days / 30 days (default) / 90 days / 1 year / custom date
* **Advanced → Group**: the model-access group, shown when your account has more than one
The API Keys page always displays your **API base address** with a copy button — use it as the base URL in your clients.
### Step 3: Save Your API Key
After creation, the key starting with `sk-` is revealed **once**. Copy and store it immediately.
Save your API key in a secure place (password manager or environment variable). Never share it publicly or commit it to version control. If a key is compromised, use **Rotate** in the key's detail panel to replace the secret, or disable/delete the key.
### Optional Hardening
From the key's detail panel you can also set:
* **Model restrictions** — limit which models this key may call
* **IP allowlist** — restrict usage to known addresses
* **Heartbeat** — require periodic liveness signals for long-running automation
## What's Next?
* **[How to Use API Key](/features/model-router/getting-started/use-api-key/overview)**: different ways to use your key
* **[List Available Models](/features/model-router/list-available-models)**: see which models your key can access
## Related Documentation
* [Use API Key Overview](/features/model-router/getting-started/use-api-key/overview)
* [List Available Models](/features/model-router/list-available-models)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
# AI Application Integrations
Source: https://docs.memorylake.ai/features/model-router/getting-started/use-api-key/ai-app-integrations
Connect Model Router to existing AI development tools like Claude Code and Codex CLI
## What are AI Application Integrations?
Instead of writing code yourself, you can connect Model Router to existing AI development tools. These tools provide user-friendly interfaces for AI-assisted coding and development.
Before configuring these tools, make sure you have:
1. Created an API key (see [Create API Key](/features/model-router/getting-started/create-api-key))
2. Checked which models are available (see [List Available Models](/features/model-router/list-available-models))
## Supported Applications
### Claude Code
Claude Code is a code editor integration tool based on Anthropic Claude. It provides AI-powered coding assistance directly in your terminal.
### Codex CLI
Codex CLI is a command-line interface AI code assistant tool that helps you write and understand code.
### Cherry Studio
Cherry Studio is a powerful desktop AI client with multi-model conversation and drawing capabilities. It integrates 30+ industry-specific intelligent assistants.
* **Official Website**: [https://cherry-ai.com/](https://cherry-ai.com/)
* **Download**: [https://cherry-ai.com/download](https://cherry-ai.com/download)
* **Official Documentation**: [https://docs.cherry-ai.com](https://docs.cherry-ai.com)
## Claude Code Integration
### What You Need
* **ANTHROPIC\_AUTH\_TOKEN**: Your API key from [Memorylake Console](https://app.memorylake.ai/panel/token) (starts with `sk-`)
* **ANTHROPIC\_BASE\_URL**: Model Router service address: `https://app.memorylake.ai/claude`
### Step 1: Install Claude Code
Install Claude Code globally via npm:
```bash theme={null}
npm install -g @anthropic-ai/claude-code
```
Verify installation:
```bash theme={null}
claude --version
```
### Step 2: Get Your API Key
Click "Add API Key" on the [API key management page](https://app.memorylake.ai/panel/token) in the Memorylake Console to get an API Key.
The name can be set arbitrarily. It's recommended to set the quota to unlimited. Keep other settings as default.
### Step 3: Configure Environment Variables
Set environment variables in your project directory:
```bash theme={null}
cd your-project-folder
export ANTHROPIC_AUTH_TOKEN=sk-...
export ANTHROPIC_BASE_URL=https://app.memorylake.ai/claude
claude
```
### Step 4: Initialize Configuration
After running, complete initialization as prompted:
1. Select your preferred theme + Enter
2. Confirm safety notice + Enter
3. Use default Terminal configuration + Enter
4. Trust working directory + Enter
### Step 5: Start Using
After configuration, you can code with your AI programming partner in the terminal.
### Persistent Configuration (Recommended)
To avoid repeatedly entering environment variables each time, you can write the configuration to shell configuration files:
**Bash Configuration:**
```bash theme={null}
echo -e '\n export ANTHROPIC_AUTH_TOKEN=sk-...' >> ~/.bash_profile
echo -e '\n export ANTHROPIC_BASE_URL=https://app.memorylake.ai/claude' >> ~/.bash_profile
echo -e '\n export ANTHROPIC_AUTH_TOKEN=sk-...' >> ~/.bashrc
echo -e '\n export ANTHROPIC_BASE_URL=https://app.memorylake.ai/claude' >> ~/.bashrc
```
**Zsh Configuration:**
```bash theme={null}
echo -e '\n export ANTHROPIC_AUTH_TOKEN=sk-...' >> ~/.zshrc
echo -e '\n export ANTHROPIC_BASE_URL=https://app.memorylake.ai/claude' >> ~/.zshrc
```
After configuration, restart the terminal to use directly:
```bash theme={null}
cd your-project-folder
claude
```
## Codex CLI Integration
### What You Need
* **OPENAI\_API\_KEY**: Your API key from [Memorylake Console](https://app.memorylake.ai/panel/token) (starts with `sk-`)
* **base\_url**: Model Router service address: `https://app.memorylake.ai/v1`
* **model**: Model name to use (check [available models](/features/model-router/list-available-models))
### Step 1: Install Node.js
Ensure Node.js environment is installed. Codex CLI requires Node.js support.
### Step 2: Install Codex CLI
Install Codex CLI globally via npm:
```bash theme={null}
npm i -g @openai/codex
```
Verify installation:
```bash theme={null}
codex --version
```
### Step 3: Get Your API Key
Click "Add API Key" on the [API key management page](https://app.memorylake.ai/panel/token) in the Memorylake Console to get an API Key.
The name can be set arbitrarily. It's recommended to set the quota to unlimited. Keep other settings as default.
### Step 4: Create Configuration Files
Create `~/.codex/config.toml` file and add the following configuration:
```toml config.toml theme={null}
model = "gpt-5"
model_provider = "memorylake"
preferred_auth_method = "apikey"
[model_providers.memorylake]
name = "MemoryLake"
base_url = "https://app.memorylake.ai/v1"
wire_api = "responses"
```
Create `~/.codex/auth.json` file and add the following configuration:
```json auth.json theme={null}
{
"OPENAI_API_KEY": "Replace here with your KEY"
}
```
The configuration file path `~/.codex` can also be specified using the `CODEX_HOME` environment variable.
### Step 5: Start Using
Run in the project directory:
```bash theme={null}
cd your-project-folder
codex
```
## Configuration File Details
### Codex CLI config.toml
* **model**: Specify the model name to use (must be available to your API key)
* **model\_provider**: Model provider identifier (use `memorylake` to represent Model Router)
* **preferred\_auth\_method**: Authentication method (use `apikey`)
* **base\_url**: Model Router API address, must include `/v1` path
### Codex CLI auth.json
* **OPENAI\_API\_KEY**: API Key obtained from the [Memorylake Console](https://app.memorylake.ai/panel/token)
### Custom Configuration Path
To use a custom configuration path, set the `CODEX_HOME` environment variable:
```bash theme={null}
export CODEX_HOME=/path/to/your/config
```
## Cherry Studio Integration
### What You Need
* **Provider Type**: Select a type supported by Model Router
* **API Key**: Your API key from [Memorylake Console](https://app.memorylake.ai/panel/token) (starts with `sk-`)
* **API Address**: Model Router service address
### Step 1: Get Your API Key
Copy your API Key from the [API key management page](https://app.memorylake.ai/panel/token) in the Memorylake Console.
### Step 2: Add Provider in Cherry Studio
1. Open Cherry Studio
2. Add a new Provider
3. Select the corresponding Provider Type
4. Enter your API Key and API Address
In the chat settings under system settings in the [Memorylake Console](https://app.memorylake.ai/panel), you can add a quick option to one-click fill Cherry Studio configuration on the [API key management page](https://app.memorylake.ai/panel/token).
### Step 3: Add Models
After configuration, add available models to Cherry Studio. Make sure to check [List Available Models](/features/model-router/list-available-models) to see which models you can use.
### Step 4: Start Using
Return to the chat page and select the configured Model Router model to start a conversation. You can switch between different Model Router models at any time.
## Common Issues
### Cherry Studio
* **Provider Not Working**: Check that the API address and API Key are correct
* **Models Not Available**: Confirm that the models are enabled in your Model Router API key group. Check [List Available Models](/features/model-router/list-available-models)
* **Connection Failed**: Verify your network connection and API endpoint URL
### Claude Code
* **Installation Failed**: Ensure Node.js and npm are installed; using `npm install -g` requires administrator privileges.
* **Connection Failed**: Check if the API address and API Key are correct, and ensure network connection is normal.
* **Environment Variables Not Effective**: Confirm they are correctly written to the configuration file and restart the terminal or execute `source ~/.bashrc` (or `source ~/.zshrc`).
### Codex CLI
* **Installation Failed**: Ensure Node.js and npm are installed; using `npm i -g` requires administrator privileges.
* **Configuration File Not Found**: Manually create `~/.codex` directory and configuration files.
* **Connection Failed**: Check if `base_url` and `OPENAI_API_KEY` are correct, and ensure network connection is normal.
* **Model Unavailable**: Confirm that the model is enabled and configured in your Model Router API key group. Check [List Available Models](/features/model-router/list-available-models).
## Important Notes
1. **Model Availability**: Model availability depends on your Model Router API key group configuration. Always check [List Available Models](/features/model-router/list-available-models) first.
2. **API Key Security**: Never share your API key publicly or commit it to version control. Use environment variables or secure configuration files.
3. **Quota Management**: Monitor your usage in the [console](https://app.memorylake.ai/panel). See [View Usage and Billing](/features/model-router/view-usage-and-billing) for details.
## Related Documentation
* [Create API Key](/features/model-router/getting-started/create-api-key)
* [List Available Models](/features/model-router/list-available-models)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Error Handling](/features/model-router/others/error-handling)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
# Direct API Requests
Source: https://docs.memorylake.ai/features/model-router/getting-started/use-api-key/direct-api-requests
Learn how to make direct HTTP requests to Model Router using cURL or any HTTP client
## What are Direct API Requests?
Direct API requests mean making HTTP calls directly to Model Router's endpoints using tools like cURL, Postman, or any HTTP client library. This is the most straightforward way to interact with the API.
## Before You Start
Before making requests, check which models are available to your API key by calling the [model list endpoint](/features/model-router/list-available-models).
## API Base URL
All requests should be sent to:
```
https://app.memorylake.ai
```
## Authentication
Include your API key in the `Authorization` header:
```
Authorization: Bearer sk-your-api-key-here
```
## Request Examples
### OpenAI-Compatible Endpoint
The `/v1` endpoint works with OpenAI-style requests. This is the most common way to use Model Router.
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello, how are you?" }],
stream: false
})
});
```
```py Python theme={null}
import requests
resp = requests.post(
"https://app.memorylake.ai/v1/chat/completions",
headers={
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json",
},
json={
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello, how are you?"}],
"stream": False,
},
)
```
```bash cURL theme={null}
curl https://app.memorylake.ai/v1/chat/completions \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello, how are you?"}],
"stream": false
}'
```
Replace `sk-demo123` with your actual API key. Replace `gpt-4o-mini` with a model that's available to your API key. Check the [model list](/features/model-router/list-available-models) to see available models.
### Streaming Responses
To get streaming responses, set `stream` to `true`:
```bash theme={null}
curl https://app.memorylake.ai/v1/chat/completions \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Tell me a story"}],
"stream": true
}'
```
### Claude Native Endpoint
If you're using Claude models, you can use the native Claude endpoint:
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/claude/v1/messages", {
method: "POST",
headers: {
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "claude-sonnet-5",
max_tokens: 200,
messages: [{ role: "user", content: "Summarize this in one sentence" }]
})
});
```
```py Python theme={null}
import requests
resp = requests.post(
"https://app.memorylake.ai/claude/v1/messages",
headers={
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json",
},
json={
"model": "claude-sonnet-5",
"max_tokens": 200,
"messages": [{"role": "user", "content": "Summarize this in one sentence"}],
},
)
```
```bash cURL theme={null}
curl https://app.memorylake.ai/claude/v1/messages \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 200,
"messages": [{"role": "user", "content": "Summarize this in one sentence"}]
}'
```
### Gemini Native Endpoint
For Gemini models, use the native Gemini endpoint:
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/gemini/v1beta/models/gemini-2.5-pro:generateContent", {
method: "POST",
headers: {
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json"
},
body: JSON.stringify({
contents: [{ role: "user", parts: [{ text: "Generate a title" }] }]
})
});
```
```py Python theme={null}
import requests
resp = requests.post(
"https://app.memorylake.ai/gemini/v1beta/models/gemini-2.5-pro:generateContent",
headers={
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json",
},
json={
"contents": [{"role": "user", "parts": [{"text": "Generate a title"}]}],
},
)
```
```bash cURL theme={null}
curl https://app.memorylake.ai/gemini/v1beta/models/gemini-2.5-pro:generateContent \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"role": "user", "parts": [{"text": "Generate a title"}]}]
}'
```
## Important Notes
1. **Check Available Models**: Always check which models are available to your API key before making requests. See [List Available Models](/features/model-router/list-available-models).
2. **Model Names**: Use the exact model ID from the model list. Different API keys may have access to different models.
3. **Error Handling**: If you get an error, check:
* Is your API key correct?
* Is the model available to your API key?
* Do you have sufficient quota?
* See [Error Handling](/features/model-router/others/error-handling) for more help.
4. **View Usage**: After making requests, you can [view your usage and billing](/features/model-router/view-usage-and-billing) in the console.
## Related Documentation
* [List Available Models](/features/model-router/list-available-models)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Minimal MVP Examples](/features/model-router/getting-started/use-api-key/minimal-mvp-examples)
* [Error Handling](/features/model-router/others/error-handling)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
# Minimal MVP Examples
Source: https://docs.memorylake.ai/features/model-router/getting-started/use-api-key/minimal-mvp-examples
Ready-to-run code examples in Python, Node.js, and TypeScript to get started quickly
## What are MVP Examples?
These are minimal, complete, and runnable code examples that you can copy and use immediately. Each example is self-contained and shows the essential code needed to make API calls to Model Router.
Before running these examples, make sure you have:
1. Created an API key (see [Create API Key](/features/model-router/getting-started/create-api-key))
2. Checked which models are available (see [List Available Models](/features/model-router/list-available-models))
3. Replaced `sk-demo123` with your actual API key
4. Replaced the model name with one available to your API key
## Python Examples
### Using OpenAI Official SDK (Recommended)
**Recommended**: The OpenAI official SDK is the easiest way to use Model Router. You only need to change the `base_url` parameter - everything else works exactly the same as with OpenAI's API.
#### Installation
```bash theme={null}
pip install openai
```
#### Complete Example
```python theme={null}
from openai import OpenAI
# Initialize client with Model Router base URL
client = OpenAI(
base_url="https://app.memorylake.ai/v1", # Only change needed!
api_key="sk-your-api-key-here" # Your Model Router API key
)
# Replace with a model available to your API key
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Hello! How are you?"}
]
)
print(response.choices[0].message.content)
```
#### Running the Example
1. Save the code to a file (e.g., `chat.py`)
2. Install dependencies: `pip install openai`
3. Replace `api_key` and `model` with your values
4. Run: `python chat.py`
**Key Point**: The only difference from using OpenAI's API directly is setting `base_url="https://app.memorylake.ai/v1"`. All other code remains exactly the same!
#### Using Environment Variables
You can also use environment variables for better security:
```bash theme={null}
export OPENAI_API_KEY="sk-your-api-key-here"
```
```python theme={null}
from openai import OpenAI
# Client automatically reads OPENAI_API_KEY from environment
client = OpenAI(
base_url="https://app.memorylake.ai/v1" # Only change needed!
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Hello! How are you?"}
]
)
print(response.choices[0].message.content)
```
### Using requests Library (Alternative)
If you prefer using the `requests` library directly:
#### Installation
```bash theme={null}
pip install requests
```
#### Complete Example
```python theme={null}
import requests
# Replace with your API key
API_KEY = "sk-your-api-key-here"
BASE_URL = "https://app.memorylake.ai/v1"
# Replace with a model available to your API key
MODEL = "gpt-4o-mini"
def chat_completion(messages):
"""Send a chat completion request"""
url = f"{BASE_URL}/chat/completions"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
data = {
"model": MODEL,
"messages": messages,
"stream": False
}
response = requests.post(url, headers=headers, json=data)
response.raise_for_status()
return response.json()
# Example usage
if __name__ == "__main__":
messages = [
{"role": "user", "content": "Hello! How are you?"}
]
result = chat_completion(messages)
print(result["choices"][0]["message"]["content"])
```
#### Running the Example
1. Save the code to a file (e.g., `chat.py`)
2. Install dependencies: `pip install requests`
3. Replace `API_KEY` and `MODEL` with your values
4. Run: `python chat.py`
## TypeScript/JavaScript Examples
### Using OpenAI Official SDK (Recommended)
**Recommended**: The OpenAI official SDK works seamlessly with Model Router. You only need to change the `baseURL` parameter - everything else works exactly the same as with OpenAI's API.
#### Installation
```bash theme={null}
npm install openai
```
For TypeScript projects, you may also want to install type definitions:
```bash theme={null}
npm install --save-dev typescript @types/node
```
#### Complete Example (TypeScript)
```typescript theme={null}
import OpenAI from "openai";
// Initialize client with Model Router base URL
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/v1", // Only change needed!
apiKey: "sk-your-api-key-here" // Your Model Router API key
});
// Replace with a model available to your API key
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "user", content: "Hello! How are you?" }
]
});
console.log(response.choices[0].message.content);
```
#### Complete Example (JavaScript)
```javascript theme={null}
import OpenAI from "openai";
// Initialize client with Model Router base URL
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/v1", // Only change needed!
apiKey: "sk-your-api-key-here" // Your Model Router API key
});
// Replace with a model available to your API key
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "user", content: "Hello! How are you?" }
]
});
console.log(response.choices[0].message.content);
```
#### Running the Example
1. Save the code to a file (e.g., `chat.ts` or `chat.mjs`)
2. Install dependencies: `npm install openai`
3. Replace `apiKey` and `model` with your values
4. Run:
* TypeScript: `npx ts-node chat.ts` (or compile first with `tsc`)
* JavaScript: `node chat.mjs` (or `node chat.js` if using CommonJS)
**Key Point**: The only difference from using OpenAI's API directly is setting `baseURL: "https://app.memorylake.ai/v1"`. All other code remains exactly the same!
#### Using Environment Variables
You can also use environment variables for better security:
```bash theme={null}
export OPENAI_API_KEY="sk-your-api-key-here"
```
```typescript theme={null}
import OpenAI from "openai";
// Client automatically reads OPENAI_API_KEY from environment
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/v1" // Only change needed!
});
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "user", content: "Hello! How are you?" }
]
});
console.log(response.choices[0].message.content);
```
## Streaming Examples
### Python - Using OpenAI Official SDK
For streaming responses with the OpenAI SDK:
```python theme={null}
from openai import OpenAI
client = OpenAI(
base_url="https://app.memorylake.ai/v1",
api_key="sk-your-api-key-here"
)
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Tell me a short story"}
],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content is not None:
print(chunk.choices[0].delta.content, end='', flush=True)
print() # New line at the end
```
### Python - Using requests Library
For streaming responses with the requests library:
```python theme={null}
import requests
import json
API_KEY = "sk-your-api-key-here"
BASE_URL = "https://app.memorylake.ai/v1"
MODEL = "gpt-4o-mini"
def chat_completion_stream(messages):
"""Send a streaming chat completion request"""
url = f"{BASE_URL}/chat/completions"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
data = {
"model": MODEL,
"messages": messages,
"stream": True
}
response = requests.post(url, headers=headers, json=data, stream=True)
response.raise_for_status()
for line in response.iter_lines():
if line:
line_text = line.decode('utf-8')
if line_text.startswith('data: '):
json_str = line_text[6:] # Remove 'data: ' prefix
if json_str == '[DONE]':
break
try:
data = json.loads(json_str)
if 'choices' in data and len(data['choices']) > 0:
delta = data['choices'][0].get('delta', {})
if 'content' in delta:
print(delta['content'], end='', flush=True)
except json.JSONDecodeError:
pass
# Example usage
if __name__ == "__main__":
messages = [
{"role": "user", "content": "Tell me a short story"}
]
chat_completion_stream(messages)
print() # New line at the end
```
### TypeScript/JavaScript - Using OpenAI Official SDK
For streaming responses with the OpenAI SDK:
```typescript theme={null}
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://app.memorylake.ai/v1",
apiKey: "sk-your-api-key-here"
});
const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "user", content: "Tell me a short story" }
],
stream: true
});
for await (const chunk of stream) {
if (chunk.choices[0]?.delta?.content) {
process.stdout.write(chunk.choices[0].delta.content);
}
}
console.log(); // New line at the end
```
## Other Official SDKs
Model Router is compatible with many official SDKs from different AI platforms. Most of them only require configuring the `API_KEY` and `BASE_URL` to work with Model Router.
**Key Point**: For most official SDKs, you only need to:
1. Set the `baseURL` or `base_url` to `https://app.memorylake.ai/v1` (or the corresponding endpoint)
2. Use your Model Router API key as the `apiKey` or `api_key`
3. Everything else works exactly the same as with the original platform's API
### Anthropic Claude SDK
The official [Anthropic Claude SDK](https://platform.claude.com/docs/en/api/client-sdks) supports Python, TypeScript/JavaScript, Java, Go, C#, Ruby, and PHP.
**Example (Python):**
```python theme={null}
from anthropic import Anthropic
client = Anthropic(
api_key="sk-your-api-key-here",
base_url="https://app.memorylake.ai/claude" # Claude native endpoint
)
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=200,
messages=[
{"role": "user", "content": "Hello!"}
]
)
```
**Example (TypeScript):**
```typescript theme={null}
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({
apiKey: 'sk-your-api-key-here',
baseURL: 'https://app.memorylake.ai/claude' // Claude native endpoint
});
const message = await client.messages.create({
model: 'claude-sonnet-5',
max_tokens: 200,
messages: [
{ role: 'user', content: 'Hello!' }
]
});
```
**Documentation**: [Anthropic Client SDKs](https://platform.claude.com/docs/en/api/client-sdks)
### Vercel AI SDK
The [Vercel AI SDK](https://ai-sdk.dev/providers/ai-sdk-providers) provides a unified interface for multiple AI providers, including OpenAI, Anthropic, Google, and more.
**Example:**
```typescript theme={null}
import { openai } from '@ai-sdk/openai';
const client = openai({
baseURL: 'https://app.memorylake.ai/v1',
apiKey: 'sk-your-api-key-here'
});
```
**Documentation**: [Vercel AI SDK Providers](https://ai-sdk.dev/providers/ai-sdk-providers)
### Google Gemini SDK
The official [Google Gemini SDK](https://ai.google.dev/gemini-api/docs/migrate) supports Python, Node.js, and other languages.
**Example (Python):**
```python theme={null}
import google.generativeai as genai
genai.configure(
api_key="sk-your-api-key-here",
transport="rest",
client_options={
"api_endpoint": "https://app.memorylake.ai/gemini"
}
)
model = genai.GenerativeModel('gemini-2.5-pro')
response = model.generate_content("Hello!")
```
**Documentation**: [Google Gemini API Migration Guide](https://ai.google.dev/gemini-api/docs/migrate)
### General Pattern
Most official SDKs follow a similar pattern:
1. **Install the SDK**: Use the official package manager (pip, npm, etc.)
2. **Configure the client**: Set `baseURL`/`base_url` to Model Router's endpoint
3. **Set API key**: Use your Model Router API key
4. **Use normally**: All other code remains the same
**Common Endpoints:**
* OpenAI-compatible: `https://app.memorylake.ai/v1`
* Claude native: `https://app.memorylake.ai/claude`
* Gemini native: `https://app.memorylake.ai/gemini`
Before using any SDK, make sure to check which models are available to your API key by calling the [model list endpoint](/features/model-router/list-available-models).
## Next Steps
1. **Test Your Code**: Run one of the examples above with your API key
2. **Check Your Usage**: See [View Usage and Billing](/features/model-router/view-usage-and-billing) to monitor your API calls
3. **Handle Errors**: Learn about [Error Handling](/features/model-router/others/error-handling) if you encounter issues
4. **Explore More**: Check out [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests) for more advanced usage
## Related Documentation
* [Create API Key](/features/model-router/getting-started/create-api-key)
* [List Available Models](/features/model-router/list-available-models)
* [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Error Handling](/features/model-router/others/error-handling)
# Use API Key Overview
Source: https://docs.memorylake.ai/features/model-router/getting-started/use-api-key/overview
Learn different ways to use your API key to interact with Model Router
## What is This Guide?
This guide shows you three main ways to use your API Key with Model Router:
1. **Direct API Requests**: Make HTTP requests directly using cURL or any HTTP client
2. **Minimal MVP Examples**: Simple, ready-to-run code examples in popular programming languages
3. **AI Application Integrations**: Connect Model Router to existing AI tools like Claude Code or Codex CLI
## Before You Start
Before making any API calls, make sure you know which models are available to your API key. Check the [List Available Models](/features/model-router/list-available-models) guide first.
## Three Ways to Use Your API Key
### 1. Direct API Requests
If you want to make requests directly using HTTP tools like cURL, Postman, or any HTTP client, this is the simplest approach.
**Best for**: Quick testing, automation scripts, or when you need full control over the request
**Learn more**: [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
### 2. Minimal MVP Examples
Ready-to-run code examples in Python, Node.js, and TypeScript that you can copy and use immediately.
**Best for**: Building your own application, learning how to integrate Model Router, or prototyping
**Learn more**: [Minimal MVP Examples](/features/model-router/getting-started/use-api-key/minimal-mvp-examples)
### 3. AI Application Integrations
Connect Model Router to existing AI development tools without writing code.
**Best for**: Using AI tools like Claude Code or Codex CLI with Model Router
**Learn more**: [AI Application Integrations](/features/model-router/getting-started/use-api-key/ai-app-integrations)
## Quick Start Checklist
1. ✅ [Create an API Key](/features/model-router/getting-started/create-api-key)
2. ✅ [Check Available Models](/features/model-router/list-available-models)
3. ✅ Choose one of the three methods above
4. ✅ Make your first API call
5. ✅ [View Your Usage](/features/model-router/view-usage-and-billing)
## Related Documentation
* [Create API Key](/features/model-router/getting-started/create-api-key)
* [List Available Models](/features/model-router/list-available-models)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
* [Minimal MVP Examples](/features/model-router/getting-started/use-api-key/minimal-mvp-examples)
* [AI Application Integrations](/features/model-router/getting-started/use-api-key/ai-app-integrations)
# List Available Models
Source: https://docs.memorylake.ai/features/model-router/list-available-models
Learn how to check which models are available to your API key
## What is the Model List?
The model list shows all the AI models you can use with your API key. Each API key has access to different models depending on its group configuration. Before making API calls, you should always check which models are available.
Only models that are enabled for your API key group will appear in the list. If you don't see a model you expect, check with your administrator or see [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites).
## How to Get the Model List
You can get the list of available models by making a simple GET request. The endpoint you use depends on which protocol you want to use.
### OpenAI-Compatible Models
Use this endpoint if you're using OpenAI-style requests:
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/v1/models", {
headers: { "Authorization": "Bearer sk-demo123" }
});
```
```py Python theme={null}
import requests
resp = requests.get(
"https://app.memorylake.ai/v1/models",
headers={"Authorization": "Bearer sk-demo123"}
)
print(resp.json())
```
```bash cURL theme={null}
curl https://app.memorylake.ai/v1/models \
-H "Authorization: Bearer sk-demo123"
```
### Claude Models
Use this endpoint for Claude models:
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/claude/v1/models", {
headers: { "Authorization": "Bearer sk-demo123" }
});
```
```py Python theme={null}
import requests
resp = requests.get(
"https://app.memorylake.ai/claude/v1/models",
headers={"Authorization": "Bearer sk-demo123"}
)
print(resp.json())
```
```bash cURL theme={null}
curl https://app.memorylake.ai/claude/v1/models \
-H "Authorization: Bearer sk-demo123"
```
### Gemini Models
Use this endpoint for Gemini models:
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/gemini/v1beta/models", {
headers: { "Authorization": "Bearer sk-demo123" }
});
```
```py Python theme={null}
import requests
resp = requests.get(
"https://app.memorylake.ai/gemini/v1beta/models",
headers={"Authorization": "Bearer sk-demo123"}
)
print(resp.json())
```
```bash cURL theme={null}
curl https://app.memorylake.ai/gemini/v1beta/models \
-H "Authorization: Bearer sk-demo123"
```
## Understanding the Response
The response will contain a list of models. Each model has important information:
* **`id`**: The model identifier - use this exact value in your API requests
* **`owned_by`**: The source or provider of the model
* **Pricing information**: Cost per token or request (for display purposes)
* **Other metadata**: Additional information about the model
The pricing information in the model list is for reference only. Actual billing is calculated based on your usage. See [View Usage and Billing](/features/model-router/view-usage-and-billing) for details.
## Example Response
```json theme={null}
{
"data": [
{
"id": "gpt-4o-mini",
"owned_by": "openai",
"pricing": {
"input": 0.00015,
"output": 0.0006
}
},
{
"id": "claude-sonnet-5",
"owned_by": "anthropic",
"pricing": {
"input": 0.015,
"output": 0.075
}
}
]
}
```
## When to Check the Model List
1. **Before making your first API call**: Make sure the model you want to use is available
2. **When you get an error**: If a model isn't found, check if it's in your available list
3. **When building a UI**: Use the model list to populate dropdown menus or model selectors
4. **After configuration changes**: If your administrator changes your group settings, check the list again
## Important Notes
1. **Model Availability**: Only models enabled for your API key group will appear. Different API keys may see different models.
2. **Model Names**: Always use the exact `id` from the model list in your API requests. Model names are case-sensitive.
3. **Real-time Updates**: The list reflects the current state. If models are enabled or disabled, you may need to refresh the list.
4. **Pricing**: Pricing shown in the model list is for reference. Actual billing is calculated based on your actual usage.
## Next Steps
After checking which models are available:
1. Make your first API call using one of the available models
2. Monitor your usage in the [console](https://app.memorylake.ai/panel)
3. See [View Usage and Billing](/features/model-router/view-usage-and-billing) to understand how you're being charged
## Related Documentation
* [Create API Key](/features/model-router/getting-started/create-api-key)
* [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
# Error Handling
Source: https://docs.memorylake.ai/features/model-router/others/error-handling
Learn about common errors and how to troubleshoot them
## What is Error Handling?
This guide helps you understand common errors you might encounter when using Model Router and how to resolve them.
## Common Errors and Solutions
### Authentication Errors
#### Error: "Invalid API Key" or 401 Unauthorized
**What it means**: Your API key is incorrect, missing, or invalid.
**How to fix**:
1. Check that your API key starts with `sk-`
2. Verify you copied the entire API key correctly
3. Make sure you're including it in the `Authorization` header: `Bearer sk-your-key`
4. If you lost your key, create a new one in the [console](https://app.memorylake.ai/panel/token)
#### Error: "API key not found"
**What it means**: The API key doesn't exist or has been deleted.
**How to fix**:
1. Verify the API key exists in the [console](https://app.memorylake.ai/panel/token)
2. Create a new API key if needed
3. Make sure you're using the correct API key
### Model Errors
#### Error: "Model not found" or "Model does not exist"
**What it means**: The model you're trying to use isn't available to your API key.
**How to fix**:
1. Check [List Available Models](/features/model-router/list-available-models) to see which models you can use
2. Verify the model name is spelled correctly (model names are case-sensitive)
3. Use the exact model `id` from the model list
4. Contact your administrator if you need access to a specific model
#### Error: "Model is not available"
**What it means**: The model exists but isn't enabled for your API key group.
**How to fix**:
1. Check which models are available to your API key
2. Contact your administrator to enable the model for your group
3. See [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites) for more information
### Quota Errors
#### Error: "Insufficient quota" or "Quota exceeded"
**What it means**: You don't have enough quota to make the request.
**How to fix**:
1. Check your balance in the console under **Billing → Overview**
2. [View your usage](/features/model-router/view-usage-and-billing) to see how much you've consumed
3. Top up credits, or ask your team admin to raise your member quota
4. Confirm you're in the intended space — personal and team contexts draw on different quota pools
Quota is checked before each request. If you don't have enough quota, the request will be rejected immediately. See [View Usage and Billing](/features/model-router/view-usage-and-billing) for details.
### Rate Limiting Errors
#### Error: 429 "Too Many Requests" or "Rate limit exceeded"
**What it means**: You're making requests too quickly.
**How to fix**:
1. Wait a moment and try again
2. Reduce the frequency of your requests
3. Implement exponential backoff in your code
4. Batch requests if possible
5. See [Reliability and Failover](/features/model-router/others/reliability-and-failover) for retry strategies
### Request Format Errors
#### Error: "Invalid request format" or 400 Bad Request
**What it means**: The request body or parameters are incorrect.
**How to fix**:
1. Check that your request body is valid JSON
2. Verify all required fields are present
3. Make sure field names and types match the API specification
4. Review the [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests) guide for correct format
#### Error: "Missing required field"
**What it means**: A required parameter is missing from your request.
**How to fix**:
1. Check the API documentation for required fields
2. Verify all required parameters are included
3. Check that field names are spelled correctly
### Network Errors
#### Error: "Connection timeout" or "Network error"
**What it means**: The request couldn't reach the server or took too long.
**How to fix**:
1. Check your internet connection
2. Verify the API endpoint URL is correct: `https://app.memorylake.ai`
3. Try again after a moment
4. Check if there are any network issues
5. See [Reliability and Failover](/features/model-router/others/reliability-and-failover) for automatic retry mechanisms
### Streaming Errors
#### Error: "Stream connection closed unexpectedly"
**What it means**: The streaming connection was interrupted.
**How to fix**:
1. This is normal for long streams - implement reconnection logic
2. Check your network stability
3. Handle stream interruptions gracefully in your code
4. See [Reliability and Failover](/features/model-router/others/reliability-and-failover) for streaming best practices
## Error Response Format
When an error occurs, the API returns a JSON response with error details:
```json theme={null}
{
"error": {
"message": "Model not found",
"type": "invalid_request_error",
"code": "model_not_found"
}
}
```
## Best Practices for Error Handling
1. **Always check the response status**: Handle both success and error cases
2. **Read error messages**: The error message usually tells you what went wrong
3. **Implement retry logic**: For transient errors like rate limits or network issues
4. **Log errors**: Keep track of errors for debugging
5. **Handle gracefully**: Don't crash your application on API errors
## Example: Error Handling in Code
### Python Example
```python theme={null}
import requests
def make_request(api_key, model, messages):
try:
response = requests.post(
"https://app.memorylake.ai/v1/chat/completions",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
},
json={
"model": model,
"messages": messages
}
)
response.raise_for_status()
return response.json()
except requests.exceptions.HTTPError as e:
if response.status_code == 401:
print("Error: Invalid API key")
elif response.status_code == 404:
print("Error: Model not found")
elif response.status_code == 429:
print("Error: Rate limit exceeded. Please wait and try again.")
else:
print(f"Error: {response.status_code} - {response.text}")
raise
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
raise
```
## Getting Help
If you're still having issues:
1. Check the [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites) guide
2. Review the [Reliability and Failover](/features/model-router/others/reliability-and-failover) documentation
3. Check your API key and model availability
4. Contact [support@memorylake.ai](mailto:support@memorylake.ai) with:
* The exact error message
* Your API key (masked)
* The request you were making
* Any relevant logs
## Related Documentation
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
* [Reliability and Failover](/features/model-router/others/reliability-and-failover)
* [List Available Models](/features/model-router/list-available-models)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
# Limits and Prerequisites
Source: https://docs.memorylake.ai/features/model-router/others/limits-and-prerequisites
Clarify model availability, quotas, rate limits, and call prerequisites before integration
## What You Need in Advance
* An account, logged in to the [console](https://app.memorylake.ai)
* At least one API key created under **API Keys**, in the space (personal or team) you intend to call from
* Sufficient balance — calls are rejected when quota is insufficient (see [Billing](/features/model-router/view-usage-and-billing))
## Model Availability
* **Determined by your access group**: each API key can call the models enabled for its model-access group. Two keys on the same account may see different model lists.
* **The model directory is authoritative**: `GET /v1/models`, `/claude/v1/models`, and `/gemini/:version/models` return exactly what the current key can call. Anything absent is unavailable.
* **Per-key restrictions**: a key can be further limited to specific models from its detail panel — a model in your group may still be blocked for that key.
* **Task services**: capabilities like Midjourney, Suno, RecraftAI, and Kling depend on those channels being enabled for your deployment.
## Quota and Billing
* **Insufficient quota rejects immediately**: quota is validated and pre-deducted before the request reaches a model. If any level (personal, team, or owner balance) is short, the call is rejected.
* **Two-phase settlement**: pre-deduction on request, settlement on completion based on actual usage; failures roll back the reservation.
* **Independent quota pools**: personal and team contexts are separate. Confirm your current space before automating.
## Rate Limits
Rate limiting applies on two dimensions: **per IP address** (separate buckets for general API traffic, uploads, and downloads, with thresholds set per deployment) and **per account** (determined by your access group — 600 requests per minute on the default group). Exceeding either returns `429` with a `Retry-After` header.
Design for it regardless:
* Implement exponential backoff on `429`
* Spread bulk workloads rather than firing them in parallel spikes
* Prefer batching where the API supports it
Model relay traffic is metered by quota rather than the general API rate limiter — the limits that matter most for high-volume inference are your balance and the upstream provider's own limits.
## Protocol and Entry Point Notes
* **OpenAI-compatible** `/v1/*`: accepts OpenAI-style request bodies. Broad surface — chat completions, responses, embeddings, images, audio, moderations, files, batches, and more.
* **Native paths**: `/claude/v1/messages` and `/gemini/:version/models/:model` preserve each provider's own protocol, fields, and model IDs. Use these with the official Claude/Gemini SDKs.
* **Task interfaces**: Midjourney, Suno, RecraftAI, and Kling follow an asynchronous "submit → poll task id" pattern; a single request does not return the final asset.
* **Parameter passthrough**: provider-specific parameters (reasoning effort, Claude thinking, Gemini search and code execution) pass through unchanged — keep them in the official format.
Newer OpenAI reasoning models (`gpt-5` family, `o1`/`o3`/`o4`) expect `max_completion_tokens` rather than `max_tokens` on Chat Completions.
## Stability Notes
* **Channel health**: automatic retry and channel switching require at least one healthy alternative; when all channels for a model are unavailable, requests fail.
* **Long streaming calls**: streams close on network errors or timeouts — implement client-side timeout and reconnection handling.
## Permissions and Context
* **Space context**: calls execute in a personal or team context, each with its own quota pool and model visibility.
* **Roles**: managing team quotas, viewing team-wide usage, and adjusting member allocations depend on your team role — see [Roles and Permissions](/features/team-collaboration/roles-permissions).
* **Log visibility**: members see their own call records; team-wide logs and statistics require the corresponding permission.
## Pre-Use Checklist
1. Confirm the current space (personal vs. team) and that your balance is sufficient
2. List models via the directory endpoint and confirm your target model appears
3. For task services, confirm the channel is enabled in your deployment
4. Estimate volume and reserve quota before production traffic
## Related Documentation
* [Create API Key](/features/model-router/getting-started/create-api-key)
* [List Available Models](/features/model-router/list-available-models)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Error Handling](/features/model-router/others/error-handling)
* [Reliability and Failover](/features/model-router/others/reliability-and-failover)
* [Multimodal and Task Interfaces](/features/model-router/others/multimodal-and-tasks)
# Multimodal and Task Interfaces
Source: https://docs.memorylake.ai/features/model-router/others/multimodal-and-tasks
Advanced guide for multimodal tasks like image generation, music creation, and video generation
## What are Multimodal and Task Interfaces?
Multimodal and task interfaces allow you to generate images, create music, produce videos, and perform other complex tasks through Model Router. These tasks work differently from regular chat completions - they're asynchronous, meaning you submit a task and then check back later for results.
This is an advanced feature. Make sure you understand basic API usage first. See [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests) for the basics.
## How Task Interfaces Work
Task interfaces follow a three-step pattern:
1. **Submit task**: Send a request to create a task (e.g., generate an image)
2. **Poll query**: Check the task status using the task ID
3. **Get results**: Retrieve the final output (image, audio, video, etc.)
Tasks are asynchronous - they don't return results immediately. You need to poll for status and retrieve results when the task is complete.
## Supported Task Types
### Midjourney: Image Generation
Generate high-quality images from text prompts.
**Capabilities**:
* Imagine: Generate images from text
* Describe: Describe existing images
* Blend: Combine multiple images
* Change: Modify existing images
* Shorten: Optimize prompts
* Notify: Get notifications when tasks complete
**Example: Submit Imagine Task**
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/midjourney/imagine", {
method: "POST",
headers: {
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json"
},
body: JSON.stringify({
prompt: "a cyberpunk city at night, neon lights, 4k",
notify: true
})
});
```
```py Python theme={null}
import requests
resp = requests.post(
"https://app.memorylake.ai/midjourney/imagine",
headers={
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json",
},
json={
"prompt": "a cyberpunk city at night, neon lights, 4k",
"notify": True,
},
)
```
```bash cURL theme={null}
curl https://app.memorylake.ai/midjourney/imagine \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"prompt": "a cyberpunk city at night, neon lights, 4k",
"notify": true
}'
```
**Query Task Status**
After submitting, you'll get a task ID. Use it to check status:
```bash theme={null}
curl https://app.memorylake.ai/tasks/tsk_12345 \
-H "Authorization: Bearer sk-demo123"
```
### Suno: Music and Voice Generation
Generate music or voice-overs from text prompts.
**Example: Submit Music Task**
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/suno/jobs", {
method: "POST",
headers: {
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json"
},
body: JSON.stringify({
prompt: "soft lo-fi background music for coding",
mode: "music"
})
});
```
```py Python theme={null}
import requests
resp = requests.post(
"https://app.memorylake.ai/suno/jobs",
headers={
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json",
},
json={
"prompt": "soft lo-fi background music for coding",
"mode": "music",
},
)
```
```bash cURL theme={null}
curl https://app.memorylake.ai/suno/jobs \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"prompt": "soft lo-fi background music for coding",
"mode": "music"
}'
```
After successful submission, query progress and audio results (playback links, download links, etc.) by task ID.
### RecraftAI: Image Processing
Process and enhance images with various tools.
**Capabilities**:
* Vectorization: Convert bitmaps to vector graphics
* Background Removal: Remove image backgrounds
* Clarity Enhancement: Enlarge images without quality loss
* Style Management: Apply styles to images
Use the same pattern: submit task → poll query → get processed image link.
### Kling: Video Generation
Generate videos from text or images.
**Capabilities**:
* Text-to-Video: Generate videos from text prompts
* Image-to-Video: Generate videos from images with text prompts
Submit a task and query by task ID. After completion, retrieve video links from results.
## Important Notes
1. **Channel Requirements**: Task interfaces require corresponding channels to be enabled. If you get errors, check with your administrator.
2. **Asynchronous Nature**: Tasks don't return results immediately. Always implement polling logic to check status.
3. **Quota Consumption**: All task interfaces consume quota just like regular API calls. See [View Usage and Billing](/features/model-router/view-usage-and-billing) for details.
4. **Large Data Volumes**: Multimodal tasks can have large data volumes. Make sure you have sufficient quota and consider rate limiting.
5. **Task Visibility**: Task submission and query must use the same API key to ensure task visibility.
## Best Practices
1. **Implement Polling**: Don't assume tasks complete immediately. Poll regularly until status is "completed" or "failed"
2. **Handle Errors**: Tasks can fail. Always check the status and handle error cases gracefully
3. **Monitor Quota**: Large tasks consume more quota. Monitor your usage regularly
4. **Rate Limiting**: Don't submit too many tasks at once. Stagger submissions to avoid rate limits
5. **Check Logs**: View task details and billing in the [console logs](https://app.memorylake.ai/panel/billing/usage)
## Related Documentation
* [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
* [View Usage and Billing](/features/model-router/view-usage-and-billing)
* [Error Handling](/features/model-router/others/error-handling)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
* [Reliability and Failover](/features/model-router/others/reliability-and-failover)
# Reliability and Failover
Source: https://docs.memorylake.ai/features/model-router/others/reliability-and-failover
Automatic retry, channel switching, and streaming fallback to reduce impact of exceptions and rate limiting
## Core Capabilities (Summary)
* When encountering 429 or upstream exceptions, the platform automatically retries and switches to enabled and healthy channels.
* Streaming calls provide heartbeat and exception fallback, automatically closing connections on exceptions to avoid hanging.
* Dynamic rate limiting guardrails peak-shave during high concurrency to protect main routes and task interfaces.
## How to Use
* Before use: In the model directory, confirm that the API key can see multiple channels (if not configured, contact an administrator).
* During calls: Normally use `/v1`, `/claude/v1/messages`, `/gemini/:version/models/:model`, or task interfaces; no additional parameters needed to enjoy automatic retry and switching.
* Before scaling: Validate with small traffic first; batch or long streaming scenarios can submit in batches to reduce instantaneous concurrency.
## Request Example (Streaming Chat)
```ts TypeScript theme={null}
await fetch("https://app.memorylake.ai/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Please give me an opening script for a product launch event" }],
stream: true
})
});
```
```py Python theme={null}
import requests
resp = requests.post(
"https://app.memorylake.ai/v1/chat/completions",
headers={
"Authorization": "Bearer sk-demo123",
"Content-Type": "application/json",
},
json={
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Please give me an opening script for a product launch event"}],
"stream": True,
},
)
```
```bash cURL theme={null}
curl https://app.memorylake.ai/v1/chat/completions \
-H "Authorization: Bearer sk-demo123" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Please give me an opening script for a product launch event"}],
"stream": true
}'
```
## Usage Reminders
* Automatic retry and channel switching depend on enabled and healthy backup channels; switching is unavailable if not enabled.
* When rate limiting guardrails take effect, speed may be reduced; recommend batching or staggering calls.
* On streaming exceptions, the platform will close connections; you can supplement retry logic on the client side as needed.
## Related Documentation
* [Direct API Requests](/features/model-router/getting-started/use-api-key/direct-api-requests)
* [Error Handling](/features/model-router/others/error-handling)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
* [List Available Models](/features/model-router/list-available-models)
# Overview
Source: https://docs.memorylake.ai/features/model-router/overview
Unified model routing and multimodal task entry point, compatible with mainstream protocols and channels
## Quick Introduction
Model Router provides a unified model routing and multimodal task entry point, compatible with mainstream protocols and channels.
* One entry point covers mainstream models and tasks, compatible with OpenAI-style calls without changing SDKs
* Preserves native paths for Claude, Gemini, and others to reduce migration and switching costs
* Built-in stability, quota settlement, notifications, and security policies to help you confidently integrate in production
**Base URL**: `https://app.memorylake.ai` — OpenAI-compatible at `/v1`, Claude-native at `/claude/v1`, Gemini-native at `/gemini/:version`. Authenticate with the same `sk-…` key you use elsewhere on the platform ([details](/authentication)).
Looking to add **memory** to your LLM calls rather than just route them? See [Memory Router](/features/memory-router/overview), which layers persistent memory on top of the same protocols.
## Quick Start
1. **[Create an API Key](/features/model-router/getting-started/create-api-key)**: Generate an API key in the console
2. **[Check Available Models](/features/model-router/list-available-models)**: See which models you can use
3. **[Use Your API Key](/features/model-router/getting-started/use-api-key/overview)**: Choose how to make API calls
4. **[Monitor Usage](/features/model-router/view-usage-and-billing)**: Track your API usage and billing
## Documentation
Learn how to create an API key and start using Model Router.
Learn different ways to use your API key: direct requests, code examples, or AI app integrations.
Check which models are available to your API key.
Monitor your API usage and understand billing details.
Learn about common errors and how to troubleshoot them.
Understand usage limits and requirements.
# View Usage and Billing
Source: https://docs.memorylake.ai/features/model-router/view-usage-and-billing
Learn how to check your API usage and understand billing details
## What is Usage and Billing?
Every API call consumes quota and generates a billing record. This guide shows where to see your usage and how charges are calculated.
Quota is checked before each request. If your balance is insufficient, the request is rejected. See [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites) for more details.
## How Quota Works
Model Router uses a two-phase quota system:
1. **Pre-deduction**: before your request is processed, the system checks and reserves quota
2. **Settlement**: after the request completes, you're charged based on actual usage; failed requests roll back the reservation
You're only charged for successful requests based on actual token usage.
## Where to Look in the Console
All usage and billing views live under **Billing** in the [console](https://app.memorylake.ai/panel/billing) sidebar:
| Tab | What you'll find |
| - | - |
| **Overview** | Current balance, credits, and recent consumption at a glance |
| **Credits** | Balance management and top-ups |
| **Usage** | Aggregated product usage — separate views for MemoryLake Memory and MemoryLake Router |
| **Logs** | Per-request records: model, tokens, latency, and cost details |
| **Payments** | Payment history and invoices |
In team spaces, team-wide statistics (member rankings, consumption trends, model usage) are on the team's **Stats** tab — see [Team Collaboration](/features/team-collaboration/quota-and-usage).
## Viewing Individual Call Billing
1. Open **Billing → Logs**
2. Click any call to see its details:
* **Input/Output pricing**: cost per token
* **Conversion process**: how the charge was calculated
* **Actual deducted quota**: what was consumed
* **Quota source**: personal, team, or mixed
## Understanding Billing Details
* **Input tokens**: cost for tokens you send to the model
* **Output tokens**: cost for tokens the model generates
* **Total cost**: input + output
* **Quota sources**: personal quota, shared team quota, or a mix — validated according to your current space context
## Model Pricing
View per-model pricing on the [Available Models page](https://app.memorylake.ai/panel/models/available) in the console. Pricing shown there is reference metadata; actual charges are calculated at settlement from real usage.
## Important Notes
1. **Quota limits**: requests are rejected when balance is insufficient — top up in **Billing → Credits** before sustained workloads.
2. **Context matters**: personal and team contexts draw on different quota pools; check your current space before automating.
3. **Real-time updates**: usage statistics update as you make calls.
## Troubleshooting
### "Insufficient Quota" Error
1. Check your balance in **Billing → Overview**
2. Top up credits, or ask your team admin for a larger member quota
3. Verify you're in the intended space (personal vs. team)
### Unexpected Charges
1. Open the call in **Billing → Logs**
2. Review input/output token counts and the conversion detail
3. Compare against the model's pricing on the Available Models page
## Related Documentation
* [List Available Models](/features/model-router/list-available-models)
* [Limits and Prerequisites](/features/model-router/others/limits-and-prerequisites)
* [Error Handling](/features/model-router/others/error-handling)
* [Team Collaboration — Quotas and Usage](/features/team-collaboration/quota-and-usage)
# Analytics and Lifecycle
Source: https://docs.memorylake.ai/features/team-collaboration/analytics-and-lifecycle
View team and member usage trends, safely transfer ownership, or exit
## Use Cases
* View team-wide usage, member rankings, and trends to quickly identify abnormal consumption.
* Smoothly transfer ownership during handover, or allow members to exit voluntarily.
* Combine logs and statistics to verify quota allocation and API call health.
## What You Can See
* **Team Statistics**: Aggregate usage, success rates, latency, and other metrics by time to identify abnormal periods or members.
* **Member Rankings**: Sort members by usage to identify high-consumption or abnormal members.
* **Personal View**: Members can view their own usage to confirm if they're approaching quota limits.
## Common Actions
* **View Team Overview**: Check overall usage and trends in "Usage/Statistics" with time range filters.
* **View Member Rankings**: Check member usage rankings in the same section to identify high-consumption members and review their quotas and roles.
* **Personal Check**: Members can view their own usage in the personal view to avoid hitting limits.
* **Log Review**: If anomalies are detected, use call logs to filter by model, token, latency, and other fields to identify the cause.
## Lifecycle and Handover
* **Transfer Ownership**: Transfer ownership to a specified member in team details. After completion, the original owner is automatically downgraded, and subsequent operations are handled by the new owner.
* **Member Exit**: Members can voluntarily exit the team. If their access is no longer needed, they can be removed directly.
* **Revoke Invitations**: Unaccepted invitations can be revoked at any time. If sent by mistake, send a new invitation.
## Tips
* When abnormal usage is detected, first tighten quotas or adjust roles, then investigate the source of calls.
* Statistics are based on actual call accumulation. Empty statistics initially are normal; trends will appear after sustained usage.
* Before transferring ownership, confirm that the recipient is already in the team and has an appropriate role to avoid handover failures.
* Confirm the context before making calls to ensure statistics and quotas are applied to the correct team or personal space.
## Next Steps
* If you need to combine quota allocation or invitation strategies, refer to the "Quotas and Usage", "Invitations and Access", and "Roles and Permissions" sections.
* Before migrating to production, use test tokens to verify that statistics and logs cover key call scenarios.
# Invitations and Access
Source: https://docs.memorylake.ai/features/team-collaboration/invitation-and-access
Invite colleagues via email or link, and control joining, roles, and revocation
## Use Cases
* Bring colleagues into a shared workspace so team memory and quotas are collective.
* Resend or revoke invitations in a controlled way to avoid mistakes or stale links.
* Assign the right role at invitation time rather than fixing permissions afterwards.
All new members join through **invitation and acceptance** — there is no direct add-member action. Both sides need a **verified email address**: if yours isn't verified yet, the console prompts you to add and verify it before sending invitations, and invitees must have a verified address to accept.
## How to Invite
* **Email invitation**: enter one or more email addresses on the team's **Invites** tab. You can paste a batch — one address per line — and specify a role per line. Invitations can be resent or revoked while pending.
* **Invitation link**: generate a shareable link. Anyone opening it can accept after signing in (or after completing registration). Revoke the link to invalidate it.
* **Invitee experience**: accepting after sign-in adds them to the team with the role you assigned. If they open an invite while logged out, they're returned to it automatically after signing in or registering.
## Joining and Access Control
* **Before acceptance**: pending invitations can be revoked at any time. Wrong address? Revoke and resend — email matching is case- and whitespace-insensitive, so duplicates are caught.
* **After acceptance**: adjust roles and quotas from the **Members** tab, grant per-resource scopes, or remove members. Members can also leave voluntarily.
* **Workspace access**: new members are added to the team's workspaces automatically, so shared memory is immediately available (deployment-configurable).
* **Context and permissions**: once in the team, calls made in the team context draw on team quota and follow the member's role permissions.
## Quick Start
1. Open team details → **Invites**, and send an email invitation (or generate a link).
2. Assign each invitee's role as you invite — Owner, Admin, Member, or a custom role.
3. Revoke or resend anything still pending as needed.
4. After they join, fine-tune quotas and per-resource scopes on the **Members** tab.
## Tips
* Revoked invitations and links are permanently invalid — generate a new one to continue.
* For sensitive teams, prefer email invitations (identity is verified) and revoke links after short-term use.
* Confirm your current space before making calls, so you don't consume personal quota in a team context or vice versa.
## Next Steps
* [Roles and Permissions](/features/team-collaboration/roles-permissions) — what each role can do, plus custom roles and resource scopes
* [Quotas and Usage](/features/team-collaboration/quota-and-usage) — allocate and monitor consumption
# Overview
Source: https://docs.memorylake.ai/features/team-collaboration/overview
Manage multi-user collaboration with teams, roles, invitations, and quotas
## Quick Introduction
Team collaboration turns individual memory into **organizational memory**: shared workspaces where documents, decisions, and extracted facts accumulate for the whole team — governed by roles, fine-grained permissions, and quotas.
* Share workspaces, projects, and memory with colleagues under clear access control
* Invite members via email or link, with resend and revoke (both sides need a verified email)
* Define base or custom roles, and scope permissions to individual workspaces and projects
* Allocate per-member quotas and review team-wide usage, rankings, and model consumption
* Switch between personal and team contexts so quota and permissions always match your intent
See the end-to-end walkthrough: structuring workspaces, loading knowledge, governing access, and keeping organizational memory current.
## Quick Start
1. [Create a team](https://app.memorylake.ai/panel/team): Add a name and description, and confirm default role assignment rules.
2. Invite colleagues: Choose link or email invitation based on your scenario. Resend if not received, or revoke if sent by mistake.
3. Quotas and roles: Assign Owner or Admin roles to key members (or define custom roles), and allocate quotas.
4. Start using: Switch between personal and team contexts to ensure quotas and permissions match the current identity.
## Documentation
Learn about team member roles and permission management.
Look up every fine-grained permission — what it lets you do, what you'll see when it's missing, and the identifier to share with your admin.
Learn how to invite members and manage access permissions.
Learn about quota allocation and usage management.
View team statistics and lifecycle management.
## Permission catalog
Every permission, grouped by feature area. Click a capability to jump to its full description in the [Permission Reference](/features/team-collaboration/permission-reference).
Each row carries a **Level** label, taken from the OpenAPI authorization matrix:
* `instance` — can be granted on a specific resource instance (e.g. one project). Admin can give it on project A and withhold it on project B.
* `service` — applies to the resource type as a whole. Once granted, it covers every instance of that resource in your team.
### Projects
| Capability | Identifier | Level |
| - | - | - |
| [Browse the project list](/features/team-collaboration/permission-reference#browse-the-project-list) | `project:read` | `service` |
| [Open a project](/features/team-collaboration/permission-reference#open-a-project) | `project:read` | `instance` |
| [Create a new project](/features/team-collaboration/permission-reference#create-a-new-project) | `project:create` | `service` |
| [Edit project settings](/features/team-collaboration/permission-reference#edit-project-settings) | `project:modify` | `instance` |
| [Delete a project](/features/team-collaboration/permission-reference#delete-a-project) | `project:delete` | `instance` |
| [Combined search](/features/team-collaboration/permission-reference#search-across-a-project-api-only) | `project:search` | `instance` |
### Documents
| Capability | Identifier | Level |
| - | - | - |
| [See the Files tab](/features/team-collaboration/permission-reference#see-the-files-tab) | `project:doc_read` | `instance` |
| [Read a document](/features/team-collaboration/permission-reference#read-a-single-document) | `project:doc_read` | `instance` |
| [Add a document](/features/team-collaboration/permission-reference#add-a-document-to-a-project) | `project:doc_add` | `instance` |
| [Remove a document](/features/team-collaboration/permission-reference#remove-a-document-from-a-project) | `project:doc_delete` | `instance` |
| [Search documents](/features/team-collaboration/permission-reference#search-documents-inside-a-project-api-only) | `project:doc_search` | `instance` |
### Memories
| Capability | Identifier | Level |
| - | - | - |
| [See the Memories tab](/features/team-collaboration/permission-reference#see-the-facts-tab) | `project:mem_read` | `instance` |
| [Read a memory](/features/team-collaboration/permission-reference#read-a-fact’s-content) | `project:mem_read` | `instance` |
| [Search memories](/features/team-collaboration/permission-reference#search-facts) | `project:mem_search` | `instance` |
| [Forget a memory](/features/team-collaboration/permission-reference#forget-delete-a-fact) | `project:mem_delete` | `instance` |
| [Add a memory](/features/team-collaboration/permission-reference#add-a-fact-via-api-api-only) | `project:mem_add` | `instance` |
| [Resolve a memory conflict](/features/team-collaboration/permission-reference#resolve-conflicting-facts) | `project:mem_conflict_resolve` | `instance` |
### MCP
| Capability | Identifier | Level |
| - | - | - |
| [See the Integrations tab](/features/team-collaboration/permission-reference#see-the-integrations-tab) | `project:mcp_read` | `instance` |
| [List MCP servers](/features/team-collaboration/permission-reference#view-existing-mcp-servers) | `project:mcp_list` | `instance` |
| [Create an MCP server](/features/team-collaboration/permission-reference#create-a-new-mcp-server) | `project:mcp_add` | `instance` |
| [Revoke an MCP server](/features/team-collaboration/permission-reference#revoke-an-mcp-server) | `project:mcp_delete` | `instance` |
### Library
| Capability | Identifier | Level |
| - | - | - |
| [Read files](/features/team-collaboration/permission-reference#read-your-files) | `drive:item_read` | `service` |
| [Upload files](/features/team-collaboration/permission-reference#upload-and-create-files) | `drive:item_add` | `service` |
| [Edit files](/features/team-collaboration/permission-reference#edit-your-files) | `drive:item_modify` | `service` |
| [Delete files](/features/team-collaboration/permission-reference#delete-files) | `drive:item_delete` | `service` |
# Permission Reference
Source: https://docs.memorylake.ai/features/team-collaboration/permission-reference
What each permission lets you do, and what you'll see when you don't have it
What you can do in MemoryLake — what pages you can open, what buttons you can click, what API calls succeed — depends on the permissions your team admin has granted you. This page is your guide:
* Each capability is described in plain language with **what it lets you do** and **what you'll see when it's missing**.
* The exact **permission identifier** is shown in each entry — copy that to your admin if you need a permission added.
### How permissions reach you
Permissions reach an individual member through three layers your admin controls:
1. **Role** — the built-in roles (Owner / Admin / Member) come with a default bundle of capabilities. Owners can also create **custom roles** by cloning a parent role or starting blank. See [Roles and Permissions](/features/team-collaboration/roles-permissions).
2. **Permission policy** — Allow / Deny rules layered on top of the role. Admins use these to override role defaults (e.g. let Members create projects).
3. **Resource scope** — per-member whitelist of specific workspaces, projects, or other resources a member can act on, plus the subset of operations allowed on each. This is how an `instance`-level capability gets narrowed to one or two workspaces or projects.
API Keys are programmatic identities (**Service Accounts**) — each one inherits the role and resource scope of the member who created it. Removing a member revokes every key they own.
## How to spot a missing permission
You don't have to memorize anything. MemoryLake makes missing permissions visible in predictable ways:
* **A tab disappears** from the side menu — that tab needs a permission you don't have.
* **A button is greyed out** — hover and the tooltip tells you exactly which permission is missing.
* **A list loads empty** even though you know there should be items in it.
* **Opening a URL directly** redirects you back, or shows a "no permission" page.
* Requests are rejected with **HTTP 403** and an `ACCESS_DENIED` error code.
* The error response tells you which permission is missing.
* See [Errors](/features/memorylake/api-reference/errors) for the full error envelope.
If a console button is greyed out and you don't know why, hover over it. The tooltip always names the exact permission you'd need.
## How permissions are grouped
Permissions live on seven resources. Every capability below belongs to one of them:
Your tenant-level data boundary — conversations, workspace-scoped search, and the right to bring actors and agents into it. All `workspace:*` capabilities live here.
What one actor may do inside one workspace, and the facts it accumulates there. Granted for that actor in that workspace — not for the workspace as a whole. All `workspace_actor:*` capabilities live here.
What one agent may do inside one workspace — its facts there, and A2A operations run as it. Granted for that agent in that workspace. All `workspace_agent:*` capabilities live here.
Individual memory carriers — the people whose facts accumulate across projects. An agent's memories are addressed on the agent, not here. All `actor:*` capabilities live here.
AI agent definitions — model, system prompt, capabilities, and versioned configurations. All `agent:*` capabilities live here.
Knowledge domains inside a workspace — documents, project-scoped facts, and MCP servers. All `project:*` capabilities live here.
Your shared file space — the storage that sits underneath every project. All `drive:*` capabilities live here.
### Lists are filtered, not gated
There is no permission for *seeing a list*. Every list endpoint returns the rows you may open and leaves out the rest, so a list is never refused for want of a permission — it comes back shorter. A workspace list shows the workspaces you hold `workspace:read` on, a project list the projects you hold `project:read` on, and so on down each resource.
This replaces an earlier set of `*_list` capabilities, which could be held without the matching `*_read` and produced rows you could see but not open. If you are looking for `project:list`, `workspace:list`, `actor:list`, `agent:list` or any of their siblings, that is why they are gone: holding `*_read` is holding the list.
An empty list and a missing row say the same thing as "you may not open this". Neither is an error, and neither tells you whether the thing exists.
## How permissions are granted
Every capability has a **Level** — `instance` or `service` — that determines whether your admin can narrow it down to specific resources. Each entry below shows the level in its **Level** line.
Acts on a specific resource instance (one workspace, one project, one actor, one agent). The role's policy makes the action **available**; the member's **resource scope** decides **which instances** they can perform it on — admins can hand out access to workspace A and withhold it on workspace B from the same dialog.
Covers opening, editing, deleting, and searching within a specific workspace or project, plus all operations on its contents. Marked `instance` in the catalog.
Acts on the resource type as a whole — there is no specific instance to narrow to. Once a role's policy grants it, it applies team-wide; **resource scope has no effect** on these capabilities.
* **Browse resource lists** and **create new resources** — these don't act on a specific instance.
* **All Library capabilities** — Library is one shared file space.
Marked `service` in the catalog.
If something isn't working in a specific workspace or project, the first question to ask is usually: **do I have permission to open that workspace or project at all?** Instance-level capabilities only do anything inside resources you've been granted access to.
***
## Common role recipes
These are typical capability bundles to use as **starting points** when you're either building a custom role or adding **permission policies** on top of the built-in Member role. They are not pre-built roles — Owners assemble them via **Team > Permission Settings**, then narrow `instance` capabilities to the right resources via the member's **Resource Scope** when assigning the role.
Can browse and open a project, read its documents and facts, but can't change anything.
| Identifier | Level | Why |
| - | - | - |
| `workspace:read` | `instance` | Open the workspace the project lives in |
| `project:read` | `instance` | Open the project's home and tabs |
| `project:doc_read` | `instance` | Read individual documents |
| `project:mem_read` | `instance` | Read individual facts |
| `project:mcp_read` | `instance` | See the Integrations tab |
| `project:mcp_list` | `instance` | See existing MCP servers (read-only) |
| `drive:item_read` | `service` | Preview and download files in Library |
Grant the `instance` permissions on **the specific workspace and projects** the viewer should see.
Read-only viewer **plus** the ability to upload, replace, and remove project documents.
| Identifier | Level | Why |
| - | - | - |
| (everything from read-only viewer) | | |
| `project:doc_add` | `instance` | Add documents to the project |
| `project:doc_delete` | `instance` | Remove documents from the project |
| `drive:item_add` | `service` | Upload new files to Library |
| `drive:item_modify` | `service` | Rename, move, edit metadata, save comments |
| `drive:item_delete` | `service` | Delete files from Library |
The `drive:item_*` set is what enables the actual upload UI; without it, `project:doc_add` lets users **import existing** Library files into the project but the upload button stays greyed out.
Curator **plus** the ability to manage the project itself, its facts, conflicts, and MCP integrations.
| Identifier | Level | Why |
| - | - | - |
| (everything from document curator) | | |
| `project:create` | `service` | Spin up new projects |
| `project:modify` | `instance` | Rename / edit / share the project |
| `project:delete` | `instance` | Delete the project |
| `project:mem_modify` | `instance` | Update facts |
| `project:mem_delete` | `instance` | Forget facts |
| `project:mem_conflict_resolve` | `instance` | Resolve fact conflicts |
| `project:mcp_add` | `instance` | Create MCP servers |
| `project:mcp_delete` | `instance` | Revoke MCP servers |
Full workspace lifecycle management — create, configure, and delete workspaces, manage conversations, and control which actors and agents operate in each workspace.
| Identifier | Level | Why |
| - | - | - |
| `workspace:create` | `service` | Spin up new workspaces |
| `workspace:read` | `instance` | Open the workspace |
| `workspace:modify` | `instance` | Edit workspace settings |
| `workspace:delete` | `instance` | Delete the workspace |
| `workspace:conv_read` | `instance` | Read conversation history |
| `workspace:conv_append` | `instance` | Send messages |
| `workspace:conv_delete` | `instance` | Delete conversations |
| `workspace_actor:create` | `instance` | Add actors to the workspace |
| `workspace_actor:delete` | `instance` | Remove actors from the workspace |
| `workspace_agent:create` | `instance` | Add agents to the workspace |
| `workspace_agent:delete` | `instance` | Remove agents from the workspace |
| `workspace_agent:a2a` | `instance` | Run A2A protocol operations |
Grant the `instance` permissions on **the specific workspaces** the administrator should manage.
The minimum set for an API credential that reads and writes conversations in a workspace without managing the workspace itself.
| Identifier | Level | Why |
| - | - | - |
| `workspace:read` | `instance` | Open the workspace |
| `workspace:conv_read` | `instance` | Read conversation messages |
| `workspace:conv_append` | `instance` | Send messages to conversations |
Add `workspace:conv_delete` if the integration should also clean up old conversations.
Can create, configure, and deploy agents across workspaces — but doesn't need project or document access.
| Identifier | Level | Why |
| - | - | - |
| `agent:create` | `service` | Create new agents |
| `agent:read` | `instance` | View agent configuration |
| `agent:modify` | `instance` | Update agent identity |
| `agent:read` | `instance` | See version history |
| `agent:modify` | `instance` | Publish new versions |
| `agent:read` | `instance` | Inspect a specific version |
| `workspace:read` | `instance` | Open the workspace |
| `workspace_agent:create` | `instance` | Bind agents to workspaces |
| `workspace_agent:delete` | `instance` | Remove agents from workspaces |
Add `actor:*` permissions if the operator also manages the actors that agents interact with.
The minimum capability set for a credential that backs one MCP server and is used by an external client to read project content.
| Identifier | Level | Why |
| - | - | - |
| `workspace:read` | `instance` | Open the workspace the project lives in |
| `project:read` | `instance` | Open the project |
| `project:doc_read` | `instance` | Fetch document detail |
| `project:doc_search` | `instance` | Semantic search over documents |
| `project:mem_read` | `instance` | Fetch fact detail |
| `project:mem_search` | `instance` | Search facts |
| `project:search` | `instance` | Combined document + fact search |
Add `workspace:conv_append` if the integration should write back conversations that produce facts.
An API Key is a **Service Account** — it inherits the role and resource scope of the member who created it. To restrict this key to a single project, set the **creator's** resource scope to that project; you can't scope the key independently. If the creator's role or scope changes, the key follows.
***
## Working with workspaces
### Create a new workspace
Lets you start a brand-new workspace from scratch.
**Without it:** "New workspace" buttons are hidden or greyed out.
**Identifier:** `workspace:create`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
***
### Open a workspace
Lets you open a workspace and view its contents. This permission also gates workspace-scoped search — the [Search Memories](/features/memorylake/api-reference/search/search-memories) API requires it.
**Without it:** workspace cards appear faded and clicking does nothing. Typing the workspace URL directly shows a full-page "no permission" message. Workspace-level search calls return 403.
**Identifier:** `workspace:read`
**Level:** `instance` — granted on a specific workspace.
***
### Edit workspace settings
Lets you rename a workspace, edit its description, and change its configuration.
**Without it:** all "Rename" and "Edit" options are greyed out wherever they appear.
**Identifier:** `workspace:modify`
**Level:** `instance` — granted on a specific workspace.
***
### Delete a workspace
Lets you permanently remove a workspace.
Deleting a workspace is destructive — its conversations, actor bindings, agent bindings, and all workspace-scoped data are removed along with it.
**Without it:** "Delete" options are greyed out on every workspace card and dialog.
**Identifier:** `workspace:delete`
**Level:** `instance` — granted on a specific workspace.
***
## Managing conversations in a workspace
Conversations are workspace-scoped — they live in a workspace and are linked to one or more projects where extracted facts are stored.
### Read a conversation
Lets you open a conversation and read its messages, including batch-fetching multiple messages at once.
**Without it:** conversation rows appear faded; clicking does nothing.
**Identifier:** `workspace:conv_read`
**Level:** `instance` — granted on a specific workspace.
This permission alone lets you read existing messages but not add new ones. Sending a message requires the next permission.
***
### Send a message to a conversation
Lets you append a new message to an existing conversation.
**Without it:** the message input area is disabled and explains it needs the conversation-append permission.
**Identifier:** `workspace:conv_append`
**Level:** `instance` — granted on a specific workspace.
***
### Delete a conversation
Lets you permanently remove a conversation from a workspace.
**Without it:** "Delete" actions on conversations are greyed out.
**Identifier:** `workspace:conv_delete`
**Level:** `instance` — granted on a specific workspace.
***
## Managing actor bindings in a workspace
Actors are created globally, then **bound** to workspaces to operate within them. These permissions control which actors can participate in a workspace.
### Bind an actor to a workspace
Lets you add an existing actor to a workspace so they can participate in conversations and accumulate facts.
**Without it:** the "Add actor" action is greyed out.
**Identifier:** `workspace_actor:create`
**Level:** `instance` — granted per actor, in one workspace.
***
### Remove an actor from a workspace
Lets you unbind an actor from a workspace — they stop participating, but their globally-stored identity and facts remain.
**Without it:** the per-actor "Remove" action is greyed out.
**Identifier:** `workspace_actor:delete`
**Level:** `instance` — granted per actor, in one workspace.
***
## Managing actor facts in a workspace
Actor facts are knowledge about a specific person or agent that accumulates across projects within a workspace. These permissions control access to that per-actor knowledge.
### Read an actor fact
Lets you view the full content of a specific actor fact.
**Without it:** fact rows appear faded; clicking does nothing.
**Identifier:** `workspace_actor:fact_read`
**Level:** `instance` — granted per actor, in one workspace.
***
### Update an actor fact
Lets you edit the content of an actor fact.
**Without it:** "Edit" actions on actor facts are greyed out.
**Identifier:** `workspace_actor:fact_modify`
**Level:** `instance` — granted per actor, in one workspace.
***
### Forget an actor fact
Lets you permanently remove an actor fact.
**Without it:** "Forget" actions on actor facts are greyed out.
**Identifier:** `workspace_actor:fact_delete`
**Level:** `instance` — granted per actor, in one workspace.
***
## Managing agent bindings in a workspace
Agents are created globally, then **bound** to workspaces to serve conversations. These permissions control which agents can operate in a workspace.
### Bind an agent to a workspace
Lets you add an existing agent to a workspace so it can serve conversations.
**Without it:** the "Add agent" action is greyed out.
**Identifier:** `workspace_agent:create`
**Level:** `instance` — granted per agent, in one workspace.
***
### Remove an agent from a workspace
Lets you unbind an agent from a workspace — it stops serving conversations, but its global definition and version history remain.
**Without it:** the per-agent "Remove" action is greyed out.
**Identifier:** `workspace_agent:delete`
**Level:** `instance` — granted per agent, in one workspace.
***
## A2A protocol operations
### Use the A2A protocol
Lets you initiate and participate in Agent-to-Agent (A2A) protocol operations within a workspace.
**Without it:** A2A requests to this workspace return 403.
**Identifier:** `workspace_agent:a2a`
**Level:** `instance` — granted per agent, in one workspace.
***
## Working with actors
### Create an actor
Lets you create a new actor — a person or assistant that can accumulate facts across workspaces and projects.
**Without it:** "New actor" buttons are hidden or greyed out.
**Identifier:** `actor:create`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
***
### View an actor
Lets you open an actor and see their configuration and details.
**Without it:** actor rows appear faded; clicking does nothing. Typing the actor URL directly shows a "no permission" message.
**Identifier:** `actor:read`
**Level:** `instance` — granted on a specific actor.
***
### Edit an actor
Lets you update an actor's name, description, and other settings.
**Without it:** all "Edit" options on the actor are greyed out.
**Identifier:** `actor:modify`
**Level:** `instance` — granted on a specific actor.
***
### Delete an actor
Lets you permanently remove an actor.
Deleting an actor removes their identity and fact associations. This cannot be undone.
**Without it:** "Delete" options on actors are greyed out.
**Identifier:** `actor:delete`
**Level:** `instance` — granted on a specific actor.
***
## Working with agents
### Create an agent
Lets you define a new agent with its model, system prompt, and capabilities. Creating an agent automatically creates a corresponding actor.
**Without it:** "New agent" buttons are hidden or greyed out.
**Identifier:** `agent:create`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
***
### View an agent
Lets you open an agent and see its configuration — model, system prompt, capabilities, and policies. **Its version history comes with it**: listing past versions and opening any one of them are part of reading the agent, not permissions of their own.
**Without it:** agent rows appear faded; clicking does nothing.
**Identifier:** `agent:read`
**Level:** `instance` — granted on a specific agent.
***
### Edit an agent's identity
Lets you update an agent's identity fields — name, description, and other top-level settings that apply across all versions. **Publishing a new version is the same permission**: a version is a snapshot of the agent, so changing what it will be next is changing the agent.
**Without it:** "Edit" options on the agent's identity are greyed out.
**Identifier:** `agent:modify`
**Level:** `instance` — granted on a specific agent.
Changing an agent's configuration (model, prompt, capabilities) creates a new **version** — that requires the version-create permission below. This permission only covers identity fields that update in place.
***
### Delete an agent
Lets you permanently remove an agent and all its versions.
Deleting an agent also removes its auto-created actor. This cannot be undone.
**Without it:** "Delete" options on agents are greyed out.
**Identifier:** `agent:delete`
**Level:** `instance` — granted on a specific agent.
***
## Working with projects
### Open a project
Lets you click a project card and view its contents — the project's home page and every tab inside it.
**Without it:** project cards appear faded and clicking does nothing. Typing the project URL directly shows a full-page "no permission" message.
**Identifier:** `project:read`
**Level:** `instance` — granted on a specific project.
***
### Create a new project
Lets you start a brand-new project from scratch.
**Without it:** "New project" buttons are hidden or greyed out — on the list page, in the first-project onboarding card, in the quick-start wizard, and on the integrations page.
**Identifier:** `project:create`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
***
### Edit project settings
Lets you rename a project, edit its description, change which industry it belongs to, and share it with others. The "Bind industry" button inside the chat composer also depends on this.
**Without it:** all "Rename", "Edit", and "Share" options are greyed out wherever they appear.
**Identifier:** `project:modify`
**Level:** `instance` — granted on a specific project.
***
### Delete a project
Lets you permanently remove a project.
Deleting a project is destructive — its documents and facts are removed along with it.
**Without it:** "Delete" options are greyed out on every project card and dialog.
**Identifier:** `project:delete`
**Level:** `instance` — granted on a specific project.
***
### Search across a project (API-only)
Lets you call the [Search Memories](/features/memorylake/api-reference/search/search-memories) API to query documents and facts within a project at once.
**Where this matters:** API integrations only. In the console, search inside a project goes through the document-search and fact-search permissions below.
**Identifier:** `project:search`
**Level:** `instance` — granted on a specific project.
***
## Working with documents inside a project
### Read a single document
Lets you fetch full document details through the API.
**Where this matters:** mostly API integrations, plus the console's background poll that refreshes document processing status. Console file downloads go through the **Read your files** permission in the Library section.
**Identifier:** `project:doc_read`
**Level:** `instance` — granted on a specific project.
**Covers this API:** [Get Document](/features/memorylake/api-reference/v3-documents/get-document).
***
### Add a document to a project
Lets you bring a file into a project — through the "Add document" button, the empty-state upload card, and the upload icon inside the chat composer.
**Without it:** every "Add document" / upload entry point is greyed out.
**Identifier:** `project:doc_add`
**Level:** `instance` — granted on a specific project.
The [Import Documents](/features/memorylake/api-reference/v3-documents/import-documents) API endpoint actually checks **two** permissions together: `project:doc_add` (this one) **and** [`drive:item_read`](#read-your-files) — the server has to read each referenced Library file before importing it. Without `drive:item_read`, the call returns 403 even though `project:doc_add` is granted.
If you're also **uploading a brand-new file** before importing it, you'll additionally need [`drive:item_add`](#upload-and-create-files) for the Library upload step.
***
### Remove a document from a project
Lets you take a document out of a project, one at a time or in bulk.
Removing a document from a project unlinks it from that project but does **not** delete the underlying file in your Library. Deleting the file itself needs the **Delete files** permission in the Library section below.
**Without it:** the per-row "Remove" action and the batch-remove action on the Files tab are greyed out.
**Identifier:** `project:doc_delete`
**Level:** `instance` — granted on a specific project.
***
### Search documents inside a project (API-only)
Lets you run semantic search queries over the documents in a project.
**Where this matters:** API integrations only. The console's in-document search is wired to its own controls.
**Identifier:** `project:doc_search`
**Level:** `instance` — granted on a specific project.
***
## Working with facts inside a project
### Read a fact's content
Lets you click a fact row to open its detail panel — full content, timestamps, and source information.
**Without it:** fact rows show as faded; clicking does nothing; drilling into a keyword from the cloud also fails.
**Identifier:** `project:mem_read`
**Level:** `instance` — granted on a specific project.
**Covers this API:** [Get Fact](/features/memorylake/api-reference/facts/get-fact).
***
### Search facts
Lets you find facts by keyword. The search box at the top of the Facts tab depends on this.
**Without it:** the search box itself is hidden — you can scroll the list but you can't filter it.
**Identifier:** `project:mem_search`
**Level:** `instance` — granted on a specific project.
**Covers this API:** [Search Memories](/features/memorylake/api-reference/search/search-memories).
***
### Add a fact via API (API-only)
Lets you push a fact in directly through the API.
**Where this matters:** API integrations only. Inside the console, facts are produced automatically from conversations and document ingestion — there's no manual "add a fact" button.
**Identifier:** `project:mem_add`
**Level:** `instance` — granted on a specific project.
***
### Update a fact
Lets you edit an existing fact's content.
**Without it:** "Edit" actions on facts are greyed out.
**Identifier:** `project:mem_modify`
**Level:** `instance` — granted on a specific project.
***
### Forget (delete) a fact
Lets you make MemoryLake forget a fact, one at a time or in bulk.
**Without it:** the per-row "Forget" action and the batch-forget action are greyed out.
**Identifier:** `project:mem_delete`
**Level:** `instance` — granted on a specific project.
***
### Resolve conflicting facts
Lets you see the **Conflicts** tab inside a project, review each conflict, and pick how to resolve it.
**Without it:** the Conflicts tab disappears entirely — you can't see whether conflicts exist or what they're about.
**Identifier:** `project:mem_conflict_resolve`
**Level:** `instance` — granted on a specific project.
This is currently a single permission — there's no read-only conflict view. If you need to see conflicts without being able to resolve them, ask your admin.
***
## Managing MCP for a project
An **MCP server** is the connection point that lets a third-party tool (Claude desktop, an MCP-compatible client, or your own app) talk to a specific project on your behalf. Each MCP server is issued its own credential. The four permissions below split the lifecycle into see / list / create / revoke.
### See the Integrations tab
Lets you open the **Integrations** tab on a project — where MCP servers are listed and managed.
**Without it:** the Integrations tab is hidden from the project's side menu.
**Identifier:** `project:mcp_read`
**Level:** `instance` — granted on a specific project.
***
### View existing MCP servers
Lets you see the list of MCP servers issued for a project, including when each one was created and what it's named.
**Without it:** the integrations page shows an empty "no permission" state, even when MCP servers exist.
**Identifier:** `project:mcp_list`
**Level:** `instance` — granted on a specific project.
***
### Create a new MCP server
Lets you set up a new MCP server to connect a third-party tool to the project.
**Without it:** the "Add integration" / "Create MCP server" button is greyed out.
**Identifier:** `project:mcp_add`
**Level:** `instance` — granted on a specific project.
***
### Revoke an MCP server
Lets you delete an existing MCP server — immediately disconnecting everything that was using it.
**Without it:** the per-row "Delete" / "Revoke" action is greyed out.
**Identifier:** `project:mcp_delete`
**Level:** `instance` — granted on a specific project.
***
## Working with your Library
Your Library is the shared file space that sits underneath every project. When you "add a document to a project", the file goes into your Library first and the project just links to it. The four permissions below apply across all your projects at once — they are not granted per project.
### Read your files
Lets you browse the file tree, see thumbnails, preview files in the viewer, download files, and read the comments people have left on them.
**Without it:** thumbnails fall back to plain file-type icons, "Download" menu items grey out, file previews are skipped, and comment panels degrade silently.
**Identifier:** `drive:item_read`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
**Covers these APIs:** [Get Item](/features/memorylake/api-reference/library/get-item), [List Items](/features/memorylake/api-reference/library/list-items).
***
### Upload and create files
Lets you upload files, create folders, and attach external storage. This is the permission that runs in the background whenever you click "Add document" or drag a file into the app.
**Without it:** "New folder" and "Upload file" entry points are greyed out everywhere, including inside the "Add document" dialog.
**Identifier:** `drive:item_add`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
**Covers these APIs:** [Create Upload](/features/memorylake/api-reference/library/create-upload), [Create Item](/features/memorylake/api-reference/library/create-item).
***
### Edit your files
Lets you rename files, move them between folders, edit their metadata and tags, and save comments. This also covers managing custom attributes (xattrs) on files via the API.
**Without it:** rename, move, and edit-metadata options grey out. The "Save" button on the comment panel is disabled and explains it needs the file-edit permission.
**Identifier:** `drive:item_modify`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
**Covers these APIs:** [Set Item Xattrs](/features/memorylake/api-reference/library/set-item-xattrs), [Delete Item Xattrs](/features/memorylake/api-reference/library/delete-item-xattrs).
Deleting a tag from a file (removing an xattr) counts as **editing**, not **deleting** — you're changing the file's metadata, not removing the file itself.
***
### Delete files
Lets you permanently delete files and folders, one or in bulk.
A deleted file goes away from every project that linked to it. If you only want to remove the link from one project, use **Remove a document from a project** above instead.
**Without it:** all "Delete" actions on files and folders are greyed out.
**Identifier:** `drive:item_delete`
**Level:** `service` — applies team-wide (not tied to a specific resource instance).
**Covers these APIs:** [Delete Item](/features/memorylake/api-reference/library/delete-item).
***
## Quick troubleshooting
You have the **Browse workspaces** permission but not the **Open a workspace** one. Ask your admin to grant `workspace:read` on the specific workspace.
The list shows the projects you may open, and nothing else — seeing the list is not a permission of its own. A project you cannot open simply does not appear in it. Ask your admin to grant `project:read` on the project you are looking for, and check that you also have `workspace:read` on the workspace it lives in.
Each tab depends on its own permission:
* **Files** tab needs `project:doc_read`
* **Facts** tab needs `project:mem_read`
* **Integrations** tab needs `project:mcp_read`
* **Conflicts** tab needs `project:mem_conflict_resolve`
Hover over the button — the tooltip tells you exactly which permission you'd need. Screenshot the tooltip and forward it to your admin.
You have `workspace:conv_read` but not `workspace:conv_append`. Ask your admin to grant `workspace:conv_append` on this workspace.
You need both `agent:read` on the agent **and** `workspace_agent:create` on the workspace. Check that you have both.
The response body names the permission, so you do not have to work it out. Read `data.denied[].permission`
for the identifier, and `data.required_any_of` for what would have satisfied it — granting any one of those
entries is enough. `data.stage` tells you which ask to make: `capability` — ask for the permission itself;
`instance` — ask for this workspace or project to be added to your access. See [Errors](/features/memorylake/api-reference/errors) for the full body.
Admins reach into one of three places depending on what's needed:
* **Permission policy** (under **Team > Permission Settings**) — to enable a capability your role doesn't include by default. The admin adds an Allow rule with the identifier you sent.
* **Resource scope** (under **Members > \[you] > Set resource scope...**) — to extend an `instance`-level capability to a specific workspace, project, actor, or agent, or to narrow it down.
* **Role change** (under **Members > \[you] > Assign role...**) — if the capability is already in a bigger role and they'd rather hand you that whole role.
Owners can do all three. Admins can do the first two but **can't promote you** to Admin or to a custom role — that's Owner-only.
* The **workspace or project home page** shows a full-page "no permission" message with a contact-admin link.
* **A tab inside a resource you can't see** redirects you back to the default tab.
***
Looking for a bird's-eye list of all permissions grouped by area? See the [Permission catalog](/features/team-collaboration/overview#permission-catalog) on the Team collaboration overview.
If the capability you need doesn't appear on your role, contact your team's owner or administrator. They can adjust roles in **Teams > My Teams > Members**.
# Quotas and Usage
Source: https://docs.memorylake.ai/features/team-collaboration/quota-and-usage
Allocate quotas to teams and members, monitor consumption, and intercept anomalies in time
## Use Cases
* Multiple users share the same endpoint and need to control team-wide quotas and allocate them to members.
* Quickly view team and personal usage and rankings to identify and handle anomalies promptly.
* Intercept calls immediately when quotas are insufficient to avoid overruns.
## What You Can Do
* **Team Quotas**: Set or adjust total quotas for the team as an overall consumption limit.
* **Member Quotas**: Allocate or adjust quotas for individual members, with support for subsequent adjustments. Insufficient quotas will directly intercept calls.
* **Usage Visibility**: View team usage, member rankings, and personal usage views.
* **Context Enforcement**: When making calls in the team context, quotas are validated against team/member quotas. In the personal context, quotas are validated against personal quotas.
## Quota Calculation and Deduction Logic
* **Unlimited Teams**: When a team is marked as "unlimited", it is not truly unlimited. Real-time available quota takes the team owner's current balance, while cumulative usage is still recorded on the team side.
* **Limited Teams**: Real-time available quota takes the minimum of "team remaining quota" and "owner's current balance" to prevent the team from exceeding the limit or the owner's balance.
* **Personal Space**: In the personal context, personal quota and usage are used directly.
* **Pre-deduction and Rollback**: Requests are validated and pre-deducted first. After successful return, the deduction is applied. Failures will roll back the pre-deduction to ensure quota accuracy.
* **Behavior After Exhaustion**: Insufficient quota at any level (personal, team, or owner balance) will directly reject the request to prevent overruns.
## How to Allocate and Adjust
1. In the "Members" page of team details, find the target member.
2. Set or adjust the member's quota, which takes effect immediately after saving.
3. If overall control is needed, first set the team total quota, then subdivide at the member level.
4. After adjustment, return to the statistics view to confirm if usage and rankings are normal.
## View Usage and Rankings
* Team Overview: View team period usage, trends, and distribution in "Usage/Statistics".
* Member Rankings: View member usage rankings in the same section to easily identify abnormal consumption.
* Personal View: Members can view their own usage to confirm if they're approaching quota limits.
## Tips
* Quota and status validation take effect in real time. Insufficient quotas will directly reject calls. Reserve a safety margin when necessary.
* If member usage is abnormal, first tighten quotas or adjust roles, then investigate the source of calls.
* Switch context before making calls to ensure quota validation is performed under the correct identity.
## Next Steps
* If you need to combine invitations, roles, and lifecycle management, continue reading the relevant sections.
* Before migrating to production, use test tokens to verify the team and member quota enforcement logic, then switch to production traffic.
# Roles and Permissions
Source: https://docs.memorylake.ai/features/team-collaboration/roles-permissions
Grant the right access to the right people — base roles, custom roles, and per-resource scopes
## Base Roles
* **Owner**: the creator (or a transferred successor). Can dissolve the team, transfer ownership, allocate quotas, adjust roles, and remove members.
* **Admin**: day-to-day operations. Can invite and remove members, adjust quotas and roles, and manage team resources — but cannot dissolve the team or take ownership.
* **Member**: uses team resources — shared workspaces, memory, and quota — and views information relevant to them. Can leave voluntarily.
## Custom Roles
When the three base roles are too coarse, define **custom roles** with exactly the capabilities you need — for example a "Knowledge Curator" who can resolve memory conflicts and manage documents but cannot invite members, or a "Read-only Auditor" for compliance review.
Every grantable capability is listed in the [Permission Reference](/features/team-collaboration/permission-reference), with identifiers (`project:doc_read`, `project:mem_conflict_resolve`, `drive:item_add`, …) and what a member sees when a permission is missing.
## Per-Resource Scopes
Beyond roles, permissions can be scoped to **specific resource instances** — a member can hold `project:read` on one project and not another. Scopable resource types are **workspaces**, **projects**, and **database connections**; granting a workspace-level scope cascades to the projects inside it.
> *Typical use*: a contractor gets access to exactly the "Vendor audit" project in the Operations workspace — everything else stays invisible.
## Available Operations
| Area | What's possible |
| - | - |
| Team management | Create, update details, transfer ownership (Owner only), dissolve |
| Members & invitations | Email or link invitations, resend/revoke, role assignment, removal; members may leave |
| Quota allocation | Team totals and per-member allocations; insufficient quota blocks calls immediately |
| Roles & scopes | Base roles, custom roles, and per-resource scopes |
| Statistics | Team-wide usage, member rankings, model usage; members always see their own |
| Space switching | Switch between personal and team context — quota and permissions follow the active space |
## Setting Up a New Team
1. Create the team and complete its details in the console (**Teams → My Teams**).
2. Invite colleagues from the team's **Invites** tab, assigning roles as you go — both inviter and invitee need verified email addresses.
3. Promote core colleagues to Admin; leave others as Member, or define custom roles for finer control.
4. Allocate per-member quotas on the **Members** tab, then have members switch to the team context for their calls.
## Secure Handover
1. Confirm the successor is already a member with an appropriate role.
2. The Owner performs **Transfer Ownership** — the previous Owner is automatically downgraded.
3. Tighten remaining permissions: adjust roles, revoke resource scopes, and disable API keys belonging to departing members.
An API key inherits the permissions of the member who created it. When someone leaves or is downgraded, review and disable their keys — otherwise automation may keep running with their old access.
## Tips
* Check your active space before making calls, so quota is drawn from the intended pool.
* High-risk actions (dissolving the team, transferring ownership, editing others' quotas, removing members) are restricted to authorized roles.
* Prefer removing a permission over relying on convention — see the [Permission Reference](/features/team-collaboration/permission-reference).
* Statistics accumulate from real usage; empty charts on a new team are normal.
## Next Steps
* [Permission Reference](/features/team-collaboration/permission-reference) — every capability, explained
* [Invitations and Access](/features/team-collaboration/invitation-and-access) — the invitation flow in detail
* [Quotas and Usage](/features/team-collaboration/quota-and-usage) — allocation and monitoring
# Overview
Source: https://docs.memorylake.ai/overview
MemoryLake is an AI memory platform — store, compute, and retrieve long-term memory for people, teams, and AI agents
## What is MemoryLake?
MemoryLake gives AI a memory that lasts. Upload documents, hold conversations, and connect your AI tools — MemoryLake extracts durable memories from all of it, keeps them consistent, and serves them back to any model or agent that needs context.
Every LLM call is stateless by default. MemoryLake adds the missing layer: a shared, queryable memory pool that persists across sessions, apps, models, and teammates.
## The Platform at a Glance
The core product: workspaces, projects, documents, and extracted memories — with a Playground to experience memory-augmented chat and integrations to bring memory into your tools.
A drop-in gateway that adds persistent memory to your existing OpenAI / Anthropic API calls with a base-URL change. Private preview.
A unified, OpenAI-compatible entry point to mainstream models — one API key, one endpoint, native paths preserved for Claude and Gemini.
Shared workspaces with roles, fine-grained permissions, member quotas, and usage analytics — memory that belongs to the organization, not just one person.
## Core Capabilities
* **Memory extraction**: Conversations and documents are distilled into structured, deduplicated memories — not just stored as raw text
* **Memory retrieval**: Hybrid semantic + keyword search across memories and document content, scoped by workspace and project
* **Memory hygiene**: Source traces show where each memory came from; conflict detection surfaces contradictory memories for you to resolve
* **Multimodal documents**: PDF, Word, Excel, PowerPoint, Markdown, text, and images are parsed and indexed for retrieval
* **Open Data**: Subscribe projects to curated industry datasets (research, clinical, financial, patents, and more) that agents can search alongside your own content
* **Integrations**: OpenClaw / QClaw / Hermes agent plugins, a REST API, and an MCP server — memory follows your agents wherever they run
## Individual Memory and Organizational Memory
MemoryLake is built around a simple idea: memory has an owner and a scope.
* **Personal**: your own workspace remembers your preferences, decisions, and files — every AI tool you connect gets the same context about you.
* **Organizational**: team workspaces accumulate shared knowledge — project documents, decisions, and domain facts — governed by roles and per-resource permissions, so institutional memory survives personnel changes.
Learn how the pieces fit together in [Core Concepts](/concepts), or jump straight into a scenario:
Give every AI tool you use one consistent, private memory of you.
Turn scattered documents and decisions into governed organizational memory.
Make OpenClaw and other coding agents remember context across sessions.
Add per-user long-term memory to your own product via API or Memory Router.
## Getting Started
1. **[Sign up](https://app.memorylake.ai)** — a default workspace is provisioned for you automatically.
2. **[Try the Playground](/quickstart)** — tell it something to remember, add Open Data, upload a file, and watch memory work.
3. **[Create an API key](/authentication)** — one key authenticates the REST API, Model Router, and agent plugins.
4. **[Connect your tools](/features/memorylake/mcp-servers/overview)** — install the OpenClaw plugin or integrate via API so memory follows you everywhere.
# Quick Start
Source: https://docs.memorylake.ai/quickstart
Experience AI memory in five minutes — chat, upload, retrieve, and connect your tools
This guide takes you from sign-up to a working memory in about five minutes, then points you at the integration path that fits how you work.
## Step 1: Sign Up
Create an account at [app.memorylake.ai](https://app.memorylake.ai). MemoryLake automatically provisions your personal workspace and assistant — there is nothing to configure before your first conversation.
## Step 2: Experience Memory in the Playground
Open the **Playground** from the sidebar (new accounts land there with a short guided tour):
Try: *"Remember that my name is Ming and I prefer answers in bullet points."*
Behind the scenes, MemoryLake extracts a durable memory from the conversation — not a transcript, a fact.
Subscribe your project to a curated industry dataset — research papers, financial data, clinical trials, and more — so the assistant can search authoritative external sources alongside your own content.
Attach a PDF, Word, Excel, or Markdown file directly in the chat. Its content is parsed, indexed, and becomes retrievable context.
Start a **new** conversation and ask: *"What's my name and how do I like my answers?"* The assistant recalls it — that's memory persisting across sessions. The Home page's Memory On/Off comparison shows the same effect side by side.
Visit **Memories** in the sidebar to see what was extracted — each memory shows its content and a **source trace** back to the conversation or document it came from.
## Step 3: Create an API Key
For anything programmatic — the REST API, Model Router, or agent plugins — create an API key:
1. Open **API Keys** in the console sidebar
2. Click create, give the key a name, and pick an expiry (defaults to 30 days; "Never" is available)
3. Copy the `sk-…` key when it is revealed — it is shown only once
See [Authentication](/authentication) for header formats and key management.
## Step 4: Put Memory Where You Work
Pick the path that matches your workflow:
Install the MemoryLake plugin — your agent automatically recalls context, captures new memories, and uploads files you share with it.
Full programmatic control: projects, documents, memory add/search/trace, and conflict resolution at `https://app.memorylake.ai/openapi/memorylake`.
Add memory to your existing OpenAI/Anthropic calls with a base-URL change. Private preview.
Call mainstream LLMs through one OpenAI-compatible endpoint with the same API key.
## What Just Happened?
Your conversation and file were distilled into **memories** inside a **project** in your **workspace** — retrievable by any assistant or API client you connect, forever scoped and private to you. When you're ready to share memory with a team, see [Team Collaboration](/features/team-collaboration/overview); to understand the full model, read [Core Concepts](/concepts).
## Next Steps
* [Core Concepts](/concepts) — workspaces, projects, memories, actors, agents
* [Scenarios](/scenarios/personal-ai-memory) — personal memory, team knowledge bases, coding agents, and product integration walkthroughs
* [MemoryLake feature guide](/features/memorylake/overview) — documents, memories, conflicts, connectors, and more
# Build Apps with Memory
Source: https://docs.memorylake.ai/scenarios/ai-apps-with-memory
Add per-user long-term memory to your own product via the REST API or Memory Router
## The Problem
You're building an AI product — a copilot, a support bot, a companion app. Users expect it to remember them, but building a memory layer means vector databases, extraction pipelines, deduplication, and conflict handling: months of infrastructure that isn't your product.
## What MemoryLake Changes
MemoryLake is your memory backend. Two integration styles, one shared memory pool:
| Style | How | Best for |
| - | - | - |
| **Memory Router** (private preview) | Point your existing OpenAI/Anthropic SDK at the gateway, pass a `boundary_id` per user | Fastest path — memory without changing your call sites |
| **REST API** | Explicit `add` / `search` / `trace` / `forget` calls against `https://app.memorylake.ai/openapi/memorylake` | Full control over what is stored and when it's recalled |
Both write to the same pool: memory captured through the Router is searchable through the API, and vice versa.
## Path A: Memory Router — memory as a base-URL change
Create one [Boundary](/concepts#boundary-memory-router-&-mcp) per user (it binds workspace + project + actors into a single scope id), then route calls through the gateway:
```python theme={null}
from openai import OpenAI
import os
client = OpenAI(
base_url="https://app.memorylake.ai/openai/v1",
api_key=os.environ["MEMORYLAKE_API_KEY"],
)
def chat(user, message):
return client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": message}],
extra_query={"boundary_id": user.boundary_id}, # per-user memory scope
)
```
Each user's conversations read and write only their own memory — no retrieval code, no extraction pipeline, no schema. BYOK mode lets you keep your existing provider account and billing. See the [Memory Router quickstart](/features/memory-router/quickstart).
Memory Router is in private preview — contact [support@memorylake.ai](mailto:support@memorylake.ai) for access. The REST API path below is generally available.
## Path B: REST API — explicit memory operations
Model your tenancy — a workspace per tenant, an [actor](/features/memorylake/core-concepts/actors-and-memory) per end user, and a project per knowledge domain — then feed and query memory where it fits your flow:
```bash theme={null}
BASE="https://app.memorylake.ai/openapi/memorylake"
# Feed: open a conversation for the user, then append their messages.
# Facts are extracted from the exchange automatically.
curl -X POST "$BASE/api/v3/workspaces/$WORKSPACE_ID/memories/conversations" \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"project_id\": \"$PROJECT_ID\", \"actor_id\": \"$ACTOR_ID\"}"
# parent_message_id is null for the first message, then the id the previous append returned
curl -X POST "$BASE/api/v3/conversations/$CONVERSATION_ID/messages" \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"custom_id\": \"msg-001\", \"actor_id\": \"$ACTOR_ID\", \"parent_message_id\": null, \"content\": [{\"block_type\": \"TEXT\", \"text\": \"I am vegetarian and lactose intolerant\"}]}"
# Recall: one search spans document passages and extracted facts
curl -X POST "$BASE/api/v3/workspaces/$WORKSPACE_ID/memories/search" \
-H "Authorization: Bearer $MEMORYLAKE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "dietary restrictions"}'
```
The API also gives you what DIY memory stacks usually lack:
* **Documents**: upload files to the Library, import them into a project, and search their content alongside facts
* **Per-user memory**: actor facts follow a user across projects, so you don't rebuild identity plumbing
* **Traces**: see exactly where a memory came from — auditability for user-facing "why do you know this?"
* **Conflicts**: list and resolve contradictory memories programmatically instead of serving stale facts
* **Forget**: hard-delete a fact — straightforward GDPR "right to be forgotten" handling
Start with [Core Memory Operations](/features/memorylake/api-reference/core-memory/overview), which walks the whole flow end to end.
## Add Models, Skip Provider Accounts
Pair either path with [Model Router](/features/model-router/overview): one OpenAI-compatible endpoint (`https://app.memorylake.ai/v1`) covering mainstream models, with quota control, logs, and failover — the same `sk-…` key you already hold.
## Design Notes for Production
* **Scope per user, always**: one boundary (Router) or one project (API) per user prevents cross-user memory leakage by construction.
* **Recall selectively**: retrieval is scoped and ranked, but your prompt budget is yours — take the top results, not everything.
* **Surface memory to users**: expose "what I know about you" (list + trace) and "forget this" (delete). It builds trust and simplifies compliance.
* **Handle conflicts**: poll or review conflicting memories so your app never asserts two contradictory facts about a user.
## Go Deeper
Gateway architecture, BYOK, boundaries, observability.
Every endpoint: projects, documents, memories, search, conflicts.
# Memory for Coding Agents
Source: https://docs.memorylake.ai/scenarios/coding-agents
Make OpenClaw and other coding agents remember context, decisions, and files across sessions
## The Problem
Your coding agent forgets everything between sessions. Yesterday's architecture discussion, the library you agreed on, the CSV you analyzed together — gone. Every session restarts from zero, and long-lived projects suffer most.
## What MemoryLake Changes
The **memorylake-openclaw** plugin gives your agent three automatic behaviors, plus explicit tools:
| Behavior | What happens |
| - | - |
| **Auto-Recall** | The agent is instructed to retrieve relevant memories and document context before answering each of your messages. |
| **Auto-Capture** | After each turn, the conversation is analyzed server-side — durable facts are stored, updated, or merged (deduplicated, incremental). |
| **Auto-Upload** | Files you share in chat are uploaded to your project in the background, becoming searchable documents. |
The agent also gets explicit tools: `retrieve_context` (one call searches memories *and* documents, and surfaces memory conflicts), `memory_store`, `memory_list`, `memory_forget`, `document_download`, plus optional `advanced_web_search` and `open_data_search` for curated external datasets (arXiv, PubMed, SEC, FRED, USPTO, and more).
## Setup
In the [console](https://app.memorylake.ai), create an API key (**API Keys** in the sidebar) and note the project you want the agent to use. The console's **Integrations → OpenClaw** page generates the exact commands below pre-filled.
One-liner from the console (recommended — it configures everything):
```bash theme={null}
curl -fsSL https://app.memorylake.ai/memorylake-openclaw/install.sh | bash -s -- \
--project-id --api-key sk-... --host https://app.memorylake.ai
```
Or manually:
```bash theme={null}
openclaw plugins install memorylake-openclaw
openclaw gateway restart
```
then add to `~/.openclaw/openclaw.json`:
```json5 theme={null}
{
"plugins": {
"entries": {
"memorylake-openclaw": {
"enabled": true,
"config": {
"apiKey": "sk-...", // or "${MEMORYLAKE_API_KEY}"
"projectId": "",
"host": "https://app.memorylake.ai"
}
}
}
}
}
```
The install script sets `tools.profile` to `"full"` — the plugin's tools need it. A Windows PowerShell installer (`install.ps1`) and QClaw (`~/.qclaw/openclaw.json`) are supported the same way. Configuration hot-reloads: changing the key, project, or host takes effect without restarting the gateway.
Start a session and tell the agent something memorable, e.g. *"Remember: we deploy on Fridays only."* End the session, start a new one, and ask *"When do we deploy?"* — the agent recalls it via `retrieve_context`.
## Power Moves
### One agent, many clients — without memory bleed
Create a project per client, then drop a per-directory override in each working folder:
```json theme={null}
// {workspace}/.memorylake/config.json
{ "projectId": "" }
```
Sessions in that directory read and write only that client's memory. The bundled `agent-memorylake-config` skill sets this up conversationally.
### Bulk-load context
Feed the agent's memory directly from the command line — single files, directories, or archives (zip/tar/7z/rar auto-extracted):
```bash theme={null}
openclaw memorylake upload ./docs-archive.zip
openclaw memorylake search "authentication flow" --limit 10
openclaw memorylake stats
```
### Migrate existing history
The bundled `migrate-memories-to-memorylake` skill imports memories and conversation history from your agent's existing session files, so you don't start from zero.
### Controlled web access
`advanced_web_search` is registered as an **optional** tool (off unless you allow it) and respects plugin-level domain allowlists/blocklists — useful for enterprise environments that restrict agent browsing.
### Use MemoryLake models too
The separate **memorylake-models-openclaw** plugin registers MemoryLake's [Model Router](/features/model-router/overview) as a model provider — one `sk-…` key for both memory and models:
```bash theme={null}
openclaw plugins install memorylake-models-openclaw
openclaw memorylake setup # interactive: validates key, picks default model
```
## What This Feels Like Day to Day
* *"Continue the refactor"* — the agent recalls the module layout you agreed on two sessions ago.
* You drag a stack trace file into chat — it's auto-uploaded; next week the agent can still cite it.
* *"Why did we pick Postgres over MySQL?"* — answered from the decision memory captured when you made the call, with its source trace.
## Privacy & Telemetry
The plugin sends data only to your configured MemoryLake host. Usage telemetry is **opt-in** (disabled unless you explicitly set a telemetry key).
## Go Deeper
All ways to connect agents and apps, including MCP.
How extraction, conflicts, and traces work.
# Personal AI Memory
Source: https://docs.memorylake.ai/scenarios/personal-ai-memory
Give every AI tool you use one consistent, private memory of you
## The Problem
You use several AI tools a day — a chat assistant, a coding agent, maybe a research tool. Each one starts from zero: it doesn't know your preferences, your ongoing projects, or the file you uploaded yesterday *to a different tool*. You spend the first five minutes of every session re-explaining yourself.
## What MemoryLake Changes
Your personal workspace becomes the single memory all your AI tools share. Tell one assistant you prefer concise answers with code examples — every connected tool knows it. Upload your apartment lease once — any assistant can cite it later.
```text theme={null}
You ──┬── Playground chat ─────────┐
├── OpenClaw coding agent ───┼──► Your workspace's memory pool
├── File uploads & library ──┤ (extracted facts + indexed documents)
└── WPS / Lark connectors ───┘ │
▼
Recalled by every tool you connect
```
## Walkthrough
Start chatting at [app.memorylake.ai](https://app.memorylake.ai). Mention things worth keeping: *"I'm preparing for a marathon in November"*, *"My daughter is allergic to peanuts"*, *"I write Python, not JavaScript"*. MemoryLake extracts each durable fact as a [memory](/features/memorylake/memories/overview) — check the **Memories** page to see them, each with a source trace.
Create separate [projects](/features/memorylake/core-concepts/workspaces-and-projects) for contexts that shouldn't blend: "Health", "Home purchase", "Side project". Retrieval is project-scoped, so your mortgage documents never surface in a fitness conversation.
Upload files to your **Library** (drag-and-drop, folder structures preserved) or mount [WPS / Lark](/features/memorylake/connectors/overview) to browse existing cloud documents. Associate them with the right project — content becomes searchable context.
Install the [OpenClaw plugin](/features/memorylake/mcp-servers/overview) so your coding agent recalls your context automatically and captures new memories as you work. Files you hand the agent are auto-uploaded into your project.
When a new fact contradicts an old one ("I moved to Berlin" vs. "lives in Munich"), MemoryLake raises a **conflict** instead of guessing. Review conflicts in the project's Conflicts tab and pick what's true — your memory stays current, not cluttered.
## What This Feels Like Day to Day
* *"Plan my meals for next week"* → the assistant already knows the marathon training and the peanut allergy.
* *"Continue where we left off on the crawler"* → the coding agent recalls last week's design decision and the library you chose.
* *"What does my lease say about subletting?"* → answered with a citation to the document you uploaded months ago.
## Privacy Notes
* Your personal workspace is yours alone — nothing is shared unless you join a team space.
* Memories are inspectable and deletable: view any memory's source trace, edit it, or **forget** it permanently.
* API keys you create can be scoped with model restrictions and IP allowlists, and revoked anytime.
## Go Deeper
How extraction, search, traces, and conflicts work.
The full OpenClaw walkthrough.
# Team Knowledge Base
Source: https://docs.memorylake.ai/scenarios/team-knowledge-base
Turn scattered documents and decisions into governed organizational memory
## The Problem
Team knowledge lives in fragments: docs in five folders, decisions in chat threads, domain expertise in one senior colleague's head. New members ramp up slowly; when someone leaves, context leaves with them. Classic wikis rot because nobody maintains them.
## What MemoryLake Changes
A team space turns collective activity into **organizational memory** that maintains itself. Documents get parsed and indexed as they're added; conversations with the assistant distill into durable facts; contradictions surface as conflicts to resolve rather than silently coexisting. Every member's AI assistant answers with the team's full accumulated context — governed by roles and permissions.
## Walkthrough
Create a team in the console and invite colleagues by email or invite link (both inviter and invitee need verified email addresses). Assign [roles](/features/team-collaboration/roles-permissions): **Owner**, **Admin**, **Member** — or define custom roles for finer control.
Create a [workspace](/features/memorylake/core-concepts/workspaces-and-projects) per major domain — "Product", "Customer Success", "Legal" — or per client engagement. Members join workspaces automatically; each workspace holds its own projects, memories, and agents.
In each project, upload the documents that matter: specs, contracts, research, meeting notes. Folder uploads preserve structure; PDF, Office, Markdown, and images are all parsed and indexed. Existing knowledge in personal notes? The migration tooling in the agent plugin can import prior conversations and memories.
Beyond the three base roles, MemoryLake supports **per-resource scopes**: grant a contractor access to workspace A's "Vendor audit" project and nothing else. The [Permission Reference](/features/team-collaboration/permission-reference) lists every fine-grained capability — from `project:doc_read` to `project:mem_conflict_resolve`.
As members chat with the assistant and agents work in project context, MemoryLake extracts shared facts: *"We committed to SOC 2 by Q2"*, *"Customer X's contract renews March 15"*, *"The refund window is 30 days."* Everything carries a **source trace** — click any memory to see the conversation or document it came from.
When the pricing changes and someone tells the assistant the new numbers, the old memory doesn't linger silently — a **conflict** is raised. Whoever holds the `mem_conflict_resolve` permission reviews and resolves it. Organizational memory stays trustworthy because disagreement is visible.
Allocate per-member quotas so costs stay predictable, and use the team statistics page (member rankings, consumption trends, model usage) to see how the team actually uses AI.
## What This Feels Like Day to Day
* A new hire asks the assistant *"How do we handle enterprise refunds?"* and gets the current policy with a citation — no scavenger hunt, no bothering the one person who knows.
* An account manager preps for a renewal call: *"Summarize everything about Customer X"* pulls contract terms, past escalations, and the promise made in last quarter's QBR.
* The senior engineer leaves; their design rationale — extracted from months of project conversations — stays searchable.
## Governance Highlights
| Need | Mechanism |
| - | - |
| "Only leads can delete memories" | Role or custom role without `project:mem_delete` for others |
| "Contractor sees one project only" | Per-resource scope on that project |
| "Finance data stays in Finance" | Separate workspace; membership controls access |
| "Track who spends what" | Per-member quotas + team usage statistics |
| "Keys must not outlive employment" | API key permissions track their creator; disable on departure |
## Go Deeper
Roles, invitations, quotas, and analytics in detail.
Every fine-grained permission, explained.
# Create API Key
Source: https://docs.memorylake.ai/features/management-api/api-keys/create-api-key
Creates an API key and returns its full value once
```
POST /openapi/memorylake/admin/v1/api-keys
```
Creates an API key and returns its full value exactly once — save it immediately; read endpoints never return it again.
The new key carries the same authority as the key that created it, unless you issue it for a [virtual member](/features/management-api/members/create-member) with a narrower role.
**Permission required:** `service_account:create`
### Headers
Optional. Retrying with the same value replays the first result instead of creating a second key.
### Request Body
Display name (1–100 characters)
Expiry, Unix seconds. Omit or send 0 for a key that never expires.
Issue the key for a [virtual member](/features/management-api/members/create-member); the key then acts as that member, with its role and attribution. Only virtual members can be targeted — human members return `404`. Requires `member:manage_virtual` in addition to `service_account:create`.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/admin/v1/api-keys' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: 5f3a2b1c-9d8e-4f00-a1b2-c3d4e5f60789' \
-d '{"name": "ci-pipeline", "expires_at": 1786536000}'
```
### Response
Stable key identifier
Display name
Display prefix
The full API key, including the `sk-` prefix. **Save it now** — it is never shown again.
```json Success (201) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "313",
"name": "ci-pipeline",
"key_prefix": "a1b2c3d4",
"key": "sk-a1b2c3d4...redacted...e5f6"
}
}
```
# Get API Key
Source: https://docs.memorylake.ai/features/management-api/api-keys/get-api-key
Returns one API key's metadata
```
GET /openapi/memorylake/admin/v1/api-keys/{id}
```
Returns one key's metadata. Keys belonging to other teams — and identifiers that do not exist — are both reported as the same `404`.
**Permission required:** `service_account:read`
### Path Parameters
Key identifier
```bash cURL theme={null}
curl 'https://app.memorylake.ai/openapi/memorylake/admin/v1/api-keys/312' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
Returns an [API key object](/features/management-api/api-keys/list-api-keys) — metadata only, never the key value.
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "312",
"name": "ci-pipeline",
"key_prefix": "a1b2c3d4",
"status": "enabled",
"created_at": 1755000000
}
}
```
```json Not found (404) theme={null}
{
"success": false,
"message": "api key not found",
"error_code": "NOT_FOUND"
}
```
# List API Keys
Source: https://docs.memorylake.ai/features/management-api/api-keys/list-api-keys
Returns the team's API keys — metadata only, never the key value
```
GET /openapi/memorylake/admin/v1/api-keys
```
Lists the team's API keys. Callers holding only own-scope read permission see just the keys they created. Read endpoints never return the key value — only a display prefix.
**Permission required:** `service_account:read`
### Query Parameters
Items per page (1–100)
Token from the previous page. Opaque — do not construct or parse it.
Case-insensitive substring match on the key name
```bash cURL theme={null}
curl 'https://app.memorylake.ai/openapi/memorylake/admin/v1/api-keys?page_size=20' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
Stable key identifier
Display name
First characters of the key body — the full key is never returned by read endpoints
`enabled`, `disabled`, or `expired`
Creation time, Unix seconds
Expiry time, Unix seconds. Omitted when the key never expires.
Last use, Unix seconds. Approximate — may lag by up to one hour. Omitted when never used.
Total matching keys
Present when there is a next page
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"items": [
{
"id": "312",
"name": "ci-pipeline",
"key_prefix": "a1b2c3d4",
"status": "enabled",
"created_at": 1755000000,
"last_used_at": 1755600000
}
],
"total": 1
}
}
```
# Revoke API Key
Source: https://docs.memorylake.ai/features/management-api/api-keys/revoke-api-key
Deletes an API key permanently
```
DELETE /openapi/memorylake/admin/v1/api-keys/{id}
```
Deletes a key. It stops authenticating immediately and cannot be recovered.
The key used to make the request cannot revoke itself — an automation that cut off its own credential mid-run would have no way back in. Revoking the calling key returns `409 STATE_NOT_READY`.
**Permission required:** `service_account:delete`
### Path Parameters
Key identifier
### Headers
Optional. Retrying with the same value replays the first result.
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/admin/v1/api-keys/312' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {}
}
```
```json Revoking the calling key (409) theme={null}
{
"success": false,
"message": "cannot revoke the key used for this request",
"error_code": "STATE_NOT_READY"
}
```
# Rotate API Key
Source: https://docs.memorylake.ai/features/management-api/api-keys/rotate-api-key
Replaces the key material and returns the new value once
```
POST /openapi/memorylake/admin/v1/api-keys/{id}/rotate
```
Replaces the key material. The previous value stops working immediately; the new value is returned once.
Rotation is not naturally idempotent: every call mints a new key and kills the previous one. When retrying over an unreliable network, always send an `Idempotency-Key` — a blind retry would invalidate the key you just received.
**Permission required:** `service_account:update`
### Path Parameters
Key identifier
### Headers
Optional but recommended. Retrying with the same value replays the first result — it does not mint a second key.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/admin/v1/api-keys/312/rotate' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Idempotency-Key: 7c1d2e3f-0a9b-4c8d-b7e6-f5a4d3c2b1a0'
```
### Response
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "312",
"name": "ci-pipeline",
"key_prefix": "f6e5d4c3",
"key": "sk-f6e5d4c3...redacted...b2a1"
}
}
```
# Invite Someone
Source: https://docs.memorylake.ai/features/management-api/invitations/create-invitation
Creates an invitation and emails the invitee
```
POST /openapi/memorylake/admin/v1/invitations
```
Creates an invitation and sends the invitee an email with an accept link. The link expires after 7 days.
One live invitation per email per team: if a pending one already exists, this returns `409` — revoke it first to re-invite. There is no resend endpoint; **re-invite = revoke + create** (the same email reactivates the same invitation with a fresh link).
Invitation creation is capped per team per UTC day (default 50, counting created invitations). On exceed you get `429` with a `Retry-After` header.
**Permission required:** `member:invite`
### Headers
Optional. Retrying with the same value replays the first result instead of sending a second email.
### Request Body
Invitee email — a bare address, no display name
Role on acceptance: `tenant_admin`, `tenant_member`, or a custom role key. The owner role cannot be invited.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/admin/v1/invitations' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Content-Type: application/json' \
-d '{"email": "bob@example.com", "role": "tenant_member"}'
```
### Response
Stable invitation identifier
Invitee email (normalised to lowercase)
Role the invitee will hold on acceptance
`pending`, `accepted`, `rejected`, `expired`, or `revoked`
First invitation time, Unix seconds. Re-inviting reactivates the same invitation, so this does not reset.
Expiry of the current email link, Unix seconds
Most recent invitation email time, Unix seconds
Acceptance time — present only when accepted
The member this invitation produced — present only when accepted
```json Success (201) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "88",
"email": "bob@example.com",
"role": "tenant_member",
"status": "pending",
"created_at": 1756300000,
"expires_at": 1756904800,
"last_invited_at": 1756300000
}
}
```
```json Already invited or already a member (409) theme={null}
{
"success": false,
"message": "a pending invitation for this email already exists; revoke it to re-invite",
"error_code": "CUSTOM_ID_CONFLICT"
}
```
# List Invitations
Source: https://docs.memorylake.ai/features/management-api/invitations/list-invitations
Returns the team's invitations, newest first
```
GET /openapi/memorylake/admin/v1/invitations
```
Lists the team's invitations, newest first, optionally filtered by state.
**Permission required:** `member:invite`
### Query Parameters
Items per page (1–100)
Token from the previous page
Filter by state: `pending`, `accepted`, `rejected`, `expired`, or `revoked`. A pending invitation whose link has lapsed reads as `expired`.
```bash cURL theme={null}
curl 'https://app.memorylake.ai/openapi/memorylake/admin/v1/invitations?status=pending' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
[Invitation objects](/features/management-api/invitations/create-invitation)
Total matching invitations
Present when there is a next page
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"items": [
{
"id": "88",
"email": "bob@example.com",
"role": "tenant_member",
"status": "pending",
"created_at": 1756300000,
"expires_at": 1756904800,
"last_invited_at": 1756300000
}
],
"total": 1
}
}
```
# Revoke Invitation
Source: https://docs.memorylake.ai/features/management-api/invitations/revoke-invitation
Revokes a pending invitation — its email link stops working
```
DELETE /openapi/memorylake/admin/v1/invitations/{id}
```
Revokes a **pending** invitation; the accept link in the email stops working immediately. The invitation stays in the list as history with status `revoked`, and the same email can be re-invited afterwards.
Accepted invitations cannot be revoked — the member already exists; [remove the member](/features/management-api/members/remove-member) instead. Expired and rejected ones are already inert. All of these return `409`.
**Permission required:** `member:invite`
### Path Parameters
Invitation identifier
### Headers
Optional. Retrying with the same value replays the first result.
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/admin/v1/invitations/88' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {}
}
```
```json Not pending (409) theme={null}
{
"success": false,
"message": "only a pending invitation can be revoked",
"error_code": "STATE_NOT_READY"
}
```
# Create Virtual Member
Source: https://docs.memorylake.ai/features/management-api/members/create-member
Creates a virtual member — a login-less managed identity
```
POST /openapi/memorylake/admin/v1/members
```
Creates a **virtual member**: a managed identity with no email and no console access. It appears in the roster, holds a role, and acts only through API keys issued for it ([Create API Key](/features/management-api/api-keys/create-api-key) with `member_principal_id`). Memories and conversations produced through those keys are attributed to the virtual member.
Human members cannot be created here — they join through [invitations](/features/management-api/invitations/create-invitation) only.
**Permission required:** `member:manage_virtual` (team owners and admins by default)
### Headers
Optional. Retrying with the same value replays the first result.
### Request Body
Display name (1–20 characters)
Role: `tenant_admin`, `tenant_member`, or a custom role key of this team. The owner role cannot be assigned.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/admin/v1/members' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Content-Type: application/json' \
-d '{"display_name": "Support Bot", "role": "tenant_member"}'
```
### Response
Returns a [Member object](/features/management-api/members/list-members) with `member_type: "virtual"`.
```json Success (201) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"principal_id": "9f2c1a7b3d5e4f60a1b2c3d4e5f60718",
"display_name": "Support Bot",
"member_type": "virtual",
"role": "tenant_member",
"joined_at": 1756300000,
"status": "active",
"used_tokens": 0
}
}
```
### Issuing a key for a virtual member
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/admin/v1/api-keys' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Content-Type: application/json' \
-d '{"name": "support-bot-key", "member_principal_id": "9f2c1a7b3d5e4f60a1b2c3d4e5f60718"}'
```
The key acts **as the virtual member** — with its role, and with attribution to its identity. Only virtual members can be targeted; requesting a human member's `principal_id` returns the same `404` as an unknown one, so keys can never impersonate a colleague. Removing a virtual member disables its keys.
# List Members
Source: https://docs.memorylake.ai/features/management-api/members/list-members
Returns the team roster
```
GET /openapi/memorylake/admin/v1/members
```
Lists the team's members. Any member's key may read the roster; contact details (`email`, `username`) are returned only when the key's creator is a team owner or admin.
### Query Parameters
Items per page (1–100)
Token from the previous page
Case-insensitive substring match on the display name. For owners and admins it also matches email and username.
```bash cURL theme={null}
curl 'https://app.memorylake.ai/openapi/memorylake/admin/v1/members' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
Stable member identifier — used in member write endpoints and matching the team's `owner_principal_id`
Display name
`human` (joined via invitation) or `virtual` (managed identity created by an owner/admin — see [Create Virtual Member](/features/management-api/members/create-member))
`tenant_owner`, `tenant_admin`, `tenant_member`, or a custom role key
Only returned to owners and admins
Only returned to owners and admins
Join time, Unix seconds
`active` or `inactive`
Tokens consumed by this member
Per-member cap in tokens. Omitted when uncapped.
Total members
Present when there is a next page
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"items": [
{
"principal_id": "32bc58d62b5c4a05a069d5d083f4dd72",
"display_name": "Alice",
"role": "tenant_owner",
"email": "alice@example.com",
"username": "alice",
"joined_at": 1750000000,
"status": "active",
"used_tokens": 1284000
}
],
"total": 1
}
}
```
# Remove Member
Source: https://docs.memorylake.ai/features/management-api/members/remove-member
Removes a member from the team
```
DELETE /openapi/memorylake/admin/v1/members/{principal_id}
```
Removes a member. Their API keys in this team are **disabled** (not deleted), so an admin can review or re-issue them from the console.
Guard rails: the team owner cannot be removed, and the calling key cannot remove its own creator (both `409`).
**Permission required:** `member:remove`
### Path Parameters
Member identifier from the [members list](/features/management-api/members/list-members)
### Headers
Optional. Retrying with the same value replays the first result.
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/admin/v1/members/9f2c1a7b3d5e4f60a1b2c3d4e5f60718' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {}
}
```
```json Removing the owner (409) theme={null}
{
"success": false,
"message": "cannot remove the team owner",
"error_code": "STATE_NOT_READY"
}
```
# Update Member Role
Source: https://docs.memorylake.ai/features/management-api/members/update-member
Changes a member's role
```
PATCH /openapi/memorylake/admin/v1/members/{principal_id}
```
Changes a member's role. Guard rails:
* the `tenant_owner` role cannot be assigned here — ownership transfer stays in the console (`400`)
* the owner's own role cannot be changed (`409`)
* the calling key cannot change **its creator's** role — self-demotion would sever the automation's own authorization mid-run (`409`)
**Permission required:** `member:change_role`
### Path Parameters
Member identifier from the [members list](/features/management-api/members/list-members)
### Headers
Optional. Retrying with the same value replays the first result.
### Request Body
New role: `tenant_admin`, `tenant_member`, or a custom role key of this team
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/admin/v1/members/9f2c1a7b3d5e4f60a1b2c3d4e5f60718' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Content-Type: application/json' \
-d '{"role": "tenant_admin"}'
```
### Response
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {}
}
```
```json Changing the owner's role (409) theme={null}
{
"success": false,
"message": "cannot change the owner's role",
"error_code": "STATE_NOT_READY"
}
```
# Management API Reference
Source: https://docs.memorylake.ai/features/management-api/overview
Govern your team programmatically — members, invitations, API keys, team info and usage
## API Overview
The Management API lets you automate the operations you would otherwise perform in the console's team pages — inviting members, changing roles, issuing and rotating API keys, and reading usage — without a browser session. Use it for onboarding/offboarding automation, key-rotation pipelines, and usage reporting.
## API Sections
Read team info and rename the team (owner only).
List, create, rotate and revoke API keys — read endpoints never return the key value.
Read the roster, change roles, remove members.
Invite by email, list invitations, revoke pending ones.
Quota snapshot and per-model consumption over a period.
**Deliberately not available:** creating or deleting teams, transferring ownership, and changing billing — these remain console-only, human-confirmed operations.
## Usage Notes
Response format, pagination and error codes are covered in [Overview](/features/memorylake/api-reference/overview) and [Errors](/features/memorylake/api-reference/errors). Three things are worth knowing about these endpoints:
### Permissions
Endpoints document their required permission as `resource:action` (for example `member:invite`). The key acts with its creator's role — a key created by a team admin can do what that admin can do. If the creator loses a permission (or leaves the team), their keys lose it too. A key that authenticates but lacks the permission gets `403` with `ACCESS_DENIED`.
### Idempotency
Write endpoints accept an optional `Idempotency-Key` header (any unique string, e.g. a UUID). Retrying with the same value replays the first result instead of repeating the side effect — for key rotation this is the difference between "got the same new key again" and "invalidated the key I just saved". Replays carry an `Idempotency-Replayed: true` response header. Rate-limit rejections (429) are never replayed, so a backoff-and-retry loop works with a stable key.
### Rate Limits
| Limit | Scope | On exceed |
| - | - | - |
| 60 requests / minute | per key | `429` with `Retry-After` |
| 50 invitations / day (UTC) | per team, counting created invitations | `429` with `Retry-After` |
## Next Steps
Start with GET /team — read your team and your key's role
Obtain an API key and make your first request
# Get Team
Source: https://docs.memorylake.ai/features/management-api/team/get-team
Returns the team this key belongs to
```
GET /openapi/memorylake/admin/v1/team
```
Returns the team the calling key is bound to. There is no team parameter — the key determines the team. Any member's key may read this.
```bash cURL theme={null}
curl 'https://app.memorylake.ai/openapi/memorylake/admin/v1/team' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
Stable team identifier
Display name
`personal` (single-user space) or `org` (team with members)
`principal_id` of the team owner — joins to the members list
Creation time, Unix seconds
The calling key's role: `tenant_owner`, `tenant_admin`, `tenant_member`, or a custom role key
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "74be678f61e34ace95530080a6562bfa",
"name": "Acme Research",
"type": "org",
"owner_principal_id": "32bc58d62b5c4a05a069d5d083f4dd72",
"created_at": 1755000000,
"caller_role": "tenant_owner"
}
}
```
# Rename Team
Source: https://docs.memorylake.ai/features/management-api/team/update-team
Updates the team's display name — owner only
```
PATCH /openapi/memorylake/admin/v1/team
```
Updates the team's display name. Only the **team owner** may do this — the same rule the console applies. Ownership transfer and team deletion are not available through this API.
**Permission required:** team owner (role check, not a grantable permission)
### Request Body
New display name (1–200 characters)
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/admin/v1/team' \
-H 'Authorization: Bearer sk-xxxxxx' \
-H 'Content-Type: application/json' \
-d '{"name": "Acme Research EU"}'
```
### Response
Returns the updated [Team object](/features/management-api/team/get-team).
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "74be678f61e34ace95530080a6562bfa",
"name": "Acme Research EU",
"type": "org",
"owner_principal_id": "32bc58d62b5c4a05a069d5d083f4dd72",
"created_at": 1755000000,
"caller_role": "tenant_owner"
}
}
```
```json Not the owner (403) theme={null}
{
"success": false,
"message": "permission denied",
"error_code": "ACCESS_DENIED"
}
```
# Get Usage
Source: https://docs.memorylake.ai/features/management-api/usage/get-usage
Quota snapshot and per-model consumption over a period
```
GET /openapi/memorylake/admin/v1/usage
```
Returns the team's quota and consumption. Two different time semantics in one response:
* `quota` is an **account-level snapshot taken now** — what the team can still spend
* `totals` and `by_model` are **aggregates over the requested period**
**Permission required:** `usage:view_all`
### Query Parameters
First day included, `YYYY-MM-DD`. Defaults to 6 days before `end_date`.
Last day included, `YYYY-MM-DD`. Defaults to today. The window may span at most 92 days.
```bash cURL theme={null}
curl 'https://app.memorylake.ai/openapi/memorylake/admin/v1/usage?start_date=2026-08-01&end_date=2026-08-26' \
-H 'Authorization: Bearer sk-xxxxxx'
```
### Response
The period the totals cover (`start_date`, `end_date`)
Currently available tokens. Account-level snapshot, not scoped to the period.
When true, `available_tokens` is not meaningful
Aggregate `requests`, `prompt_tokens`, `completion_tokens` over the period
Per-model breakdown. Entries may name a platform metering operation (`files_process`, `memory_input`, `retrieval_call`, `search_call`) rather than an LLM — those are real billable operations.
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"period": { "start_date": "2026-08-01", "end_date": "2026-08-26" },
"quota": { "available_tokens": 8421000, "unlimited": false },
"totals": { "requests": 1204, "prompt_tokens": 3210000, "completion_tokens": 1150000 },
"by_model": [
{ "model": "claude-sonnet-5", "requests": 800, "prompt_tokens": 2400000, "completion_tokens": 900000 },
{ "model": "memory_input", "requests": 404, "prompt_tokens": 810000, "completion_tokens": 250000 }
]
}
}
```
# Bind Agent to Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/bind-agent
Bind an agent to a workspace to enable A2A communication
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/agents
```
Binds an existing agent to the specified workspace. Once bound, the agent becomes available for A2A (Agent-to-Agent) communication and task execution within the workspace. An agent can be bound to multiple workspaces.
**Permission required:** `workspace_agent:create`
### Path Parameters
Workspace identifier
### Request Body
Identifier of the agent to bind to the workspace
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f"
}'
```
### Response
Agent name
Agent identifier
Custom identifier for external system integration
Latest version number of the agent
Timestamp when the agent was bound to the workspace
```json Success (200) theme={null}
{
"success": true,
"data": {
"name": "Support Assistant",
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"custom_id": "support-assistant-v1",
"latest_version": 3,
"bound_at": "2025-04-01T08:00:00Z"
}
}
```
# Create Agent Version
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/create-agent-version
Create a new version of an agent with updated configuration
```
POST /openapi/memorylake/api/v3/agents/{id}/versions
```
Creates a new version of the specified agent. The new version uses merge semantics: only the fields you supply override the previous version's values. Omitted fields carry forward from the current version unchanged.
This is how you update an agent's model, capabilities, policies, subagents, skills, system prompt, and other configuration. The agent's `version` field automatically advances to the newly created version.
**Permission required:** `agent:modify`
### Path Parameters
Agent identifier
### Request Body
All fields are optional. Only supplied fields override the previous version.
Model to use for this version
Updated list of capability identifiers
Updated execution policies
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Updated output configuration
Output mode (`text` or `json`)
JSON Schema that the agent's output must conform to when mode is `json`
Updated subagent definitions
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Updated skill references
Skill identifier
Skill version number
Updated system prompt
Updated model-specific settings
Updated runtime binding configuration
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/versions' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 25,
"max_tool_calls": 15
},
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 3
}
],
"model_settings": {
"temperature": 0.5,
"max_tokens": 8192
}
}'
```
### Response
Version number of the newly created version
Model used in this version
List of capability identifiers
Execution policies for this version
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for this version
Output mode
JSON Schema for structured output
Subagent definitions in this version
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills in this version
Skill identifier
Skill version number
Parent agent identifier
System prompt used in this version
Model-specific settings for this version
Runtime binding configuration for this version
Version creation timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"version": 4,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 25,
"max_tool_calls": 15,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "delegate",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 3
}
],
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.5,
"max_tokens": 8192
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-05-15T10:00:00Z"
}
}
```
# Delete Agent
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/delete-agent
Permanently delete an agent and all its versions
```
DELETE /openapi/memorylake/api/v3/agents/{id}
```
This is a destructive operation. The agent and all its versions are permanently removed. Any workspace bindings for this agent are also deleted.
Permanently deletes an agent. This action cannot be undone.
**Permission required:** `agent:delete`
### Path Parameters
Agent identifier
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents/agt_r8k2m1n3' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Returns an empty `data` field on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Get Agent Version
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/get-agent-version
Retrieve a specific version of an agent
```
GET /openapi/memorylake/api/v3/agents/{id}/versions/{version}
```
Retrieves a single version of the specified agent. Use this to inspect the configuration snapshot for any historical or current version.
**Permission required:** `agent:read`
### Path Parameters
Agent identifier
Version number to retrieve
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/versions/3' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Version number
Model used in this version
List of capability identifiers
Execution policies for this version
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for this version
Output mode
JSON Schema for structured output
Subagent definitions in this version
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills in this version
Skill identifier
Skill version number
Parent agent identifier
System prompt used in this version
Model-specific settings for this version
Runtime binding configuration for this version
Version creation timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"version": 3,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "delegate",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 2
}
],
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-04-22T14:30:00Z"
}
}
```
# List Agent Versions
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/list-agent-versions
Returns a paginated list of versions for a specific agent
```
GET /openapi/memorylake/api/v3/agents/{id}/versions
```
Returns a paginated list of all versions for the specified agent, ordered by version number. Each version captures a snapshot of the agent's configuration at the time it was created.
**Permission required:** `agent:read`
### Path Parameters
Agent identifier
### Query Parameters
Number of versions to return per page
Token from a previous response to fetch the next page of results
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents/agent-f8bf71ab17ed8eccad8c0e8ae708273f/versions?page_size=10' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of agent version objects
Version number
Model used in this version
List of capability identifiers
Execution policies for this version
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for this version
Output mode
JSON Schema for structured output
Subagent definitions in this version
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills in this version
Skill identifier
Skill version number
Parent agent identifier
System prompt used in this version
Model-specific settings for this version
Runtime binding configuration for this version
Version creation timestamp
Token to retrieve the next page of results. Absent when there are no more pages.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"version": 3,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "delegate",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 2
}
],
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-04-22T14:30:00Z"
},
{
"version": 2,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read"],
"policies": {
"max_turns": 15,
"max_tool_calls": 8,
"allow_tools": ["search_kb"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 2
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 1
}
],
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"system_prompt": "You are a helpful support assistant.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 2048
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-03-25T11:00:00Z"
}
],
"continuation_token": null
}
}
```
# List Workspace Agents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/list-workspace-agents
Returns a paginated list of agents bound to a workspace
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/agents
```
Returns a paginated list of all agents that are bound to the specified workspace. Bound agents are available for A2A communication and task execution within the workspace.
**Permission required:** `workspace_agent:read` — rows you cannot open are left out of the list rather than the list being refused
### Path Parameters
Workspace identifier
### Query Parameters
Number of agent bindings to return per page
Token from a previous response to fetch the next page of results
Fuzzy search by agent name
Filter by whether the platform hosts the agent's runtime. Omit to get both. A binding whose agent no longer has a record has no type and is left out of a filtered page, the same way the name filter leaves it out
Filter by whether the agent still exists. Omit to get both
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of agent binding objects
Agent name
Agent identifier
Custom identifier for external system integration
Latest version number of the agent
Timestamp when the agent was bound to the workspace
Token to retrieve the next page of results. Absent when there are no more pages.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"name": "Support Assistant",
"agent_id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"custom_id": "support-assistant-v1",
"latest_version": 3,
"bound_at": "2025-04-01T08:00:00Z"
},
{
"name": "Research Agent",
"agent_id": "agent-e86c40e11be2c2024ebfc9e19d8fe371",
"custom_id": "research-agent-v1",
"latest_version": 1,
"bound_at": "2025-04-10T15:30:00Z"
}
],
"continuation_token": null
}
}
```
# Unbind Agent from Workspace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/unbind-agent
Remove an agent binding from a workspace
```
DELETE /openapi/memorylake/api/v3/workspaces/{workspaceId}/agents/{agentId}
```
Removes the binding between an agent and a workspace. After unbinding, the agent is no longer available for A2A communication within the workspace. The agent definition itself is not deleted.
**Permission required:** `workspace_agent:delete`
### Path Parameters
Workspace identifier
Agent identifier to unbind from the workspace
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/agents/agt_r8k2m1n3' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Returns an empty `data` field on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Update Agent
Source: https://docs.memorylake.ai/features/memorylake/api-reference/agents/update-agent
Update an agent's identity fields such as name, description, and metadata
```
PATCH /openapi/memorylake/api/v3/agents/{id}
```
Updates an existing agent's identity fields. Only the fields you include in the request body are modified; omitted fields remain unchanged.
This endpoint updates identity fields only (name, description, metadata). To change the agent's model, capabilities, policies, or other configuration, create a new version with the [Create Agent Version](/features/memorylake/api-reference/agents/create-agent-version) endpoint.
**Permission required:** `agent:modify`
### Path Parameters
Agent identifier
### Request Body
Updated agent name
Updated agent description
Updated key-value pairs. Replaces the existing metadata entirely.
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/api/v3/agents/agt_r8k2m1n3' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "Support Assistant (Production)",
"description": "Production support agent with knowledge base integration"
}'
```
### Response
Unique agent identifier
Updated agent name
Updated agent description
Arbitrary key-value pairs for storing additional agent information
Current active version number
Model used by the agent
List of capability identifiers the agent supports
Execution policies that constrain agent behavior
Maximum number of conversation turns per run
Maximum number of tool calls per turn
Allowlist of tool names the agent may invoke
Denylist of tool names the agent must not invoke
Maximum seconds a subagent may run before being cancelled
Maximum number of subagents that may run concurrently
Output configuration for the agent
Output mode
JSON Schema for structured output
Subagent definitions attached to this agent
Subagent name
Execution mode for the subagent
Context instructions passed to the subagent
Whether the subagent inherits the parent agent's tools
Skills attached to this agent
Skill identifier
Skill version number
Custom identifier for external system integration
Actor identifier associated with this agent
Latest version number available for this agent
System prompt used to instruct the agent
Model-specific settings such as temperature and max tokens
Runtime binding configuration for tools and data sources
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "agent-f8bf71ab17ed8eccad8c0e8ae708273f",
"name": "Support Assistant (Production)",
"description": "Production support agent with knowledge base integration",
"metadata": {
"team": "customer-success",
"tier": "production"
},
"version": 3,
"model": "gpt-4o",
"capabilities": ["tool_use", "memory_read", "memory_write"],
"policies": {
"max_turns": 20,
"max_tool_calls": 10,
"allow_tools": ["search_kb", "create_ticket"],
"deny_tools": [],
"subagent_timeout": 300,
"subagent_max_concurrency": 3
},
"output": {
"mode": "text",
"json_schema": null
},
"subagents": [
{
"name": "ticket-creator",
"mode": "delegate",
"context": "Create support tickets from conversation context",
"inherit_tools": false
}
],
"skills": [
{
"skill_id": "skl_kb_search",
"skill_version": 2
}
],
"custom_id": "support-assistant-v1",
"actor_id": "actor-9ad7a492416c6a8197f42a64b0a4a2d2",
"latest_version": 3,
"system_prompt": "You are a helpful support assistant. Use the knowledge base to answer questions accurately.",
"model_settings": {
"temperature": 0.7,
"max_tokens": 4096
},
"runtime_bindings": {
"knowledge_base": "kb_prod_docs"
},
"created_at": "2025-03-10T09:00:00Z",
"updated_at": "2025-05-01T11:45:00Z"
}
}
```
# Error Codes & Handling
Source: https://docs.memorylake.ai/features/memorylake/api-reference/errors
Understand and handle API errors
## HTTP Status Codes
| Status | Meaning | Common Causes |
| - | - | - |
| 200 | Success | Request completed successfully |
| 400 | Bad Request | Invalid parameters or malformed request |
| 401 | Unauthorized | Missing or invalid API key |
| 402 | Payment Required | Insufficient quota for this operation |
| 403 | Forbidden | Valid auth but insufficient permissions |
| 404 | Not Found | Resource doesn't exist |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server-side error |
## Error Response
When a request fails, the API returns a structured error body alongside the HTTP status code. The `error_code` field identifies the specific error for programmatic handling:
```json theme={null}
{
"success": false,
"message": "Human-readable error description",
"error_code": "ERROR_CODE"
}
```
## What a 403 tells you
A permission refusal carries more than the code. Alongside `error_code: ACCESS_DENIED`, the `data`
object names the permission that was missing and what would have satisfied it, so you can act on the
response without guessing:
```json theme={null}
{
"success": false,
"message": "You don't have the \"Modify Library Item\" permission. Ask a team owner or admin to grant it.",
"error_code": "ACCESS_DENIED",
"data": {
"denied": [
{
"permission": "drive:item_modify",
"permission_level": "service",
"resource_type": "drive"
}
],
"stage": "capability",
"required_any_of": [
{ "key": "pkg:library:write", "resource_type": "library" }
]
}
}
```
The permissions that were checked and not held. `permission` is the identifier to grant,
`permission_level` says whether it is granted once for the whole service or per resource instance.
Which request to make of your admin. `capability` — ask for the permission itself; you do not have
it anywhere, so widening your access to this one resource will not help. `instance` — ask for access
to this resource; you already hold the permission elsewhere.
Any one of these grants would have allowed the request. Hand this to whoever administers your
team: it is the shortest answer to "what do I need".
A refusal does not tell you whether the resource exists — a `403` on a read means "not for you"
and says nothing more. Deleting is the exception: it answers `200` whether the resource was
removed or was never there, so a repeated delete is safe to retry.
## Error Codes
| Error Code | Description |
| - | - |
| `NOT_FOUND` | Resource not found |
| `DRIVE_ITEM_CONFLICT` | Drive item name conflict, e.g. file or folder with the same name already exists |
| `INVALID_ARGUMENT` | Invalid input: parameter validation, type mismatch, or malformed body |
| `CONNECTOR_NOT_LINKED` | Third-party connector (WPS, Lark, etc.) not yet authorized |
| `STATE_NOT_READY` | Resource exists but its current state does not allow the operation |
| `ACCESS_DENIED` | Caller lacks permission to access the resource |
| `QUOTA_EXCEEDED` | Quota or usage limit exceeded |
| `DATASET_TABLE_LIMIT_EXCEEDED` | Number of tables in the NL2SQL dataset exceeds the allowed limit |
| `DOWNLOAD_NOT_SUPPORTED` | The requested resource does not support download |
| `UNAUTHORIZE` | Authentication required |
| `CONNECTOR_UNAUTHORIZE` | Connector unauthorized |
| `CUSTOM_ID_CONFLICT` | A resource with the given `custom_id` already exists |
| `BINDING_ALREADY_EXISTS` | The binding relationship already exists |
| `INTERNAL_ERROR` | Unexpected server-side error |
## Error Handling Best Practices
### Retry Logic
```javascript theme={null}
async function apiRequest(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) {
return await response.json();
}
// Don't retry 4xx errors (except 429)
if (response.status >= 400 && response.status < 500 && response.status !== 429) {
throw new Error(`Client error: ${response.status}`);
}
// Exponential backoff for 5xx and 429
if (i < maxRetries - 1) {
await sleep(Math.pow(2, i) * 1000);
continue;
}
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}
```
### Error Logging
```javascript theme={null}
try {
const data = await apiRequest(url, options);
return data;
} catch (error) {
console.error('API Error:', {
url,
status: error.status,
message: error.message,
timestamp: new Date().toISOString()
});
throw error;
}
```
## Next Steps
Learn about authentication
Understand rate limiting
# Batch Forget Facts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/batch-forget-facts
Mark multiple facts as forgotten in a single request
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts/forget
```
Marks multiple facts as forgotten (expired) in a single request. Like [Forget Fact](/features/memorylake/api-reference/facts/forget-fact), this is a soft delete -- facts remain available for audit purposes but are excluded from future retrievals and searches.
**Permission required:** `project:mem_delete`
### Path Parameters
Workspace ID
Project ID
### Request Body
Array of fact IDs to forget
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/projects/proj_a1b2c3d4e5f6/memories/facts/forget' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
"fact-2fe07aee0058d141c744685a2d7272be",
"fact-044bdc2ffcf8c7915aa9e79d5a10efd4",
"fact_7g9h0i1j2k3l"
]
}'
```
### Response
Returns an empty `data` object on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Forget Fact
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/forget-fact
Mark a fact as forgotten without deleting it
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts/{factId}/forget
```
Marks a fact as forgotten (expired) without permanently deleting it. The fact remains available for audit purposes but is excluded from future retrievals and searches. To forget multiple facts at once, use [Batch Forget Facts](/features/memorylake/api-reference/facts/batch-forget-facts).
**Permission required:** `project:mem_delete`
### Path Parameters
Workspace ID
Project ID
Fact ID to forget
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/projects/proj_a1b2c3d4e5f6/memories/facts/fact-2fe07aee0058d141c744685a2d7272be/forget' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Returns an empty `data` object on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Get Fact
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/get-fact
Returns the content and metadata of a single fact
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts/{factId}
```
Returns the content and metadata of a single fact in a project.
**Permission required:** `project:mem_read`
### Path Parameters
Workspace ID
Project ID
Fact ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/projects/proj_a1b2c3d4e5f6/memories/facts/fact_8f3a1b2c4d5e' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
Relevance score
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "fact-2fe07aee0058d141c744685a2d7272be",
"fact": "User prefers dark mode in all applications",
"metadata": {
"category": "preferences",
"confidence": "high"
},
"expired": false,
"score": 0.95,
"expiration_date": null,
"created_at": "2025-06-10T14:30:00Z",
"updated_at": "2025-06-10T14:30:00Z"
}
}
```
# List Facts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/list-facts
Returns a paginated list of facts in a project
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts
```
Returns a paginated list of facts stored in a project. Facts are structured pieces of knowledge automatically extracted from conversations. You can filter facts by content with `fact_fuzzy`.
**Permission required:** `project:mem_read`
### Path Parameters
Workspace ID
Project ID
### Query Parameters
Number of facts to return per page. Range: 1–200.
Token from a previous response to fetch the next page of results
Filter facts by content substring
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/projects/proj_a1b2c3d4e5f6/memories/facts?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of fact objects
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
Relevance score
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
Token to retrieve the next page. `null` when there are no more results.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "fact-2fe07aee0058d141c744685a2d7272be",
"fact": "User prefers dark mode in all applications",
"metadata": {
"category": "preferences",
"confidence": "high"
},
"expired": false,
"score": 0.95,
"expiration_date": null,
"created_at": "2025-06-10T14:30:00Z",
"updated_at": "2025-06-10T14:30:00Z"
},
{
"id": "fact-044bdc2ffcf8c7915aa9e79d5a10efd4",
"fact": "User is based in San Francisco timezone (PST/PDT)",
"metadata": {
"category": "location"
},
"expired": false,
"score": 0.88,
"expiration_date": "2026-06-10T14:30:00Z",
"created_at": "2025-06-12T09:15:00Z",
"updated_at": "2025-06-12T09:15:00Z"
}
],
"continuation_token": "eyJsYXN0X2lkIjoiZmFjdF8yZDRlNmY4YTBiMWMifQ"
}
}
```
# Update Fact
Source: https://docs.memorylake.ai/features/memorylake/api-reference/facts/update-fact
Update the text or metadata of an existing fact
```
PATCH /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/facts/{factId}
```
Updates the text or metadata of an existing fact in a project. You can modify the fact content, its metadata, or both.
**Permission required:** `project:mem_modify`
### Path Parameters
Workspace ID
Project ID
Fact ID
### Request Body
Updated fact text
Updated key-value metadata to attach to the fact
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-fe314186ccd18cde04d6af48a5afd79f/projects/proj_a1b2c3d4e5f6/memories/facts/fact_8f3a1b2c4d5e' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"fact": "User prefers dark mode in all applications and IDEs",
"metadata": {
"category": "preferences",
"confidence": "high",
"verified": true
}
}'
```
### Response
Unique fact identifier
The fact text
Arbitrary key-value metadata attached to the fact
Whether the fact has been forgotten
Relevance score
Scheduled expiration date, or `null` if the fact does not expire
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "fact-2fe07aee0058d141c744685a2d7272be",
"fact": "User prefers dark mode in all applications and IDEs",
"metadata": {
"category": "preferences",
"confidence": "high",
"verified": true
},
"expired": false,
"score": 0.95,
"expiration_date": null,
"created_at": "2025-06-10T14:30:00Z",
"updated_at": "2025-06-20T11:45:00Z"
}
}
```
# Add Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/add-document
Import one or more Library files into a project as documents
```
POST /openapi/memorylake/api/v1/projects/{id}/documents
```
Imports files from the user's Library into a project. Each imported file becomes a project document and is queued for processing immediately. The operation is batch and supports **partial success** — the response tells you how many imports succeeded and how many failed.
**Permission required:** `project:doc_add` on the project, and `drive:item_read` on the library item being imported.
You can pass either **file** or **directory** IDs in `drive_item_ids`. Directories are recursively flattened to every descendant file before import, so importing a folder effectively imports its whole subtree in one call. Unsupported item types inside a directory are silently skipped.
For convenience, `drive_item_ids` also accepts two aliases:
* `MY_SPACE` — import every file under the user's workspace root in one call.
* `ROOT` — import every file the user has access to across the whole Library.
To add a file that is not yet in the Library, upload it first using the [Library upload flow](/features/memorylake/api-reference/library/overview#uploading-a-file-end-to-end).
**Permissions required (all of):**
* [`project:doc_add`](/features/team-collaboration/permission-reference#add-a-document-to-a-project) · `instance`
* [`drive:item_read`](/features/team-collaboration/permission-reference#read-your-files) · `service`
**Workflow note:** The two permissions above are checked together when this endpoint is called — `drive:item_read` is needed because the server resolves and reads each referenced drive item. If you're uploading a **new** file end-to-end first, the Library upload calls ([Create Upload](/features/memorylake/api-reference/library/create-upload) and [Create Item](/features/memorylake/api-reference/library/create-item)) additionally require [`drive:item_add`](/features/team-collaboration/permission-reference#upload-and-create-files).
### Path Parameters
Project ID.
### Request Body
Library item IDs to import. Accepts file and directory IDs in any combination — directories are recursively flattened to all descendant files, and unsupported item types are silently skipped. The aliases `MY_SPACE` (your workspace root) and `ROOT` (the whole Library) are also accepted.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/documents' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"drive_item_ids": [
"sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"sc-5c6bf0f82d624a20a6fa4696997bdd46:2a8cf1e93f634b31b7"
]
}'
```
```python Python theme={null}
import requests
BASE = "https://app.memorylake.ai/openapi/memorylake/api/v1"
HEADERS = {"Authorization": "Bearer sk_xxxxxx", "Content-Type": "application/json"}
resp = requests.post(
f"{BASE}/projects/proj-e7b262987be4589fabc60257ec2a2230/documents",
headers=HEADERS,
json={
"drive_item_ids": [
"sc-5c6bf0f82d624a20a6fa4696997bdd46:7d8cf1e93f634b31b5",
"sc-5c6bf0f82d624a20a6fa4696997bdd46:2a8cf1e93f634b31b7",
]
},
).json()
print(f"imported {resp['data']['success_count']}, failed {resp['data']['failure_count']}")
```
### Response
Number of files successfully imported as documents
Number of files that failed to import
```json Success (200) theme={null}
{
"success": true,
"data": {
"success_count": 2,
"failure_count": 0
}
}
```
After import, documents start out with status `pending` and transition through `running` → `okay` (or `error`). Poll [List Documents](/features/memorylake/api-reference/memories/list-documents) or [Get Document](/features/memorylake/api-reference/memories/get-document) to observe progress.
## Typical Flow
Either upload it via the [chunked upload flow](/features/memorylake/api-reference/library/overview#uploading-a-file-end-to-end), or locate an existing file with [List Items](/features/memorylake/api-reference/library/list-items).
Pass one or more `item_id`s inside `drive_item_ids`. You can mix files and directories — passing a directory imports every descendant file in one call. Batch in a single request when you can; it is faster than looping.
Poll [List Documents](/features/memorylake/api-reference/memories/list-documents) until the new documents reach `okay`.
# Add Memory
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/add-memory
Submit a conversation to extract and store memories
```
POST /openapi/memorylake/api/v2/projects/{id}/memories
```
Submits a user–assistant conversation to the project. Structured memories are automatically extracted from the messages and stored asynchronously. The response includes an event ID that can be used to track processing progress.
**Permission required:** [`project:mem_add`](/features/team-collaboration/permission-reference#add-a-fact-via-api-api-only) · `instance`
### Path Parameters
Project ID (format: `proj-{uuid}`)
### Request Body
Array of message objects representing the conversation. Each message contains a `role` (`user` or `assistant`) and `content`.
Unique identifier of the user associated with this memory
Unique identifier of the chat session
Whether to infer memories from messages, or store messages directly. Defaults to `true` (infer mode).
Additional arbitrary metadata key-value pairs
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"messages": [
{"role": "user", "content": "What restaurants do you recommend in Hangzhou?"},
{"role": "assistant", "content": "I recommend trying Grandma'\''s Kitchen for Hangzhou cuisine and Green Tea Restaurant for a modern take on local dishes."}
],
"user_id": "user-abc123",
"chat_session_id": "session-abc123",
"infer": true
}'
```
### Response
Array of async processing results
Status message
Processing status (e.g. `PENDING`)
Event ID for tracking processing progress
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"results": [
{
"message": "Memory processing has been queued for background execution",
"status": "PENDING",
"event_id": "97ba056d-df1b-4236-886a-4db825f29227"
}
]
}
}
```
# Download Document
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/download-document
Download the binary content of a project document
```
GET /openapi/memorylake/api/v1/projects/{id}/documents/{documentId}/download
```
Downloads the binary content of a project document. The response is either a `303` redirect to the storage download URL, or streamed binary content.
**Permission required:** `project:doc_read` on the project, and `drive:item_read` on the underlying library item.
**Permissions required (all of):**
* [`project:doc_read`](/features/team-collaboration/permission-reference#read-a-single-document) · `instance`
* [`drive:item_read`](/features/team-collaboration/permission-reference#read-your-files) · `service`
The server resolves the document to its underlying Library file and forwards to the drive download handler — both permissions are checked on every call.
### Path Parameters
Project ID
Project document ID
```bash cURL theme={null}
curl -L -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/documents/doc-fc71c24ddac8a9cb19b87c462629f36e/download' \
-H 'Authorization: Bearer sk_xxxxxx' \
-o downloaded_file.pdf
```
### Response
Returns either a `303` redirect to the storage download URL, or `200` with streamed binary content (`application/octet-stream`).
```
HTTP/1.1 303 See Other
Location: https://storage.example.com/download/document.pdf?signature=...
```
# Forget Memory
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/forget-memory
Mark a memory as forgotten without deleting it
```
POST /openapi/memorylake/api/v2/projects/{id}/memories/{memoryId}/forget
```
Marks the memory as forgotten (expired) without deleting it. The memory stays for audit purposes but is excluded from future searches and recalls.
**Permission required:** [`project:mem_delete`](/features/team-collaboration/permission-reference#forget-delete-a-fact) · `instance`
### Path Parameters
Project ID
Memory ID to forget
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/fact-b6729ff5905991da96a5eced75b95fa1/forget' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Memory forgotten successfully"
}
```
# Get Document
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/get-document
Returns details of a single document in a project
```
GET /openapi/memorylake/api/v1/projects/{id}/documents/{documentId}
```
Returns the details of a single document, including file name and processing status.
**Permission required:** [`project:doc_read`](/features/team-collaboration/permission-reference#read-a-single-document) · `instance`
### Path Parameters
Project ID
Project document ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/documents/doc-1234567890abcdef' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Document ID
File name
Processing status: `pending`, `running`, `okay`, or `error`
Drive item identifier
Creation timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "doc-fc71c24ddac8a9cb19b87c462629f36e",
"name": "report.pdf",
"status": "okay",
"drive_item_id": "sc-4d2beb72e9af4b01:inode-926ead7cac284666",
"created_at": "2024-01-15T10:30:00Z"
}
}
```
# Get Memory
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/get-memory
Returns the content and metadata of a single memory
```
GET /openapi/memorylake/api/v2/projects/{id}/memories/{memoryId}
```
Returns the content and metadata of a single memory.
**Permission required:** [`project:mem_read`](/features/team-collaboration/permission-reference#read-a-fact’s-content) · `instance`
### Path Parameters
Project ID
Memory ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/mem-123' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Memory ID
Memory content
Whether the memory has been forgotten
Associated user ID
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "fact-b6729ff5905991da96a5eced75b95fa1",
"content": "User prefers Hangzhou cuisine restaurants",
"expired": false,
"user_id": "user-abc123",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:00:00Z"
}
}
```
# Get Memory Conflict
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/get-memory-conflict
Retrieve full details of a single memory conflict
```
GET /openapi/memorylake/api/v2/projects/{id}/memories/conflicts/{conflictId}
```
Returns the full record for one conflict. You always get the memory snapshots captured at detection time. For memory-vs-document (`m2d`) conflicts, you also get the document excerpts that contradict the memory — excerpts whose source document has since been removed from the project are dropped.
**Permission required:** [`project:mem_read`](/features/team-collaboration/permission-reference#read-a-fact’s-content) · `instance`
### Path Parameters
Project ID
Conflict ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts/conf-abc123' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Conflict ID
Short title
Longer explanation of the contradiction
`m2m` (memory vs memory) or `m2d` (memory vs document)
What kind of inconsistency:
* `logical` — contradiction or tension between statements.
* `knowledge` — disagreement about facts or what was cited.
Whether the conflict has been resolved
Resolution record — present only when `resolved` is `true`.
Resolution record ID
Strategy applied: `keep_memory`, `trust_memory`, `trust_document`, or `dismiss`
Memory kept when the strategy required a choice
Memories forgotten as part of resolution
Actor that resolved the conflict
When the conflict was resolved
Whether underlying content has changed since detection
Memories involved in the conflict
Snapshots of each memory's text at the moment the conflict was detected
Memory identifier
History revision ID, if any
Memory text at detection time
Document excerpts — non-empty when `category` is `m2d`
ID of the project document
Display name of the document
Matched text span from the document
`text`
Plain text content
Optional location hint (e.g. page or cell range)
ID of the event that triggered detection
First detected at
Last updated at
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conf-abc123",
"name": "Contradicting restaurant preferences",
"description": "An earlier memory says the user prefers spicy food; a later one says they avoid it.",
"category": "m2m",
"conflict_type": "logical",
"resolved": false,
"stale": false,
"memory_ids": ["fact-7f20f052f02e642c44e79b2f371acc52", "fact-c9fe56ab6ca621340629858ab9480b09"],
"memory_snapshots": [
{
"memory_id": "fact-7f20f052f02e642c44e79b2f371acc52",
"memory_text": "User prefers spicy food"
},
{
"memory_id": "fact-c9fe56ab6ca621340629858ab9480b09",
"memory_text": "User avoids spicy food"
}
],
"file_chunks": [],
"event_id": "evt-xyz",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
```
Once you have the conflict detail, apply a decision with [Resolve Memory Conflict](/features/memorylake/api-reference/memories/resolve-memory-conflict). The returned `forgotten_memory_ids` tells you which memories were removed so your UI can stay in sync.
# Get Memory Trace
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/get-memory-trace
Returns the full change history of a memory
```
GET /openapi/memorylake/api/v2/projects/{id}/memories/{memoryId}/trace
```
Returns the full change history of a memory — all versions it has gone through and the original conversation messages that triggered each change.
**Permission required:** [`project:mem_read`](/features/team-collaboration/permission-reference#read-a-fact’s-content) · `instance`
### Path Parameters
Project ID
Memory ID to trace
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/fact-b6729ff5905991da96a5eced75b95fa1/trace' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Memory ID
Current memory content
Array of change history entries
History entry ID
Event type (e.g. `ADD`, `UPDATE`, `DELETE`)
Memory content after this change
Whether the memory was expired at this point
Timestamp of the change
Associated event ID
Original conversation messages that triggered this change
```json Success (200) theme={null}
{
"success": true,
"data": {
"memory_id": "fact-b6729ff5905991da96a5eced75b95fa1",
"current_memory": "User prefers Hangzhou cuisine restaurants",
"trace": [
{
"history_id": "19135a2d-2cc6-45db-bfc7-959d8fc117b2",
"event_type": "ADD",
"new_memory": "User prefers Hangzhou cuisine restaurants",
"expired": false,
"changed_at": "2024-01-15T10:00:00Z",
"event_id": "batch-637d4f2ded6243feb926e5cf15f69b97",
"source_messages": [
{
"role": "user",
"content": "What restaurants do you recommend in Hangzhou?",
"timestamp": 1705312800
},
{
"role": "assistant",
"content": "I recommend trying Grandma's Kitchen for Hangzhou cuisine.",
"timestamp": 1705312800
}
]
}
]
}
}
```
# List Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/list-documents
Returns a paginated list of documents in a project
```
GET /openapi/memorylake/api/v1/projects/{id}/documents
```
Returns a paginated list of documents associated with the project.
**Permission required:** [`project:doc_read`](/features/team-collaboration/permission-reference#see-the-files-tab) · `instance`
### Path Parameters
Project ID
### Query Parameters
Page number (1-based)
Page size (max 100)
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/documents?page=1&size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of document objects
Document ID
File name
Processing status: `pending`, `running`, `okay`, or `error`
Drive item identifier
Creation timestamp
Total number of documents
Current page number
Page size
Total number of pages
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "doc-8f86f326d4eb4f7a88cc51c5774cae56",
"name": "report.pdf",
"status": "okay",
"drive_item_id": "sc-4d2beb72e9af4b01:inode-926ead7cac284666",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 1,
"page": 1,
"size": 20,
"total_pages": 1
}
}
```
# List Memories
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/list-memories
Returns a paginated list of memories in a project
```
GET /openapi/memorylake/api/v2/projects/{id}/memories
```
Returns a paginated list of all memories stored in the project. Use `user_id` to filter memories belonging to a specific user.
**Permission required:** [`project:mem_read`](/features/team-collaboration/permission-reference#see-the-facts-tab) · `instance`
### Path Parameters
Project ID
### Query Parameters
Page number (1-based)
Page size (max 100)
Filter by user ID
Filter by content keyword (substring match)
Filter by expired status
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories?page=1&size=20&user_id=user-abc123' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of memory objects
Memory ID
Memory content
Whether the memory has been forgotten
Associated user ID
Creation timestamp
Last update timestamp
Total number of memories
Current page number
Page size
Total number of pages
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "fact-b6729ff5905991da96a5eced75b95fa1",
"content": "User prefers Hangzhou cuisine restaurants",
"expired": false,
"user_id": "user-abc123",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:00:00Z"
}
],
"total": 1,
"page": 1,
"size": 20,
"total_pages": 1
}
}
```
# List Memory Conflicts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/list-memory-conflicts
Browse memory-vs-memory and memory-vs-document conflicts in a project
```
GET /openapi/memorylake/api/v2/projects/{id}/memories/conflicts
```
When a new memory is added, MemoryLake checks it against two things: the project's existing memories, and the project's documents. If the new memory contradicts either one, the contradiction is recorded as a **conflict**. There are two kinds:
* **`m2m` — memory vs memory**: the new memory contradicts an existing memory.
* **`m2d` — memory vs document**: the new memory contradicts content in a project document.
Use this endpoint to surface conflicts to end users ("review unresolved conflicts"), or to fetch conflicts tied to specific memories you're about to display.
**Permission required:** [`project:mem_read`](/features/team-collaboration/permission-reference#see-the-facts-tab) · `instance`
### Path Parameters
Project ID
### Query Parameters
Page number (1-based)
Page size, 1–100
Filter by conflict category:
* `m2m` — memory vs memory.
* `m2d` — memory vs document.
Filter by kind of inconsistency:
* `logical` — contradiction or tension between statements.
* `knowledge` — disagreement about facts or what was cited.
Filter to only resolved (`true`) or only unresolved (`false`) conflicts. Omit to return both.
Filter by whether the underlying content has changed since the conflict was detected. Stale conflicts may no longer be accurate.
Comma-separated list of memory IDs. Returns conflicts that involve any of the listed memories.
```bash Unresolved conflicts theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts?resolved=false&page=1&page_size=50' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Conflicts involving specific memories theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts?memory_ids=mem-001,mem-002' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of conflict objects
Conflict ID
Short title
Longer explanation of the contradiction
`m2m` (memory vs memory) or `m2d` (memory vs document)
`logical` (contradicting statements) or `knowledge` (disagreement about facts or citations)
Whether the conflict has been resolved
Resolution details — present only when `resolved` is `true`. See [Get Memory Conflict](/features/memorylake/api-reference/memories/get-memory-conflict) for the full shape.
Whether underlying content has changed since detection
IDs of memories involved in the conflict
Memory snapshots captured at detection time
Document excerpts involved. Non-empty when `category` is `m2d`.
ID of the event that triggered detection
First detected at
Last updated at
Total matching conflicts
Current page (1-based)
Page size
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "conf-abc123",
"name": "Contradicting restaurant preferences",
"description": "An earlier memory says the user prefers spicy food; a later one says they avoid it.",
"category": "m2m",
"conflict_type": "logical",
"resolved": false,
"stale": false,
"memory_ids": ["fact-7f20f052f02e642c44e79b2f371acc52", "fact-c9fe56ab6ca621340629858ab9480b09"],
"memory_snapshots": [
{ "memory_id": "fact-7f20f052f02e642c44e79b2f371acc52", "memory_text": "User prefers spicy food" },
{ "memory_id": "fact-c9fe56ab6ca621340629858ab9480b09", "memory_text": "User avoids spicy food" }
],
"file_chunks": [],
"event_id": "evt-xyz",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 50
}
}
```
For the full breakdown of a single conflict — including the nested resolution record when it's been resolved and document excerpts for `m2d` cases — call [Get Memory Conflict](/features/memorylake/api-reference/memories/get-memory-conflict).
# Remove Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/remove-documents
Batch remove documents from a project
```
DELETE /openapi/memorylake/api/v1/projects/{id}/documents
```
Removes one or more documents from a project.
This is a destructive operation. The document associations will be permanently removed.
**Permission required:** [`project:doc_delete`](/features/team-collaboration/permission-reference#remove-a-document-from-a-project) · `instance`
### Path Parameters
Project ID
### Request Body
List of project document IDs to remove
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/documents' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"ids": ["doc-fc71c24ddac8a9cb19b87c462629f36e", "doc-abcdef1234567890"]
}'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Documents removed successfully"
}
```
# Resolve Memory Conflict
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/resolve-memory-conflict
Apply a resolution strategy to a memory conflict
```
POST /openapi/memorylake/api/v2/projects/{id}/memories/conflicts/{conflictId}/resolve
```
Records the user's decision on a conflict. Depending on the strategy, one or more of the conflicting memories may be forgotten — those IDs come back in `forgotten_memory_ids` so your UI can update the corresponding memory rows.
**Permission required:** [`project:mem_modify`](/features/team-collaboration/permission-reference#resolve-conflicting-facts) · `instance`
### Path Parameters
Project ID
Conflict ID
### Request Body
Resolution strategy. Each strategy fits a particular conflict shape:
| Strategy | What it does | Memories forgotten |
| - | - | - |
| `keep_memory` | Keep one memory from the conflict set; drop the rest. **Requires** `keep_memory_id`. Typical for memory-vs-memory. | The memories not chosen |
| `trust_memory` | Keep the memory and treat the file-side disagreement as resolved. Typical for memory-vs-document. | None |
| `trust_document` | Drop the conflicting memory in favor of the document. Typical for memory-vs-document. | The conflicting memory |
| `dismiss` | Mark as resolved without changing any memories — use when the conflict is a false alarm. | None |
The `memory_id` to keep. Required when `strategy` is `keep_memory`; ignored otherwise.
```bash Keep a specific memory theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "keep_memory",
"keep_memory_id": "fact-c9fe56ab6ca621340629858ab9480b09"
}'
```
```bash Trust the memory theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "trust_memory"
}'
```
```bash Trust the document theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "trust_document"
}'
```
```bash Dismiss theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "dismiss"
}'
```
### Response
Conflict ID
Whether the conflict is now marked resolved
Strategy that was applied
Audit record ID for this resolution
Memories forgotten as part of resolution (may be empty)
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conf-abc123",
"resolved": true,
"strategy": "keep_memory",
"resolve_id": "resv-0001",
"forgotten_memory_ids": ["fact-7f20f052f02e642c44e79b2f371acc52"]
}
}
```
# Search Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/search-documents
Semantic search over documents in a project
```
POST /openapi/memorylake/api/v1/projects/{id}/documents/search
```
Performs semantic search over all documents in the project. Returns matched content ranked by relevance. Results are categorized into three types — `table`, `paragraph`, and `figure` — each identified by the `type` field.
**Permission required:** [`project:doc_search`](/features/team-collaboration/permission-reference#search-documents-inside-a-project-api-only) · `instance`
### Path Parameters
Project ID
### Request Body
Search query text
Maximum number of results to return (minimum 1)
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/documents/search' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"query": "What were the quarterly sales figures in 2024?",
"top_n": 10
}'
```
### Response
Actual number of results returned
Search results ranked by relevance. Each item is a discriminated union — `type` decides which variant-only fields are present and which sub-field of `highlight` is populated. Click to expand the full per-item shape.
Discriminator. One of `paragraph`, `table`, or `figure`.
Document ID
Document file name, e.g. `report_2024.xlsx`
Source file info.
Original file name
Matched content. The object always has the same three optional fields below — exactly one is populated, selected by the parent item's `type`.
Populated when `type=paragraph`. Matched text spans, in document order. Absent otherwise.
Plain-text snippet of the match
Location hint (e.g. page number `p12`, or a cell range for workbook paragraphs)
Populated when `type=table`. Matched sub-tables within the source table region. Absent otherwise.
Inner table ID
Cell range covered, e.g. `A1:D50`
Number of data rows
Internal storage path of the materialized table
Column descriptors.
Column ID
Column header name
Inferred data type (e.g. `string`, `number`, `date`)
Column cell range
Non-null value count
Null value count
Approximate number of distinct values
Minimum value (string-encoded)
Maximum value (string-encoded)
Sample raw values from the column
Sample formatted/display values
Model-inferred semantic comment for the column
Whether the column participates in a row hierarchy
Populated when `type=figure`. The matched figure descriptor. Absent otherwise.
Original figure caption
OCR / extracted text inside the figure
Model-generated summary of the figure
Pre-generated questions the figure can answer
Internal storage path of the figure asset
**Only when `type=paragraph`.** Paragraph block ID inside the document.
**Only when `type=table`.** Table entity ID.
**Only when `type=table`.** Table title.
**Only when `type=table`.** Table footnote.
**Only when `type=table`.** Worksheet name (workbook tables).
**Only when `type=table`.** Model-inferred semantic name for the worksheet.
**Only when `type=table`.** Model-inferred semantic comment for the worksheet.
**Only when `type=table`.** Table region location, e.g. `A1:D50`.
**Only when `type=figure`.** Figure numeric ID.
```json Success (200) theme={null}
{
"success": true,
"data": {
"count": 3,
"results": [
{
"type": "paragraph",
"document_id": "doc-80e1657a999bce34ef2f7056f117134d",
"document_name": "report_2024.pdf",
"paragraph_block_id": "blk-456",
"highlight": {
"chunks": [
{
"text": "Q1 2024 sales reached $2.5M...",
"range": "p12"
}
]
},
"source_document": {
"file_name": "report_2024.pdf"
}
},
{
"type": "table",
"document_id": "doc-7f432d326c7acd40563b4503da81cdd8",
"document_name": "sales_data.xlsx",
"table_id": "tbl-001",
"title": "Quarterly Sales Summary",
"sheet_name": "Sheet1",
"table_region_info": "A1:D50",
"highlight": {
"inner_tables": [...]
},
"source_document": {
"file_name": "sales_data.xlsx"
}
}
]
}
}
```
# Search Memories
Source: https://docs.memorylake.ai/features/memorylake/api-reference/memories/search-memories
Search memories using natural language with optional reranking
```
POST /openapi/memorylake/api/v2/projects/{id}/memories/search
```
Searches memories in the project using natural language. Results can be filtered by user, limited by score threshold, and optionally reranked for higher relevance.
**Permission required:** [`project:mem_search`](/features/team-collaboration/permission-reference#search-facts) · `instance`
### Path Parameters
Project ID
### Request Body
The search query text
Filter by user ID
Maximum number of results to return (1–1000)
Minimum similarity score threshold. Results below this score are filtered out.
Whether to apply reranking to improve result relevance
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v2/projects/proj-e7b262987be4589fabc60257ec2a2230/memories/search' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"query": "What restaurants were recommended?",
"user_id": "user-abc123",
"top_k": 10,
"threshold": 0.3,
"rerank": false
}'
```
### Response
List of matching memories ordered by relevance
Memory ID
Memory content
Associated user ID
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"results": [
{
"id": "fact-b6729ff5905991da96a5eced75b95fa1",
"content": "User prefers Hangzhou cuisine restaurants",
"user_id": "user-abc123",
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:00:00Z"
}
]
}
}
```
# Create Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/projects/create-project
Create a new project with name and optional description
```
POST /openapi/memorylake/api/v1/projects
```
Creates a new project. Returns the created project with a generated ID in format `proj-{uuid}`.
**Permission required:** [`project:create`](/features/team-collaboration/permission-reference#create-a-new-project) · `service`
### Request Body
Project name (1–255 characters)
Project description (max 2000 characters)
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "My New Project",
"description": "This project contains documents and memories related to my research"
}'
```
### Response
Unique project identifier
Project name
Project description
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"id": "proj-e7b262987be4589fabc60257ec2a2230",
"name": "My New Project",
"description": "This project contains documents and memories related to my research",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
```
# Delete Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/projects/delete-project
Permanently delete a project and all its associated data
```
DELETE /openapi/memorylake/api/v1/projects/{id}
```
This is a destructive operation. The project and all its associated data will be permanently removed.
**Permission required:** [`project:delete`](/features/team-collaboration/permission-reference#delete-a-project) · `instance`
### Path Parameters
Project ID
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Indicates if the request was successful
Human-readable status message
```json Success (200) theme={null}
{
"success": true,
"message": "Project deleted successfully"
}
```
# Get Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/projects/get-project
Retrieve project details by ID
```
GET /openapi/memorylake/api/v1/projects/{id}
```
Retrieves a project by its ID. Returns project details including usage statistics.
**Permission required:** [`project:read`](/features/team-collaboration/permission-reference#open-a-project) · `instance`
### Path Parameters
Project ID (format: `proj-{uuid}`)
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique project identifier
Project name
Project description
Aggregated usage statistics (token counts, retrieve counts)
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "proj-e7b262987be4589fabc60257ec2a2230",
"name": "My Project",
"description": "Project description",
"statistics": {
"total_history_document_retrieve_tokens": 12800,
"total_history_document_tokens": 50000,
"total_history_memory_retrieve_tokens": 4500,
"total_history_memory_tokens": 20000,
"total_document_tokens": 60000,
"total_memory_tokens": 8000,
"document_retrieve_count": 42,
"memory_retrieve_count": 18
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T14:45:00Z"
}
}
```
# List Projects
Source: https://docs.memorylake.ai/features/memorylake/api-reference/projects/list-projects
Returns a paginated list of projects with optional filtering
```
GET /openapi/memorylake/api/v1/projects
```
Returns a paginated list of projects created by the current authenticated user with optional filtering by name.
**Permission required:** [`project:read`](/features/team-collaboration/permission-reference#browse-the-project-list) · `service` — rows you cannot open are left out of the list rather than the list being refused
### Query Parameters
Page number (1-based)
Page size (max 100)
Fuzzy filter by project name (partial match)
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects?page=1&size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of project objects
Unique project identifier
Project name
Project description
Aggregated usage statistics (token counts, retrieve counts)
Creation timestamp
Last update timestamp
Total number of projects
Current page number
Page size
Total number of pages
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "proj-e7b262987be4589fabc60257ec2a2230",
"name": "My Project",
"description": "Project description",
"statistics": {
"total_history_document_retrieve_tokens": 12800,
"total_history_document_tokens": 50000,
"total_history_memory_retrieve_tokens": 4500,
"total_history_memory_tokens": 20000,
"total_document_tokens": 60000,
"total_memory_tokens": 8000,
"document_retrieve_count": 42,
"memory_retrieve_count": 18
},
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T14:45:00Z"
}
],
"total": 1,
"page": 1,
"size": 20,
"total_pages": 1
}
}
```
# Search Memories & Documents in Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/projects/search-project
Run document search and memory search together in a single call
```
POST /openapi/memorylake/api/v1/projects/{id}/search
```
Searches across everything the project knows — both the ingested document content and the accumulated conversation memories — and returns the matches grouped by source. A single query surfaces the full picture, which is what you typically want in a chat assistant that grounds answers on documents **and** personalizes them with memories.
Items in `documents` and `memories` have the same shapes as [Search Documents](/features/memorylake/api-reference/memories/search-documents) and [Search Memories](/features/memorylake/api-reference/memories/search-memories) respectively — the relevant request knobs (`top_n`, `threshold`) carry the same meaning here.
**Permission required:** [`project:search`](/features/team-collaboration/permission-reference#search-across-a-project-api-only) · `instance`
### Path Parameters
Project ID
### Request Body
Natural-language search query. Used by both sub-searches.
User ID filter for the memory sub-search. Document search ignores this field.
Maximum number of results to return, 1–1000. Applied to both document and memory matches — e.g. `top_n=10` yields up to 10 documents and up to 10 memories.
Minimum similarity score for memory results. Scores below this are filtered out. Does not apply to documents.
Include conflict info on memory results.
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-e7b262987be4589fabc60257ec2a2230/search' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"query": "What were the quarterly sales figures in 2024?",
"user_id": "user-abc123",
"top_n": 10,
"threshold": 0.3
}'
```
### Response
Document search results. Each item is a discriminated union — `type` decides which variant-only fields are present and which sub-field of `highlight` is populated. Click to expand the full per-item shape.
Discriminator. One of `paragraph`, `table`, or `figure`.
Document ID
Document file name, e.g. `report_2024.xlsx`
Source file info.
Original file name
Matched content. The object always has the same three optional fields below — exactly one is populated, selected by the parent item's `type`.
Populated when `type=paragraph`. Matched text spans, in document order. Absent otherwise.
Plain-text snippet of the match
Location hint (e.g. page number `p12`, or a cell range for workbook paragraphs)
Populated when `type=table`. Matched sub-tables within the source table region. Absent otherwise.
Inner table ID
Cell range covered, e.g. `A1:D50`
Number of data rows
Internal storage path of the materialized table
Column descriptors.
Column ID
Column header name
Inferred data type (e.g. `string`, `number`, `date`)
Column cell range
Non-null value count
Null value count
Approximate number of distinct values
Minimum value (string-encoded)
Maximum value (string-encoded)
Sample raw values from the column
Sample formatted/display values
Model-inferred semantic comment for the column
Whether the column participates in a row hierarchy
Populated when `type=figure`. The matched figure descriptor. Absent otherwise.
Original figure caption
OCR / extracted text inside the figure
Model-generated summary of the figure
Pre-generated questions the figure can answer
Internal storage path of the figure asset
**Only when `type=paragraph`.** Paragraph block ID inside the document.
**Only when `type=table`.** Table entity ID.
**Only when `type=table`.** Table title.
**Only when `type=table`.** Table footnote.
**Only when `type=table`.** Worksheet name (workbook tables).
**Only when `type=table`.** Model-inferred semantic name for the worksheet.
**Only when `type=table`.** Model-inferred semantic comment for the worksheet.
**Only when `type=table`.** Table region location, e.g. `A1:D50`.
**Only when `type=figure`.** Figure numeric ID.
Memory search results. Same shape as [Search Memories](/features/memorylake/api-reference/memories/search-memories).
Memory ID
Memory content
Associated user ID
Whether this memory has expired
Whether this memory has an unresolved conflict (only meaningful when `with_conflicts=true`)
Creation timestamp (ISO 8601)
Last update timestamp (ISO 8601)
```json Success (200) theme={null}
{
"success": true,
"message": "Operation completed successfully",
"data": {
"documents": [
{
"type": "paragraph",
"document_id": "doc-80e1657a999bce34ef2f7056f117134d",
"document_name": "report_2024.pdf",
"paragraph_block_id": "blk-456",
"highlight": {
"chunks": [
{ "text": "Q1 2024 sales reached $2.5M...", "range": "p12" }
]
},
"source_document": { "file_name": "report_2024.pdf" }
},
{
"type": "table",
"document_id": "doc-7f432d326c7acd40563b4503da81cdd8",
"document_name": "sales_data.xlsx",
"table_id": "tbl-001",
"title": "Quarterly Sales Summary",
"sheet_name": "Sheet1",
"semantic_sheet_name": "2024 Quarterly Sales",
"table_region_info": "A1:D50",
"highlight": {
"inner_tables": [
{
"id": "itbl-001",
"data_range": "A1:D50",
"num_rows": 49,
"persist_path": "tables/doc-7f432d326c7acd40563b4503da81cdd8/itbl-001",
"columns": [
{
"id": "col-1",
"name": "Quarter",
"data_type": "string",
"range": "A2:A50",
"count": 49,
"null_count": 0,
"approx_ndv": 4,
"examples": [{ "v": "Q1" }, { "v": "Q2" }],
"display_examples": [{ "v": "Q1" }, { "v": "Q2" }]
},
{
"id": "col-2",
"name": "Revenue",
"data_type": "number",
"range": "B2:B50",
"min_value": "1200000",
"max_value": "3100000"
}
]
}
]
},
"source_document": { "file_name": "sales_data.xlsx" }
},
{
"type": "figure",
"document_id": "doc-7e00074632a081cdffe6700d4c496206",
"document_name": "report_2024.pdf",
"figure_id": 7,
"highlight": {
"figure": {
"caption": "Figure 7. Quarterly revenue trend, 2024",
"text": "Q1 $2.5M Q2 $2.8M Q3 $3.0M Q4 $3.1M",
"summary_text": "Bar chart showing steady quarterly revenue growth across 2024.",
"prequestion_list": [
"Which quarter had the highest revenue in 2024?",
"What was the revenue trend across 2024?"
],
"persist_path": "figures/doc-7e00074632a081cdffe6700d4c496206/fig-7.png"
}
},
"source_document": { "file_name": "report_2024.pdf" }
}
],
"memories": [
{
"id": "fact-b6729ff5905991da96a5eced75b95fa1",
"content": "User prefers Hangzhou cuisine restaurants",
"user_id": "user-abc123",
"expired": false,
"has_unresolved_conflict": false,
"created_at": "2024-01-15T10:00:00Z",
"updated_at": "2024-01-15T10:00:00Z"
}
]
}
}
```
Either list can be empty if no matches cross the threshold. Treat `documents` and `memories` independently — they're just two lookups returned together for convenience.
# Update Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/projects/update-project
Update an existing project's name and/or description
```
PUT /openapi/memorylake/api/v1/projects/{id}
```
Updates an existing project's name and/or description.
**Permission required:** [`project:modify`](/features/team-collaboration/permission-reference#edit-project-settings) · `instance`
### Path Parameters
Project ID
### Request Body
Updated project name (1–255 characters)
Updated project description (max 2000 characters)
```bash cURL theme={null}
curl -X PUT 'https://app.memorylake.ai/openapi/memorylake/api/v1/projects/proj-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "My Updated Project",
"description": "Updated project description"
}'
```
### Response
Unique project identifier
Updated project name
Updated project description
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"message": "Project updated successfully",
"data": {
"id": "proj-e7b262987be4589fabc60257ec2a2230",
"name": "My Updated Project",
"description": "Updated project description",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T14:45:00Z"
}
}
```
# Rate Limiting & Quotas
Source: https://docs.memorylake.ai/features/memorylake/api-reference/rate-limits
API rate limits and usage quotas
## Rate Limit Overview
API requests are rate limited to ensure fair usage and system stability. Limits are enforced at two levels: **per IP address** and **per user account**.
## Current Limits
| Dimension | Limit |
| - | - |
| Per IP address | Sliding window of several minutes; the exact threshold is set per deployment and is generous for normal integration traffic |
| Per user account | 600 requests / minute on the default access group |
| Per IP address, upload endpoints | Separate, tighter per-minute bucket |
When either limit is exceeded, the API returns HTTP status `429 Too Many Requests` with a `Retry-After` header. The per-account limit is set by your access group, so it may differ from the default shown above — contact support for higher limits.
## Rate Limit Exceeded Response
When a rate limit is exceeded, the API responds with:
```json theme={null}
{
"success": false,
"message": "Rate limit exceeded. Please retry later.",
"error_code": "RATE_LIMIT_EXCEEDED"
}
```
## Handling Rate Limits
### Implement Exponential Backoff
```javascript theme={null}
async function apiRequestWithBackoff(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
const response = await fetch(url, options);
if (response.status === 429) {
const waitTime = Math.pow(2, i) * 1000;
console.log(`Rate limited. Retrying in ${waitTime}ms...`);
await sleep(waitTime);
continue;
}
return response;
}
throw new Error('Max retries exceeded due to rate limiting');
}
```
### Best Practices
* Implement exponential backoff with jitter for retries
* Cache responses when possible to reduce redundant requests
* Batch operations where supported (e.g. batch document removal)
* Implement client-side request queuing to smooth out traffic spikes
* Monitor request volume and log `429` responses for observability
## Storage and Resource Quotas
| Resource | Limit |
| - | - |
| Projects | Unlimited |
| Memories per project | Unlimited |
| Documents per project | Unlimited |
| Total storage | Depends on your plan |
| Max file size | Depends on your plan; large files upload via multipart automatically |
Storage allowances are tied to your subscription. Check **Billing** in the [console](https://app.memorylake.ai/panel/billing) for your current plan, or contact support if you expect unusually large uploads.
## Requesting Higher Limits
To request higher rate limits, contact support with:
* Current usage patterns and peak request volume
* Expected future usage
* Use case description
## Next Steps
Return to API overview
Handle rate limit errors
# Get Memory Conflict
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-conflicts/get-conflict
Retrieve the full details of a single memory conflict in a project
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/conflicts/{conflictId}
```
Returns the complete record for a single conflict, including the fact snapshots captured at detection time, any document excerpts involved, and the resolution record if the conflict has been resolved.
**Permission required:** `project:mem_conflict_read`
### Path Parameters
Workspace ID
Project ID
Conflict ID
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj-b93e8d95a8705bcc4ec42a65ba4cc7f8/memories/conflicts/conf-abc123' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Conflict identifier
Short title describing the conflict
Detailed explanation of the contradiction
Conflict category: `m2m` (fact vs. fact) or `m2d` (fact vs. document)
Whether the conflict has been resolved
Resolution record. Present only when the conflict has been resolved; `null` otherwise.
Resolution record identifier
Strategy that was applied: `keep_fact`, `trust_fact`, `trust_document`, or `dismiss`
The fact kept when `strategy` is `keep_fact`
IDs of the facts forgotten as part of the resolution
When the conflict was resolved
Whether an involved fact changed after the conflict was detected
Conflict type: `logical` or `knowledge`
IDs of the facts involved in the conflict
Snapshots of the involved facts at detection time
Fact identifier
Fact text at detection time
Document excerpts cited by a fact-vs-document conflict
The conflicting excerpt text
ID of the document this excerpt belongs to
Display name of the document
When the conflict was first detected
When the conflict was last updated
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conf-abc123",
"name": "Contradicting project deadline",
"description": "One fact states the project deadline is March 2025; another says it was moved to June 2025.",
"category": "m2m",
"resolved": true,
"resolve": {
"id": "res-9f8e7d6c",
"strategy": "keep_fact",
"keep_fact_id": "fact-b21e7865a355b52582356646e793d79d",
"forgotten_fact_ids": ["fact-4d5d087022dac9318b1abbfacbc4340c"],
"created_at": "2025-01-21T09:15:00Z"
},
"stale": false,
"conflict_type": "logical",
"fact_ids": ["fact-4d5d087022dac9318b1abbfacbc4340c", "fact-b21e7865a355b52582356646e793d79d"],
"fact_snapshots": [
{
"fact_id": "fact-4d5d087022dac9318b1abbfacbc4340c",
"fact_text": "Project deadline is March 2025"
},
{
"fact_id": "fact-b21e7865a355b52582356646e793d79d",
"fact_text": "Project deadline was moved to June 2025"
}
],
"file_chunks": [],
"created_at": "2025-01-20T14:30:00Z",
"updated_at": "2025-01-21T09:15:00Z"
}
}
```
To resolve this conflict, call [Resolve Memory Conflict](/features/memorylake/api-reference/v3-conflicts/resolve-conflict) with the strategy you want to apply.
# List Memory Conflicts
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-conflicts/list-conflicts
Returns a paginated list of memory conflicts in a project
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/conflicts
```
When MemoryLake extracts facts from conversations, it compares new facts against existing knowledge. If a contradiction is detected, it is recorded as a **memory conflict**. Use this endpoint to list a project's conflicts, newest first, so you can surface them to users for review.
You can filter by resolution status to show only unresolved conflicts that need attention, or only resolved ones for audit purposes. For conflicts among an actor's personal facts, use [List Actor Memory Conflicts](/features/memorylake/api-reference/v3-conflicts/list-actor-conflicts) instead.
**Permission required:** `project:mem_conflict_read`
### Path Parameters
Workspace ID
Project ID
### Query Parameters
Filter by resolution status. Pass `true` for resolved conflicts only, `false` for unresolved only. Omit to return both.
Number of conflicts to return per page. Range: 1–100.
Token from a previous response to fetch the next page of results
```bash Unresolved conflicts theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj-b93e8d95a8705bcc4ec42a65ba4cc7f8/memories/conflicts?resolved=false&page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash All conflicts theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj-b93e8d95a8705bcc4ec42a65ba4cc7f8/memories/conflicts?page_size=50' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of conflict objects
Conflict identifier
Short title describing the conflict
Detailed explanation of the contradiction
Conflict category: `m2m` (fact vs. fact) or `m2d` (fact vs. document)
Whether the conflict has been resolved
Resolution record. Present only when the conflict has been resolved; `null` otherwise. See [Get Memory Conflict](/features/memorylake/api-reference/v3-conflicts/get-conflict) for the full structure.
Whether an involved fact changed after the conflict was detected. Stale conflicts may no longer be accurate.
Conflict type: `logical` or `knowledge`
IDs of the facts involved in the conflict
Snapshots of the involved facts at detection time
Fact identifier
Fact text at detection time
Document excerpts cited by a fact-vs-document conflict
The conflicting excerpt text
ID of the document this excerpt belongs to
Display name of the document
When the conflict was first detected
When the conflict was last updated
Token to retrieve the next page of results. Absent when there are no more pages.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "conf-abc123",
"name": "Contradicting project deadline",
"description": "One fact states the project deadline is March 2025; another says it was moved to June 2025.",
"category": "m2m",
"resolved": false,
"resolve": null,
"stale": false,
"conflict_type": "logical",
"fact_ids": ["fact-4d5d087022dac9318b1abbfacbc4340c", "fact-b21e7865a355b52582356646e793d79d"],
"fact_snapshots": [
{
"fact_id": "fact-4d5d087022dac9318b1abbfacbc4340c",
"fact_text": "Project deadline is March 2025"
},
{
"fact_id": "fact-b21e7865a355b52582356646e793d79d",
"fact_text": "Project deadline was moved to June 2025"
}
],
"file_chunks": [],
"created_at": "2025-01-20T14:30:00Z",
"updated_at": "2025-01-20T14:30:00Z"
}
],
"continuation_token": null
}
}
```
# Resolve Memory Conflict
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-conflicts/resolve-conflict
Apply a resolution strategy to a memory conflict in a project
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/conflicts/{conflictId}/resolve
```
Applies a resolution strategy to a conflict. You can keep a designated fact, trust one side of a fact-vs-document conflict, or dismiss the conflict as a false positive.
**Permission required:** `project:mem_conflict_resolve`
### Path Parameters
Workspace ID
Project ID
Conflict ID
### Request Body
Resolution strategy to apply:
| Strategy | What it does |
| - | - |
| `keep_fact` | Keep the fact designated by `keep_fact_id` and forget the other conflicting facts |
| `trust_fact` | Trust the fact side of a fact-vs-document conflict |
| `trust_document` | Trust the document side of a fact-vs-document conflict; conflicting facts are forgotten or rewritten |
| `dismiss` | Mark the conflict as resolved without changing any facts |
ID of the fact to keep. Required when `strategy` is `keep_fact`.
```bash Keep a fact theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj-b93e8d95a8705bcc4ec42a65ba4cc7f8/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "keep_fact",
"keep_fact_id": "fact-b21e7865a355b52582356646e793d79d"
}'
```
```bash Trust the document theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj-b93e8d95a8705bcc4ec42a65ba4cc7f8/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "trust_document"
}'
```
```bash Dismiss theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj-b93e8d95a8705bcc4ec42a65ba4cc7f8/memories/conflicts/conf-abc123/resolve' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"strategy": "dismiss"
}'
```
### Response
Conflict identifier
Whether the conflict is now resolved
Applied resolution strategy
Resolution record identifier
IDs of the facts forgotten as part of the resolution
IDs of the facts rewritten as part of the resolution
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "conf-abc123",
"resolved": true,
"strategy": "keep_fact",
"resolve_id": "res-9f8e7d6c",
"forgotten_fact_ids": ["fact-4d5d087022dac9318b1abbfacbc4340c"],
"updated_fact_ids": []
}
}
```
# Delete Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-documents/delete-documents
Remove one or more documents from a project
```
DELETE /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/documents
```
Removes documents from a project. The original files in the Library are not affected -- only the project references and any extracted content are deleted.
**Permission required:** `project:doc_delete`
This is irreversible. All indexed content and memories derived from the deleted documents are permanently removed from the project.
### Path Parameters
Workspace ID that owns the project.
Project to delete documents from.
### Body Parameters
Array of document IDs to delete.
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-a1b2c3d4e5f6/projects/proj-7g8h9i0j1k2l/memories/documents' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"ids": [
"doc-3451335835b6cda07544335dc13e6183",
"doc-06f59fb06590915cc2df05ce4e8b70e1"
]
}'
```
### Response
Returns an empty `data` object on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Get Document
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-documents/get-document
Retrieve a single document's metadata by its ID
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/documents/{documentId}
```
Returns metadata for a single project document. Use this to check whether a recently imported document has finished processing, inspect its token usage, or confirm it exists before performing other operations.
**Permission required:** `project:doc_read`
### Path Parameters
Workspace ID that owns the project.
Project the document belongs to.
Document ID to retrieve.
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-a1b2c3d4e5f6/projects/proj-7g8h9i0j1k2l/memories/documents/doc-3m4n5o6p7q8r' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Document ID.
File name of the document.
Processing status: `pending`, `running`, `okay`, or `error`.
Error details when `status` is `error`. `null` otherwise.
Token usage for processing.
Number of tokens consumed to process this document.
Document type: `drive_file`.
ISO 8601 timestamp when the document was imported.
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "doc-3451335835b6cda07544335dc13e6183",
"name": "quarterly-report.pdf",
"status": "okay",
"error": null,
"usage": {
"files_process_tokens": 15230
},
"document_type": "drive_file",
"created_at": "2025-03-10T14:22:00Z"
}
}
```
# List Documents
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-documents/list-documents
List documents in a project with cursor pagination
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}/memories/documents
```
Returns documents that have been imported into a project. Uses cursor pagination: if `continuation_token` is returned, pass it back on the next request to fetch the next page. When the token is absent from the response, you have reached the end.
**Permission required:** `project:doc_read`
### Path Parameters
Workspace ID that owns the project.
Project to list documents from.
### Query Parameters
Number of documents per page. Defaults to 20 when omitted.
Token returned by the previous call. Omit on the first request.
Fuzzy match on document name.
```bash First page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-a1b2c3d4e5f6/projects/proj-7g8h9i0j1k2l/memories/documents?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
```bash Next page theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-a1b2c3d4e5f6/projects/proj-7g8h9i0j1k2l/memories/documents?page_size=20&continuation_token=eyJsYXN0SWQiOiJkb2MtOW4wbTFsMms' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of project documents.
Document ID.
File name of the document.
Processing status: `pending`, `running`, `okay`, or `error`.
Error details when `status` is `error`. `null` otherwise.
Token usage for processing.
Number of tokens consumed to process this document.
Document type: `drive_file`.
ISO 8601 timestamp when the document was imported.
Token for the next page. Absent or `null` when this is the last page.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "doc-3451335835b6cda07544335dc13e6183",
"name": "quarterly-report.pdf",
"status": "okay",
"error": null,
"usage": {
"files_process_tokens": 15230
},
"document_type": "drive_file",
"created_at": "2025-03-10T14:22:00Z"
},
{
"id": "doc-06f59fb06590915cc2df05ce4e8b70e1",
"name": "product-spec.docx",
"status": "running",
"error": null,
"usage": {
"files_process_tokens": 0
},
"document_type": "drive_file",
"created_at": "2025-03-11T09:15:00Z"
}
],
"continuation_token": "eyJsYXN0SWQiOiJkb2MtOW4wbTFsMms"
}
}
```
# Create Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-projects/create-project
Create a new project in a workspace
```
POST /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects
```
Creates a new project in the specified workspace. You provide a name and custom identifier, and optionally attach a description and metadata.
**Permission required:** `project:create`
### Path Parameters
Workspace identifier
### Request Body
Project name
Your own identifier for this project — the one it already has in your system. Must be unique within your tenant. Pass `by_custom_id=true` on later requests to address the project by it instead of by `id`. See [Your own identifiers](/features/memorylake/api-reference/overview#your-own-identifiers).
Project description
Arbitrary key-value pairs for storing additional project information
```bash cURL theme={null}
curl -X POST 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "Customer Research",
"custom_id": "research-2024-q1",
"description": "Interview transcripts and survey analysis",
"metadata": {
"team": "product",
"quarter": "Q1-2024"
}
}'
```
### Response
Unique project identifier
Project name
Project description
Custom identifier for external system integration
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8",
"name": "Customer Research",
"description": "Interview transcripts and survey analysis",
"custom_id": "research-2024-q1",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
}
```
# Delete Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-projects/delete-project
Permanently delete a project and all its associated data
```
DELETE /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}
```
This is a destructive operation. The project and all its associated documents and conversations are permanently removed.
Permanently deletes a project from the workspace. This action cannot be undone.
**Permission required:** `project:delete`
### Path Parameters
Workspace identifier
Project identifier
```bash cURL theme={null}
curl -X DELETE 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj_def456' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Returns an empty `data` field on success.
```json Success (200) theme={null}
{
"success": true,
"data": {}
}
```
# Get Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-projects/get-project
Retrieve a project by ID or custom ID
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}
```
Retrieves a single project from the workspace. By default, the `projectId` path parameter is matched against the internal project ID. Set `by_custom_id=true` to look up the project by its custom identifier instead.
**Permission required:** `project:read`
### Path Parameters
Workspace identifier
Project identifier. Interpreted as the internal ID by default, or as the custom ID when `by_custom_id` is `true`.
### Query Parameters
When `true`, the `projectId` path parameter is matched against the project's `custom_id` instead of its internal `id`.
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj_def456' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Unique project identifier
Project name
Project description
Custom identifier for external system integration
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8",
"name": "Customer Research",
"description": "Interview transcripts and survey analysis",
"custom_id": "research-2024-q1",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-02-10T08:15:00Z"
}
}
```
# List Projects
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-projects/list-projects
Returns a paginated list of projects in a workspace with optional filtering
```
GET /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects
```
Returns a paginated list of projects in the specified workspace. You can filter results by name using a fuzzy match and control pagination with `page_size` and `continuation_token`.
**Permission required:** `project:read` — rows you cannot open are left out of the list rather than the list being refused
### Path Parameters
Workspace identifier
### Query Parameters
Number of projects to return per page
Token from a previous response to fetch the next page of results
Fuzzy filter by project name (partial match)
```bash cURL theme={null}
curl -X GET 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects?page_size=20' \
-H 'Authorization: Bearer sk_xxxxxx'
```
### Response
Array of project objects
Unique project identifier
Project name
Project description
Custom identifier for external system integration
Creation timestamp
Last update timestamp
Token to retrieve the next page of results. Absent when there are no more pages.
```json Success (200) theme={null}
{
"success": true,
"data": {
"items": [
{
"id": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8",
"name": "Customer Research",
"description": "Interview transcripts and survey analysis",
"custom_id": "research-2024-q1",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-02-10T08:15:00Z"
}
],
"continuation_token": "eyJsYXN0SWQiOiJwcm9qX2RlZjQ1NiJ9"
}
}
```
# Overview
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-projects/overview
Projects are knowledge containers within a workspace that hold documents, conversations, and facts
A **Project** is a knowledge container within a [workspace](/features/memorylake/api-reference/workspaces/overview). It is where documents are imported, conversations are captured, and facts are extracted and stored. Each project organizes a distinct body of knowledge — a product's documentation, a customer's interaction history, or a research domain.
## What a Project Contains
```
Project
├── Documents — files imported from the Library, indexed for semantic search
├── Conversations — user-assistant message exchanges
│ └── Messages — individual messages within a conversation
└── Project Facts — structured knowledge extracted from conversations
```
## Typical Workflow
[Create a project](/features/memorylake/api-reference/v3-projects/create-project) within a workspace to start organizing knowledge.
Upload files to the [Library](/features/memorylake/api-reference/library/overview), then [import them](/features/memorylake/api-reference/v3-documents/import-documents) into the project. MemoryLake indexes the content for semantic search.
[Create conversations](/features/memorylake/api-reference/conversations/create-conversation) and [append messages](/features/memorylake/api-reference/conversations/create-message). MemoryLake automatically extracts structured facts from the exchanges.
[Search](/features/memorylake/api-reference/search/search-memories) across all memory sources, or manage [project facts](/features/memorylake/api-reference/facts/list-facts) directly.
## Endpoints
| Operation | Method | Path |
| - | - | - |
| [List Projects](/features/memorylake/api-reference/v3-projects/list-projects) | `GET` | `/api/v3/workspaces/{id}/projects` |
| [Create Project](/features/memorylake/api-reference/v3-projects/create-project) | `POST` | `/api/v3/workspaces/{id}/projects` |
| [Get Project](/features/memorylake/api-reference/v3-projects/get-project) | `GET` | `/api/v3/workspaces/{id}/projects/{projectId}` |
| [Update Project](/features/memorylake/api-reference/v3-projects/update-project) | `PATCH` | `/api/v3/workspaces/{id}/projects/{projectId}` |
| [Delete Project](/features/memorylake/api-reference/v3-projects/delete-project) | `DELETE` | `/api/v3/workspaces/{id}/projects/{projectId}` |
# Update Project
Source: https://docs.memorylake.ai/features/memorylake/api-reference/v3-projects/update-project
Update an existing project's name or description
```
PATCH /openapi/memorylake/api/v3/workspaces/{workspaceId}/projects/{projectId}
```
Updates an existing project. Only the fields you include in the request body are modified; omitted fields remain unchanged.
**Permission required:** `project:modify`
### Path Parameters
Workspace identifier
Project identifier
### Request Body
Updated project name
Updated project description
```bash cURL theme={null}
curl -X PATCH 'https://app.memorylake.ai/openapi/memorylake/api/v3/workspaces/ws-8001856949ad4f6a5b6226f415ffa877/projects/proj_def456' \
-H 'Authorization: Bearer sk_xxxxxx' \
-H 'Content-Type: application/json' \
-d '{
"name": "Customer Research (Updated)",
"description": "Expanded to include focus-group recordings"
}'
```
### Response
Unique project identifier
Updated project name
Updated project description
Custom identifier for external system integration
Creation timestamp
Last update timestamp
```json Success (200) theme={null}
{
"success": true,
"data": {
"id": "proj-b93e8d95a8705bcc4ec42a65ba4cc7f8",
"name": "Customer Research (Updated)",
"description": "Expanded to include focus-group recordings",
"custom_id": "research-2024-q1",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-03-05T16:20:00Z"
}
}
```