Overview
MeeMesh gives your app, agent, or robot long-term memory that survives across conversations, LLM providers, and time. You store facts and conversation turns; MeeMesh recalls the relevant ones semantically when you ask.
Base URL: https://api.meemesh.com · All request/response bodies are JSON.
The web dashboard lives at https://dashboard.meemesh.com — programmatic
calls and MCP connectors should always use api.meemesh.com.
All /v1 endpoints except /v1/register require the
X-API-Key header.
Two memory systems are available per request (see Memory systems): legacy, a classic vector store, and meemesh, the PES engram store whose recall returns verbatim evidence with a confidence score — or formally abstains instead of guessing.
New: MeeMesh is also an MCP connector — plug your memory directly into Claude, ChatGPT, or Gemini and carry it across AI vendors.
Quickstart (60 seconds)
# 1. Register once — save the api_key it returns
curl -X POST https://api.meemesh.com/v1/register \
-H "Content-Type: application/json" \
-d '{"name": "Kitchen Robot 7", "kind": "robot"}'
# 2. Store a memory
curl -X POST https://api.meemesh.com/v1/remember \
-H "X-API-Key: mm_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"text": "Mr Smith takes his coffee black at 7am", "memory_system": "meemesh"}'
# 3. Recall it — note the evidence and confidence in the response
curl -X POST https://api.meemesh.com/v1/recall \
-H "X-API-Key: mm_YOUR_KEY" -H "Content-Type: application/json" \
-d '{"query": "how does Mr Smith take his coffee", "memory_system": "meemesh"}'
Authentication
Register once via POST /v1/register. The response contains your
api_key (prefix mm_). Send it on every other
/v1 call:
X-API-Key: mm_xxxxxxxxxxxxxxxxxxxxxxxx
Keys identify a user (an app, robot, or person). Each user's memories are fully isolated from every other user's. Treat the key like a password — anyone holding it can read and write that user's memory.
Users & sessions
- User — your app/robot/person. One API key each. Hard isolation boundary.
- Session — a memory scope inside a user: one conversation thread, one
robot deployment, one household. Every memory carries
user_id+session_id. Adefaultsession always exists; writing to a newsession_idauto-creates it. - Recall scope — search one session (
scope: "session") or the whole user across all sessions (scope: "user", the default).
Memory systems
Every store/recall/chat request accepts an optional memory_system field.
Omit it to use the server default (legacy). Systems store separately —
a memory written to one is not visible to the other, which makes side-by-side
comparison possible.
legacy | meemesh | |
|---|---|---|
| Design | Vector store, nearest-neighbor recall | PES engrams: memory objects + compressed trace vault |
| Irrelevant query | Still returns the closest matches | Formally abstains: "abstained": true |
| Evidence | — | Every hit carries the verbatim stored text |
| Confidence | Mirrors similarity score | Calibrated: similarity × capture confidence × trace tier |
| Places | — | Place entities with containment ("what happened at X") |
GET /memory_systems —
new systems (competitor adapters and future MeeMesh phases) appear there without client changes.The recall contract
All recall-shaped responses share this structure:
{
"results": [
{
"id": "eng_9f3a1c...",
"text": "Mr Smith takes his coffee black at 7am",
"meta": { "session_id": "smith-household", "role": "note", "ts": 1751930000, ... },
"score": 0.81, // raw similarity 0..1
"confidence": 0.79, // calibrated confidence 0..1
"evidence": "Mr Smith takes his coffee black at 7am" // verbatim trace (meemesh)
}
],
"abstained": false, // true -> the system found nothing relevant enough
"reason": null, // human-readable abstention reason
"memory_system": "meemesh"
}
abstained is
true, results is empty — your integration should treat it as
"no memory", not as an error. This is the cite-or-abstain guarantee: MeeMesh never
fabricates a nearest-neighbor answer to fill silence.Spatial memory Phase 1.5
The meemesh system keeps place entities: named places your
memories link to, with a containment hierarchy (Blue Bottle ⊂ Shibuya ⊂ Tokyo).
Places are created two ways — automatically, when a stored text explicitly mentions
one ("planning session at Blue Bottle in Shibuya"), or explicitly via
POST /v1/places.
Ask "what happened at X" by adding place to
/v1/recall. Recall inherits downward through
containment: querying "Tokyo" surfaces episodes recorded at Blue Bottle,
and every such hit carries a place_path receipt showing the derivation —
hierarchy-based inference is always evidence-linked, never a guess.
Cite-or-abstain extends to the spatial axis with two formal abstentions:
an unknown place ("no known place matching 'Atlantis'") and a known
place with no linked memories. Coordinates (lat/lon) are
optional enrichment on /v1/remember — nothing requires them, and no
location permission is ever needed for text-derived places.
alias_of link rather than deleted.Visual memory Phase 4
MeeMesh can now remember what it sees. An image sent to
POST /v1/see becomes a visual memory with the same
guarantees as text: the original image is archived verbatim in the binary vault
(content-addressed and deduplicated — re-seeing the same photo reinforces the memory
instead of storing a copy), and a text gist of the image joins the shared
recall index. Because the gist is the interlingua, ordinary text recall finds visual
memories with no new query machinery — ask "what did the whiteboard say?"
and the photo of the whiteboard comes back, with its image as the receipt.
Two capture paths:
1. caption — you supply the gist ("bring your own percept": an on-device
captioner, user-typed text, an OCR pass). No server-side model
call is made; capture confidence is 1.0 — you asserted it.
2. describe — the server's multimodal model distills the gist, visible
objects, and any text in the image. The model's own confidence
becomes the engram's capture_conf, so uncertain perception
honestly lowers recall confidence downstream:
confidence = similarity × capture_conf × trace-tier penalty.
Recall hits for visual memories carry meta.media_sha — the handle for
fetching the image itself from GET /v1/media/{sha}
(strictly ownership-checked). Cite-or-abstain is unchanged; pixels never enter the
vector index, so the embedding space stays uniform and rebuildable. Gists flow
through the same spatial extraction as text, so a photo captioned "at Blue Bottle in
Shibuya" is linked to those places and answers
"what happened at Shibuya".
Env: MEEMESH_VISION_PROVIDER (openai | gemini, auto-picked
from available keys), MEEMESH_VISION_MODEL (default
gpt-4o-mini / gemini-2.0-flash),
MEEMESH_VISION_MAX_BYTES (default 8 MB).
Audio memory Phase 5
MeeMesh also remembers what it hears. A recording sent to
POST /v1/hear becomes an audio memory with the
same guarantees as text and vision: the original recording is archived verbatim in
the binary vault (content-addressed and deduplicated — re-hearing the same clip
reinforces the memory and never pays for a second transcription), and a
transcript-anchored text gist joins the shared recall index. Ask
"what did she say in the voice note?" in plain text and the recording
comes back, with the audio itself as the receipt.
Two capture paths:
1. transcript — you supply the gist ("bring your own percept": on-device
speech-to-text, a call stack's ASR, human notes). No server-side
model call is made; capture confidence is 1.0 — you asserted it.
2. transcribe — the server transcribes/describes the recording. With
whisper models, capture_conf is derived from the segments'
average log-probability — an honest per-recording estimate,
not a constant. Gemini returns a structured percept that also
captures non-speech sounds (an alarm, applause, a dog barking).
Either way: confidence = similarity × capture_conf × tier penalty.
Recall hits for audio memories carry meta.media_sha — fetch the
recording from GET /v1/media/{sha} (strictly
ownership-checked). Cite-or-abstain is unchanged; waveforms never enter the vector
index. Gists flow through spatial extraction, so a voice note mentioning
"the Marina Bay office" links to that place.
Env: MEEMESH_AUDIO_PROVIDER (openai | gemini, auto-picked
from available keys), MEEMESH_AUDIO_MODEL (default
whisper-1 / gemini-2.0-flash),
MEEMESH_AUDIO_MAX_BYTES (default 16 MB).
Open modality registry PES v2.1
Senses are not special cases in MeeMesh — they are entries in an open registry
(GET /v1/modalities). Every modality
declares its media class: rich/continuous media (text,
vision, audio — verbatim vault archive plus a text gist) or
scalar/structured telemetry (temperature, heart rate, tactile
pressure — typed values with templated gists, arriving with the first telemetry
sense). The text gist is the universal interlingua: because every sense distills
into it, all modalities share one embedding space and one recall path, and adding
a new sense never touches core engram logic.
Write-time admission runs through an ordered gate pipeline shared by all modalities — the trigger/gating subsystem. Built-in gates stop zero-information utterances and bare recall questions from polluting the store; deployments can register additional gates (PII filters, compliance policies) without forking the core.
MCP connector — memory inside Claude, ChatGPT & Gemini Phase A
MeeMesh is also a remote MCP server (Model Context Protocol, Streamable HTTP). Add it as a connector and the AI you already use gains persistent, portable memory — stored here, available on every connected platform. Store a fact in Claude, recall it in Gemini, with evidence receipts.
Your connector URL embeds your API key:
https://api.meemesh.com/mcp/mm_YOUR_KEY
Claude
Settings → Connectors → Add custom connector → paste the URL → Connect.
Works on all plans, including free. In the connector's tool permissions, a sensible
split: allow memory_search / memory_context always
(read-only), keep memory_forget / memory_update on approval,
and set memory_settings to never — change backend and mode from
the dashboard buttons instead.
Gemini CLI
// ~/.gemini/settings.json
{ "mcpServers": { "meemesh": { "httpUrl": "https://api.meemesh.com/mcp/mm_YOUR_KEY" } } }
ChatGPT
Requires OAuth 2.1 (Phase B, in development). The tool surface will not change.
Verify by hand
# handshake
curl -s https://api.meemesh.com/mcp/mm_YOUR_KEY \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl"}}}'
# list tools (expect 7)
curl -s https://api.meemesh.com/mcp/mm_YOUR_KEY \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
The 7 tools
The connected AI decides when to call these; you steer with plain language ("remember that…", "what do you know about…", "forget that").
| Tool | What it does |
|---|---|
memory_search | Find relevant memories. Empty query = most recent.
On meemesh, results carry verbatim evidence receipts, and
abstained: true is a reliable "nothing stored". Optional filters:
memory_types, time_range: {"days": n}. |
memory_store | Save a durable memory with type
(fact, preference, project, goal, decision, commitment, …) and
importance (0–1). On meemesh the raw content is also
archived verbatim in the evidence vault. |
memory_update | Correct an outdated memory. On
meemesh the old engram is tombstoned and linked as superseded —
history preserved, contradiction removed from recall. |
memory_forget | Default tombstone (unrecallable,
audit record kept) or permanent_delete. Given only a query, returns
candidates to confirm by id first. |
memory_context | One packed context packet for the current
conversation (relevant memories + open commitments + recent items) within a
token_budget. Called once at conversation start instead of many searches. |
memory_log_turn | Full-backup path: archives a conversation
turn. Active only when the connection's mode is full. |
memory_settings | Get/set this user's default backend and memory mode from chat. Recommended: disable in Claude's permissions and use the dashboard buttons instead. |
Store a memory with type: "commitment" ("I promised to review
the spec by Friday") and memory_context will surface it automatically in
future conversations — on every connected platform. Prospective memory, cross-AI.
Backends & memory modes
Backend routing
Every tool accepts an optional backend; without it, the user's saved
default applies (initially legacy, so connector memories are shared with
this dashboard's chat from day one).
| Backend | Behavior over the connector |
|---|---|
legacy | Classic vector store. Always returns nearest neighbors; no evidence, no abstention. Updates and forgets are permanent (no supersedence history). |
meemesh | PES engrams + trace vault. Recall cites verbatim evidence or formally abstains; updates supersede with history; forgets tombstone by default. |
Memory modes
| Mode | What the connected AI is instructed to do |
|---|---|
selective default | Store only
noteworthy, durable facts via memory_store. |
summaries | Also store a distilled summary at natural breakpoints (topic change, conversation end). |
full | Also call memory_log_turn after every
reply, archiving the conversation. On meemesh: user turns become
recallable engrams with receipts; assistant turns and low-information turns are
archived in the vault but excluded from recall by design. |
Connector settings endpoints
The dashboard's MCP Connector card uses these; you can call them directly.
GET/mcp-settings/{user_id}
{ "settings": { "default_backend": "legacy", "memory_mode": "selective" },
"available_backends": ["legacy", "meemesh"],
"available_modes": ["selective", "summaries", "full"] }
POST/mcp-settings/{user_id}
{ "default_backend": "meemesh", "memory_mode": "full" }
Settings are per user, not per platform: one change applies to
every AI connected with that user's key. Invalid values return 400;
unknown users 404.
Import chat history M3
Bring your existing conversations into MeeMesh: request your official data export
from ChatGPT (Settings → Data controls → Export) or Claude (Settings → Privacy →
Export data), then upload the zip — or the conversations.json inside it —
unmodified. The format is auto-detected. This also captures history from
before you ever connected MeeMesh.
POST/v1/import?source=auto&include_assistant=false&dry_run=false
# preview what an import would do (nothing is written)
curl -s "https://api.meemesh.com/v1/import?dry_run=true" \
-H "X-API-Key: mm_YOUR_KEY" \
--data-binary @chatgpt-export.zip
# run it
curl -s "https://api.meemesh.com/v1/import" \
-H "X-API-Key: mm_YOUR_KEY" \
--data-binary @chatgpt-export.zip
# → { "job_id": "imp_…", "status": "running", "conversations": 214, "total_turns": 6031,
# "estimated_disk_mb": 52.3, … }
# poll progress
curl -s "https://api.meemesh.com/v1/import/imp_JOBID" -H "X-API-Key: mm_YOUR_KEY"
What happens to each turn — the percept/engram split doing its job:
project-type memories and the docs as semantic memories
(and is forward-compatible: if a future export adds in-Project conversations, they
are detected and imported as full conversations automatically). Until then, capture
in-Project work live with the MCP connector (full-backup mode inside the Project),
or ask the Project to write a summary and store it via memory_store.| Turn | Vault (evidence) | Recall index |
|---|---|---|
| Your messages | verbatim percept | episodic engram with receipt, timestamp backdated to the original conversation date |
| Assistant replies | verbatim percept | excluded by default
(include_assistant=true to index them too) |
| Low-information turns ("ok", "thanks") | verbatim percept | gated out |
Import targets the meemesh backend only — full history in
the vault, recall index stays curated. Re-running the same import is safe: exact
duplicates are detected by content hash before any embedding cost. Both the dry run
and the import kickoff return estimated_disk_mb — roughly 18 KB per
recallable memory (vector index + row) plus the compressed vault, deliberately a
slight over-estimate — so check it against your free disk before committing. Caps:
20 000 turns per run, 100 MB per upload (env-tunable). Once imported, the
history is a ready corpus for the consolidation daemon to distill into semantic
facts. The dashboard's Import / Export card wraps all of this with a file
picker and progress display.
Export your memory
Your memory belongs to you, so it can leave. One request returns everything MeeMesh holds for your user — every engram (including superseded ones, with their full audit chain) alongside its verbatim vault evidence, plus legacy vector memories.
GET/v1/export?backend=all
curl -s "https://api.meemesh.com/v1/export?backend=all" \
-H "X-API-Key: mm_YOUR_KEY" -o meemesh_export.json
{ "exported_at": "2026-07-20T…", "user_id": "…",
"backends": {
"meemesh": { "count": 96, "engrams": [
{ "id": "…", "kind": "episodic", "gist": "…", "salience": 0.6,
"ts": 1718000000.0, "valid_to": null, "superseded_by": null,
"derived_from": [], "evidence": "verbatim original text…" } ] },
"legacy": { "count": 44, "memories": [ … ] } } }
backend=meemesh or backend=legacy narrows the
export. The download is plain JSON — no proprietary format, no lock-in.
POST/v1/registerno auth
Create a user and receive an API key. Call once and persist the key.
// request
{ "name": "Kitchen Robot 7", "kind": "robot", "user_id": "kitchen-robot-7" }
// kind: "app" | "robot" | "human" · user_id optional (slug is generated from name)
// response
{ "ok": true, "user_id": "kitchen-robot-7", "name": "Kitchen Robot 7",
"api_key": "mm_...", "kind": "robot",
"usage": "Send header 'X-API-Key: <api_key>' on all /v1 requests." }
GET/v1/me
Who am I: your profile, sessions, and memory counts per system.
{ "user_id": "kitchen-robot-7", "name": "Kitchen Robot 7", "kind": "robot",
"sessions": [ { "session_id": "default", "name": "default", "created": 1751... } ],
"memories": { "legacy": 5, "meemesh": 12 } }
POST/v1/sessions · GET/v1/sessions
Create a session / list your sessions. Creating is optional — writing to a new
session_id auto-creates it.
// POST request // POST response
{ "name": "smith-household" } { "ok": true, "session_id": "smith-household", ... }
POST/v1/remember
Store one memory.
// request
{ "text": "Mr Smith takes his coffee black at 7am",
"session_id": "smith-household", // default: "default"
"role": "note", // free-form tag: note | user | assistant | sensor ...
"memory_system": "meemesh", // default: server default (legacy)
"place": "Smith kitchen", // optional — resolved place identity (Phase 1.5)
"lat": 35.6595, "lon": 139.7005 } // optional pose enrichment; never required
// response (meemesh includes the trace receipt; places lists spatial links)
{ "ok": true, "id": "eng_9f3a1c...", "trace_ref": "vault://ab/abf3...",
"places": ["Smith kitchen"],
"session_id": "smith-household", "memory_system": "meemesh", "total": 13 }
Without an explicit place, meemesh conservatively extracts
place mentions from the text itself ("at Blue Bottle in Shibuya" links the memory to
Blue Bottle and records Shibuya as its parent). See Spatial memory.
POST/v1/recall
Semantic recall. Returns the recall contract plus
scope and session_id echoes.
// request
{ "query": "how does Mr Smith take his coffee",
"k": 5, // max results
"scope": "user", // "user" (all sessions) | "session"
"session_id": null, // required when scope = "session"
"place": null, // set -> spatial recall ("what happened at X")
"memory_system": "meemesh" }
// spatial recall: place is the filter, query (optional) re-ranks within it
{ "place": "Tokyo", "query": "investor meeting", "memory_system": "meemesh" }
// spatial response adds the resolved place and per-hit place_path receipts
{ "results": [ { ..., "meta": { ..., "place_path": ["Blue Bottle","Shibuya","Tokyo"] } } ],
"abstained": false, "reason": null,
"place": { "name": "Tokyo", "path": ["Tokyo"] }, "memory_system": "meemesh" }
GET/v1/memories?limit=25&session_id=&memory_system=
Most recent memories, newest first — a browse view, no semantic search.
POST/v1/chat
One-call convenience: recalls relevant memories, injects them into the system prompt, calls the LLM, and (optionally) stores the exchange as new memories.
// request
{ "provider": "openai", // openai | gemini | deepseek | ollama
"model": "gpt-4o-mini",
"message": "What do you know about Mr Smith?",
"session_id": "smith-household",
"k": 5,
"store": true, // store this turn as memories
"recall_scope": "user",
"memory_system": "meemesh" }
// response
{ "reply": "...", "used_memories": [ ...recall results... ],
"abstained": false, "abstain_reason": null,
"memory_system": "meemesh", "provider": "openai", "model": "gpt-4o-mini",
"user_id": "kitchen-robot-7", "session_id": "smith-household", "total": 15 }
When the memory system abstains, the model is explicitly told no relevant memories exist, so it answers honestly instead of hallucinating a recollection.
POST/v1/forget
Delete your memories. Scope by session and/or memory system; defaults are broad.
// request — both fields optional
{ "session_id": "smith-household", // null -> ALL your sessions
"memory_system": "meemesh" } // null -> ALL memory systems
// response
{ "ok": true, "deleted": { "meemesh": 12 }, "total": { "legacy": 5, "meemesh": 0 } }
GET/v1/places · POST/v1/placesPhase 1.5
GET lists your place entities — the spatial index of your memory —
with containment paths and live memory counts.
// GET /v1/places?limit=100
{ "places": [
{ "id": "plc_4d2e...", "name": "Blue Bottle", "kind": "place",
"lat": 35.6595, "lon": 139.7005, "parent_id": "plc_a1b2...",
"path": ["Blue Bottle", "Shibuya", "Tokyo"],
"memory_count": 3, "salience": 0.7, "attrs": {} } ],
"memory_system": "meemesh" }
POST declares a place explicitly: containment, coordinates, attributes,
or an alias link (the non-destructive merge for duplicate names).
// state containment — explicit declarations may re-parent
{ "name": "Shibuya", "parent": "Tokyo" }
// merge a duplicate name into its canonical place
{ "name": "Blue Bottle Shibuya", "alias_of": "Blue Bottle" }
// response
{ "ok": true, "place": { ..., "path": ["Shibuya", "Tokyo"] }, "memory_system": "meemesh" }
Attributes (attrs) describe an already-identified place —
"quiet", "has wifi" — and are never used as identity criteria.
POST/v1/seePhase 4
Store one visual memory. Base64 image bytes only — no data: prefix, no
URLs. Allowed mimes: jpeg, png, webp, gif.
// request — caption path (no server-side model call)
{ "image_b64": "<base64>", "mime": "image/jpeg",
"caption": "Team lunch at Blue Bottle in Shibuya",
"session_id": "default",
"place": "Blue Bottle", // optional resolved place (Phase 1.5)
"lat": 35.6595, "lon": 139.7005, // optional pose enrichment
"memory_system": "meemesh" }
// request — describe path (server-side multimodal model)
{ "image_b64": "<base64>", "mime": "image/png",
"hint": "photo of our planning whiteboard" } // optional context
// response
{ "ok": true, "id": "eng_9f3a1c...", "gist": "A whiteboard covered in ...",
"media_sha": "4be1...64-hex...", "trace_ref": "vault://4b/4be1...",
"capture_conf": 0.82, "modality": "vision", "places": ["Blue Bottle"],
"session_id": "default", "memory_system": "meemesh", "total": 14 }
// duplicate image (same bytes, same scope): reinforced, not re-stored
{ "ok": true, "id": "eng_9f3a1c...", "media_sha": "4be1...", "deduplicated": true }
Without a configured vision provider the describe path returns
502 with an explanation — the caption path always works. Oversize or
invalid images are rejected with 400 before anything is stored.
POST/v1/hearPhase 5
Store one audio memory. Base64 audio bytes only — no data: prefix, no
URLs. Allowed mimes include mp3, wav, m4a/mp4, aac, webm, ogg, flac.
// request — transcript path (no server-side model call)
{ "audio_b64": "<base64>", "mime": "audio/m4a",
"transcript": "Standup recap: demo moved to Thursday at the Marina Bay office",
"session_id": "default",
"place": "Marina Bay office", // optional resolved place (Phase 1.5)
"lat": 1.2839, "lon": 103.8607, // optional pose enrichment
"memory_system": "meemesh" }
// request — transcribe path (server-side model)
{ "audio_b64": "<base64>", "mime": "audio/webm",
"hint": "voice note about the investor demo" } // optional context
// response
{ "ok": true, "id": "eng_2c8d0e...", "gist": "A voice note about ... Transcript: ...",
"transcript": "Remember the investor demo is moved to Thursday ...",
"media_sha": "9d27...64-hex...", "trace_ref": "vault://9d/9d27...",
"capture_conf": 0.74, "modality": "audio", "places": ["Marina Bay office"],
"session_id": "default", "memory_system": "meemesh", "total": 15 }
// duplicate recording (same bytes, same scope): reinforced, not re-stored
{ "ok": true, "id": "eng_2c8d0e...", "media_sha": "9d27...", "deduplicated": true }
Without a configured audio provider the transcribe path returns
502 with an explanation — the transcript path always works (pairs
naturally with on-device STT). Oversize or invalid recordings are rejected with
400 before anything is stored.
GET/v1/modalitiesPES v2.1
The open modality registry: every registered sense with its media class, mime allowlist, size cap, and capture module — plus the ordered write-time gate pipeline. No authentication required.
// response
{ "modalities": [
{ "name": "text", "media_class": "rich", "allowed_mimes": null, "max_bytes": null, ... },
{ "name": "vision", "media_class": "rich", "allowed_mimes": ["image/jpeg", ...], "max_bytes": 8388608, ... },
{ "name": "audio", "media_class": "rich", "allowed_mimes": ["audio/mpeg", ...], "max_bytes": 16777216, ... } ],
"gates": ["low_information", "bare_question"] }
GET/v1/media/{sha}Phase 4
Fetch the verbatim media (image or recording) behind a memory — the receipt. sha comes
from media_sha on a recall hit, /v1/memories row, or a
/v1/see / /v1/hear response. Responds with the raw bytes and original mime type.
curl -s "https://api.meemesh.com/v1/media/4be1...&memory_system=meemesh" \
-H "X-API-Key: mm_YOUR_KEY" -o receipt.jpg
Strictly ownership-checked: media resolves only for the user whose
engram references it; everyone else gets 404 (no existence oracle).
Forgetting the memory garbage-collects the media from the vault.
DELETE/v1/me
Self-service account deletion: removes the user, all sessions, and all memories in every system. The API key stops working immediately. Irreversible.
GET/memory_systemsno auth
Registered memory systems with capability flags — use it to build system pickers or feature-gate on capabilities.
{ "memory_systems": [
{ "name": "legacy", "label": "Legacy (vector store)", "description": "...",
"capabilities": { "abstention": false, "evidence": false, "multimodal": false,
"spatial": false, "consolidation": false }, "default": true },
{ "name": "meemesh", "label": "MeeMesh PES (engrams)", "description": "...",
"capabilities": { "abstention": true, "evidence": true, "multimodal": false,
"spatial": false, "consolidation": false }, "default": false }
],
"default": "legacy" }
GET/healthno auth
Service status: per-system memory counts, user count, embedding config, and which LLM providers are enabled.
Python example
import requests
BASE = "https://api.meemesh.com"
# one-time setup
key = requests.post(f"{BASE}/v1/register",
json={"name": "My Agent", "kind": "app"}).json()["api_key"]
H = {"X-API-Key": key}
# store
requests.post(f"{BASE}/v1/remember", headers=H, json={
"text": "Project codename is Blue Lantern",
"memory_system": "meemesh",
})
# recall — handle abstention
out = requests.post(f"{BASE}/v1/recall", headers=H, json={
"query": "what is the project codename",
"memory_system": "meemesh",
}).json()
if out["abstained"]:
print("No memory of that:", out["reason"])
else:
top = out["results"][0]
print(top["text"], "| confidence:", top["confidence"])
print("evidence:", top["evidence"])
Errors
| Status | Meaning |
|---|---|
400 | Bad request — e.g. unknown memory_system, or scope: "session" without a session_id. The detail field explains. |
401 | Invalid or missing X-API-Key. |
404 | Unknown user or session. |
502 | An upstream LLM provider failed (chat only); detail carries the provider error. |
200 with "abstained": true. Design your integration to branch on it.Interactive explorer
A machine-generated OpenAPI explorer (Swagger UI) is available at
/docs — try any endpoint live from the browser.
This page is the curated guide; /docs is the exhaustive schema reference.
MeeMesh Memory Service · memory with receipts