The Key Is the Unit of Deletion
Someone asks you to delete their account. You remove the user record, the session tokens, the uploads, and the billing row. Then you go looking for the AI memory and find one key in an environment variable that every user in the product has been sharing since March.
That is the failure this post is about, and it does not start at deletion. It starts on the afternoon you first wired memory in.
The key is the address
MemoryRouter scopes retrieval to the vault a Memory Key points to. A request authenticated with one user's key reaches that user's vault and stops there. Nothing in the call carries a user id to filter by. The key is the address, not a label stuck onto the data afterwards.
That gets pitched as the isolation story, correctly. What people read is the part about one customer never seeing another's context. What they skip is what the same split does for removal, which sets the price of a support ticket two years later.
What the delete call needs
The call is DELETE /v1/memory, authenticated with the key that belongs to that user. It clears the memories stored in that vault.
Two requirements fall out of that sentence. The key has to exist per user, and it has to be reachable by your code at deletion time. If your provisioner mints keys lazily and never stores the mapping, you own a vault you can no longer address, which is worse than a vault you forgot about.
The rest of the lifecycle is written up in the user lifecycle docs, including export, rotation, and where the delete call belongs in your account deletion flow.
The shortcut that gets shipped
The dashboard hands you a working key before you have a single user. Most people paste that key into their app, ship, and have memory working the same afternoon. At three users it is a reasonable decision.
At three hundred it means every customer's context sits in one vault. Your delete path now has two settings: all of it, or none of it. Nobody notices in staging because nothing breaks. Retrieval just gets a little noisier as details belonging to other people start competing for the same window. By the time the first deletion request arrives, the shared key is load bearing and unwinding it is a project.
Mint one per user at signup
Provisioning is one call. Send your account key, name the key after the user, and store the mapping where the rest of your user data lives.
curl -X POST https://api.memoryrouter.ai/v1/keys \
-H "Authorization: Bearer $MEMORYROUTER_ACCOUNT_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "user:42" }'
Provision on first use if you prefer. A vault does not need to exist until that person makes an AI call. What matters is that the link between a user and their vault lands in a table you control, not in a log line and not in a comment.
Rotation is a credential problem
If a key leaks, mint a fresh one and repoint the mapping. Your mapping is what ties a person to their vault, so rotation is a row update rather than a migration. Do not treat the key string as the person's identity. Treat it as a credential that happens to address one.
The security page has the rest of that posture, including what the model provider does and does not receive.
Scopes limit damage, they do not draw the boundary
Keys take mode suffixes, so one key can recall only, store only, or pass through without touching memory. On the MCP server the four scopes are independent of each other. Write does not imply recall, and reflection authority does not imply deletion, which means a connector installed to file notes cannot wipe a vault.
That is worth having and it does not replace per-user keys. A scope constrains a tool's reach. The key decides whose vault that reach lands in.
The one test that settles it
Seed a disposable fact against a test user's key, run a search, and watch it come back. Then call DELETE /v1/memory with that same key and run the identical search.
An empty result is the only evidence that deletion reached retrieval. Everything else is a flag in a table that may or may not be checked by the code path that answers questions.
Export runs on the same boundary
If your product offers a data export, read that person's stored memories through POST /v1/memory/search and put the results in the package you already send. The boundary that lets you delete one user's memory cleanly is the boundary that lets you hand it back, and both of them are decided by the same provisioning step.
If you already shipped the shared key
There is no split call. A vault cannot be cut back into users after the fact, because nothing recorded who said what. The way out is to mint a key per user, rebuild each vault from your own transcripts with POST /v1/memory/upload scoped to that user, check recall per user, and only then clear the shared vault.
At a few hundred users that is a weekend. At a few thousand it is a quarter, and you are reconstructing something you could have had for free. Doing it at signup is one curl call inside the code that already creates the user.