Reference

HTTP API

Everything the CLI, TUI, and web UI do goes through the local HTTP API — and you can call it directly. The full, machine-readable surface is the OpenAPI 3.1 specification:

  • From a running service: GET /v1/openapi.yaml (always describes exactly the build it came from)
  • In the repository: docs/api/openapi.yaml

A contract test keeps the specification's path inventory in sync with the router in both directions, so it cannot silently drift from the code.

Base URL and authentication

The service listens on localhost only by default (127.0.0.1:4040 native, localhost:4040 in the Docker stack). In the default single_user mode, clients use the installation token. In multi_user mode, non-browser clients use a scoped Memory Layer service token:

curl -s http://127.0.0.1:4040/v1/query \
  -H "Authorization: Bearer $MEMORY_LAYER_CLIENT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"project": "demo", "query": "How does reinforcement work?"}'

The bundled browser UI uses an Authentik-backed HttpOnly session plus CSRF protection in multi-user mode. 401 means authentication failed; 403 means the principal is valid but lacks the required role or project. Read Authentication and access for configuration, roles, token lifecycle, and migration.

API version and stability

The /v1 prefix is the HTTP API namespace; it is not the Memory Layer product release number. Memory Layer v2.0.0 retained that namespace but made documented breaking changes, including removing obsolete routes and consolidating loop and activity operations. Fetch the specification from the running service when upgrading a direct integration.

Every operation in the spec carries an x-stability marker:

  • core — the supported integration boundary for the current v2 line. Additive fields may appear, and clients must ignore unknown fields.
  • internal — the service control plane (loops, watchers, agent workspaces, admin, embeddings management). Used by the bundled UIs; may change between minor versions.

For v1-to-v2 route removals and migration steps, read the Update guide.

Core endpoints

EndpointWhat it does
POST /v1/queryQuery one project's memory: hybrid retrieval plus a cited, synthesized answer — or an honest refusal (insufficient_evidence).
POST /v1/query/globalThe same across every project.
POST /v1/capture/taskCapture completed work — the HTTP write entry point, optionally with pre-distilled structured_candidates. The CLI spelling is memory capture.
POST /v1/curateCurate raw captures into canonical memories.
GET /v1/memory/{id}One memory with tags, sources, relations, and scores.
GET /v1/memory/{id}/historyFull version history, including tombstones.
GET /v1/projects/{slug}/memoriesList a project's canonical memories.
GET /v1/projects/{slug}/memory-graphMemory/source nodes with provenance and relation edges, plus decayed ACT-R activation per memory.
GET /v1/projects/{slug}/overviewCounts, watchers, recent activity.
POST /v1/projects/{slug}/resumeResume briefing for project re-entry.
GET /v1/projects/{slug}/activitiesThe activity timeline.
POST /v1/provenance/verifyVerify source provenance against the filesystem.
POST /v1/projects/{slug}/bundle/export · importShareable, privacy-safe memory bundles (with /preview variants).
GET /healthzHealth probe.

Capture requests still require writer_id as an advisory activity label, but v2 derives durable authorship and permissions from the authenticated principal. Changing the label does not impersonate another principal or grant access.

A five-line integration

import requests

BASE, TOKEN = "http://127.0.0.1:4040", "<your Memory Layer service token>"
r = requests.post(f"{BASE}/v1/query", json={"project": "demo", "query": "How does auth work?"},
                  headers={"Authorization": f"Bearer {TOKEN}"})
print(r.json()["answer"], r.json()["answer_citations"])

Typed Python and TypeScript clients generated from the spec are on the roadmap.

© 2026 Olivier Van Acker (3vilM33pl3). Memory Layer is AGPL-3.0-or-later with commercial licensing available.