twin memory

Authentication & keys

Every request carries a key for one of your projects and names one end user. A key either reads, or reads and writes.

Every request to twin memory sends two headers:

Authorization: Bearer tm_...
X-Twin-Account: user_42

The key says which organisation and project the request belongs to, and whether it may write. The header says which of your end users it is about. Neither one is ever a field in a request body.

Projects

An organisation has one or more projects, such as production and staging. A project is a separate set of end users: user_42 in staging and user_42 in production are two memories that never meet. Every key belongs to exactly one project, so the project is never something you send.

Use one project per environment, so test data cannot reach production and a test key cannot read real users.

Two kinds of key

KeyCan callGive it to
Readsearch, grep, read, ls, around, latest, overview, history, status, lineage, and the read tools over MCPAn agent, tool binding or MCP client that only reads
Read and writeEverything a read key can, plus add, forget, correct, versions, and memory_add over MCPYour backend, and an agent or MCP client that saves

A read key cannot change memory. A model holding one can search and read, but cannot add, erase or rewrite anything, so a prompt injection cannot make it do so either.

So: a read key for an agent that only reads, and a key that writes for an agent that saves what it learns. Over MCP, a key that writes adds one tool, memory_add; forget, correct and versions are never offered to a model, and stay with your backend over HTTP.

versions needs a write key even though it changes nothing. It returns text that was edited away, and a model should not be able to read what your backend replaced.

A read key sent to a write route is refused with 403:

{ "detail": "this key reads; writing takes a key that writes" }

Create a key

In the console, open API keys, choose the project, and create a key. Give it a label that says where it will live, such as backend-prod or agent-runtime, and choose read or read and write.

The key is shown once. Only its first characters, such as tm_AbC1234, are kept for display, so you can tell keys apart in the list. If you lose a key, create a new one and revoke the old one.

Where to keep each key

  • Write key: in your backend's secret store, read from an environment variable, or in the service that runs an agent that saves. Never in a browser, a mobile app, a public repository or a prompt.
  • Read key: in the service that runs your model or agent. It is still a secret: anyone holding it can read every end user in the project, because the end user is only a header.
  • Neither key in client code. Your users' browsers and apps call your backend. Your backend decides which end user a request is for and calls twin memory with that user's id.
export TWIN_MEMORY_API_KEY="tm_..."

Every example in these docs reads the key from TWIN_MEMORY_API_KEY.

Revoke a key

Revoke a key in API keys. It stops working at once, with no restart and no grace period. To rotate a key, create the new one, deploy it, then revoke the old one.

The end user header

X-Twin-Account is required on every request. Use the id your app already has for the user. Letters, digits, ., _ and - are allowed, starting with a letter or a digit. Inside twin memory the full id is your organisation, your project and this value joined by dots, and that whole id may be at most 64 characters, so the value you send has a shorter limit. End users & tenancy gives the exact number.

A missing or unusable header is refused with 400, before any memory is read:

{ "detail": "X-Twin-Account is not a usable end user id: '.bad' (letters, digits, '.', '_' and '-', starting with a letter or digit, at most 41 characters)" }

Errors

StatusMessageMeaning
401a bearer this service issued is requiredThe Authorization header is missing, or the key is not one twin memory issued, or it was revoked.
403this key reads; writing takes a key that writesA read key was sent to a write route. Use a read and write key.
400X-Twin-Account is required: ...The end user header is missing.
400X-Twin-Account is not a usable end user id: '...'The header has a character outside the allowed set, or is too long.

Every status is on the errors page.

On this page