Documentation Index
Fetch the complete documentation index at: https://docs.memvid.com/llms.txt
Use this file to discover all available pages before exploring further.
Use this guide when you are integrating Memvid through HTTP in platforms like n8n, Replit, Lovable, or v0.
This page is the shared contract for API-first integrations. Platform pages should reuse these request shapes and reliability patterns.
Base Setup
- Base URL:
https://api.memvid.com
- Auth header (recommended):
Authorization: Bearer mv2_YOUR_API_KEY
- Alternative auth header:
X-API-Key: mv2_YOUR_API_KEY
Golden Path (Minimal Production Flow)
- Create or select a memory ID
- Ingest documents (JSON text, file, or URL)
- Use
find for retrieval UX
- Use
ask for grounded synthesis
- Return answer with sources in your app UI
Canonical Request Shapes
Create Memory
POST /v1/memories
Content-Type: application/json
{
"name": "Support KB",
"description": "Runbooks and policies"
}
Add Documents (JSON)
POST /v1/memories/:id/documents
Content-Type: application/json
{
"documents": [
{
"title": "P1 Playbook",
"text": "Acknowledge P1 in 10 minutes.",
"tags": ["incident", "support"]
}
]
}
Find
POST /v1/memories/:id/find
Content-Type: application/json
{
"query": "How quickly do we acknowledge P1 incidents?",
"topK": 5
}
Ask
POST /v1/memories/:id/ask
Content-Type: application/json
{
"question": "What is our P1 SLA?",
"options": {
"model": "gpt-4o-mini",
"includeSources": true,
"maxContextChunks": 10
}
}
Typed Client Wrapper (TypeScript)
type MemvidRequestInit = Omit<RequestInit, "headers"> & {
headers?: Record<string, string>;
timeoutMs?: number;
retries?: number;
};
class MemvidHttpError extends Error {
constructor(
public status: number,
public body: string,
public method: string,
public path: string
) {
super(`Memvid ${method} ${path} failed (${status})`);
}
}
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
export async function memvidRequest<T = unknown>(
path: string,
init: MemvidRequestInit = {}
): Promise<T> {
const baseUrl = process.env.MEMVID_API_BASE || "https://api.memvid.com";
const apiKey = process.env.MEMVID_API_KEY;
if (!apiKey) throw new Error("Missing MEMVID_API_KEY");
const retries = init.retries ?? 2;
const timeoutMs = init.timeoutMs ?? 15000;
const method = init.method || "GET";
for (let attempt = 0; attempt <= retries; attempt++) {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetch(`${baseUrl}${path}`, {
...init,
signal: controller.signal,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
...(init.headers || {}),
},
});
if (res.status === 204) return null as T;
const text = await res.text();
if (!res.ok) {
const retryable = res.status === 429 || res.status >= 500;
if (retryable && attempt < retries) {
await sleep(250 * Math.pow(2, attempt));
continue;
}
throw new MemvidHttpError(res.status, text, method, path);
}
return text ? (JSON.parse(text) as T) : (null as T);
} catch (err) {
const retryable = err instanceof Error && err.name === "AbortError";
if (!retryable || attempt >= retries) throw err;
await sleep(250 * Math.pow(2, attempt));
} finally {
clearTimeout(timeout);
}
}
throw new Error("Unexpected retry loop exit");
}
Async Ingestion and Job Polling
Some uploads are processed asynchronously via a background worker. This happens automatically when:
- The file is larger than 2 MB
- A PDF has more than 5 scanned/image-only pages (triggers OCR in the background)
- You set
options.async: true explicitly
When async processing kicks in, the response returns HTTP 202 instead of 200, with a jobId and pollUrl:
{
"added": 0,
"chunksCreated": 0,
"jobId": "abc123...",
"pollUrl": "/v1/jobs/abc123..."
}
Polling for completion
type JobStatus = "pending" | "processing" | "completed" | "failed" | "partial";
interface JobResult {
status: JobStatus;
progress: number; // 0-100
message?: string; // e.g. "Generating embeddings..."
result?: {
documentsAdded: number;
chunksCreated: number;
documentIds: string[];
totalBytes: number;
processingMs: number;
};
error?: string;
}
export async function waitForJob(jobId: string, timeoutMs = 600000) {
const started = Date.now();
while (Date.now() - started < timeoutMs) {
const job = await memvidRequest<JobResult>(`/v1/jobs/${jobId}`);
if (job.status === "completed" || job.status === "partial") return job;
if (job.status === "failed") throw new Error(job.error || "Memvid job failed");
await sleep(5000); // Poll every 5 seconds
}
throw new Error(`Timed out waiting for job ${jobId}`);
}
Scanned PDFs with many pages can take 2–8 minutes to process via OCR. Use a generous timeout (5–10 minutes) and poll every 5–10 seconds.
Handling both sync and async responses
const res = await fetch(`${baseUrl}/v1/memories/${memoryId}/documents`, {
method: "POST",
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
body: JSON.stringify({ documents: [...] }),
});
if (res.status === 200) {
// Sync — documents are ready immediately
const data = await res.json();
console.log(`Added ${data.added} documents (${data.chunksCreated} chunks)`);
} else if (res.status === 202) {
// Async — poll for completion
const data = await res.json();
const result = await waitForJob(data.jobId);
console.log(`Job done: ${result.result?.chunksCreated} chunks created`);
}
Reliability Checklist
- Keep API keys server-side only.
- Use memory-scoped keys for least privilege.
- Retry
429 and 5xx with backoff.
- Enforce request timeouts to prevent hanging workers.
- Log method, path, status, and request IDs for debugging.
- Show source snippets in UI for grounded trust.
5-Minute Smoke Test
Run these calls in order and verify non-empty responses:
POST /v1/memories -> get memory.id
POST /v1/memories/:id/documents -> ingest sample text
POST /v1/memories/:id/find -> expect at least one hit
POST /v1/memories/:id/ask -> expect answer/text and optional sources
Next Pages