Skip to main content
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)

  1. Create or select a memory ID
  2. Ingest documents (JSON text, file, or URL)
  3. Use find for retrieval UX
  4. Use ask for grounded synthesis
  5. 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:
  1. POST /v1/memories -> get memory.id
  2. POST /v1/memories/:id/documents -> ingest sample text
  3. POST /v1/memories/:id/find -> expect at least one hit
  4. POST /v1/memories/:id/ask -> expect answer/text and optional sources

Next Pages