MemoryRouterMemoryRouter

Keys & Usage Modes

Memory Keys vs Provider Keys, and the three ways to use the MemoryRouter proxy.

Keys & Usage Modes

MemoryRouter uses a two-key system, and there are three distinct ways to wire it into your app. The piece people get stuck on is where your provider API key goes (or whether MemoryRouter ever sees it at all). This page is the single, authoritative answer.

The two key types

Memory Key (mk_…): your credential for MemoryRouter itself. It authenticates the request and points to a single user-scoped memory vault (retrieval + storage boundary). In a multi-user product, you issue one stable Memory Key per end user. See Core concepts and Authentication.

Provider Keys: your real API keys for the model providers (OpenAI, Anthropic, Google, etc.). These authenticate with the model provider, not with MemoryRouter. They are completely decoupled from your Memory Key, so you can rotate a provider key without touching any user's memory. Depending on the usage mode below, MemoryRouter may use a stored provider key, receive one per request, or never see one at all.


Three ways to use MemoryRouter

1. BYOK per-call (pass-through)

What it is: You call the MemoryRouter proxy, but you send your provider API key on every request. MemoryRouter uses it to authenticate with the provider for that single call and then forwards the response back. The X-Memory-Key (or mk_…) identifies the vault; the provider key authenticates with the model.

Where your provider key goes: In the request. There are two equivalent, fully supported ways to send it, so pick whichever fits your client. Both behave identically: MemoryRouter does not store the key. It is used for that one request and discarded.

MethodHow you send itBest for
A. Drop-in (recommended)Put the provider key in Authorization: Bearer sk-… and the Memory Key in X-Memory-Key.Existing OpenAI/Anthropic SDKs: set api_key to your provider key and add one header. No code changes beyond the base URL.
B. Explicit headerPut the provider key in X-Provider-Key: sk-… and the Memory Key in Authorization: Bearer mk_… (or X-Memory-Key).Clients where you'd rather keep Authorization as your MemoryRouter credential and pass the provider key as a separate, clearly-named header.

Use A if you're pointing an existing provider SDK at MemoryRouter (most common). Use B if you want the provider key in its own dedicated header. They're two paths to the same result, not a fallback or a guess.

When to use it: Production apps that already manage their own provider keys (vaults, rotation, per-tenant keys) and don't want any provider credentials stored server-side at MemoryRouter.

from openai import OpenAI

client = OpenAI(
    api_key="sk-your-openai-key",          # goes to the provider
    base_url="https://api.memoryrouter.ai/v1",
    default_headers={
        "X-Memory-Key": "mk_xxxxxxxxxxxxxxxx"  # MemoryRouter vault auth
    },
)

response = client.chat.completions.create(
    model="openai/gpt-5.5",
    messages=[{"role": "user", "content": "My name is Alice"}],
)
curl -X POST https://api.memoryrouter.ai/v1/chat/completions \
  -H "X-Memory-Key: mk_xxxxxxxxxxxxxxxx" \
  -H "Authorization: Bearer sk-your-openai-key" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-5.5", "messages": [{"role": "user", "content": "My name is Alice"}]}'

See Authentication → Pass-Through Mode and the API Quickstart.


2. Stored provider keys

What it is: You save your provider keys once in the dashboard. After that you only send your Memory Key, and MemoryRouter looks up the stored key and calls the model on your behalf. This is the simplest integration and the default the API Quickstart assumes.

Where your provider key goes: Saved in the dashboard at app.memoryrouter.ai → Provider Keys (encrypted at rest). MemoryRouter stores it so it can call the provider for you. Your app never sends a provider key on the request.

When to use it: The easiest way to get started and the easiest way to test in the dashboard. This is also the mode that unlocks the full model selector in the dashboard Testing and Playground pages (see the note below).

from openai import OpenAI

client = OpenAI(
    api_key="mk_xxxxxxxxxxxxxxxx",          # Memory Key only
    base_url="https://api.memoryrouter.ai/v1",
)

response = client.chat.completions.create(
    model="openai/gpt-5.5",
    messages=[{"role": "user", "content": "My name is Alice"}],
)
curl -X POST https://api.memoryrouter.ai/v1/chat/completions \
  -H "Authorization: Bearer mk_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-5.5", "messages": [{"role": "user", "content": "My name is Alice"}]}'

Add your keys in the dashboard, then any model from a provider you've configured becomes available. See Authentication → Store in Dashboard.


3. Retrieval-only (local inference mode)

What it is: Your app calls the model provider directly and uses MemoryRouter only for retrieval and storage. You call POST /v1/memory/prepare to get the user's memory as text, inject it into your own prompt, call your provider yourself, then call POST /v1/memory/ingest to store the completed exchange.

Where your provider key goes: Nowhere near MemoryRouter. Your provider key stays inside your own stack. MemoryRouter never sees it and never sees your inference traffic. This is the maximum-privacy option.

When to use it: You already own provider routing, run your own model gateway, or need full control over streaming, retries, evals, and logging, and you want provider keys to never touch MemoryRouter. Full guide: Local inference mode.

# 1. Retrieve memory (Memory Key only, no provider key)
curl -X POST https://api.memoryrouter.ai/v1/memory/prepare \
  -H "Authorization: Bearer mk_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: conversation_abc" \
  -d '{"messages": [{"role": "user", "content": "What should I focus on today?"}]}'

# 2. Inject the returned `context` into your own prompt and call your provider DIRECTLY
#    (your keys, your routing; MemoryRouter is not involved here)

# 3. Store the completed exchange (returns 202, stored in background)
curl -X POST https://api.memoryrouter.ai/v1/memory/ingest \
  -H "Authorization: Bearer mk_xxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -H "X-Session-ID: conversation_abc" \
  -d '{
    "model": "openai/gpt-5.5",
    "messages": [
      {"role": "user", "content": "What should I focus on today?"},
      {"role": "assistant", "content": "Focus on the launch checklist and your 6am training block."}
    ]
  }'

prepare returns a ready-to-inject context string (or null when nothing relevant is found); ingest accepts the exchange and stores it asynchronously. See Local inference mode for request/response fields and a full TypeScript example.


Comparison

ModeProvider key locationDoes MemoryRouter store it?Dashboard model selector?Best for
1. BYOK per-callSent on each request (Authorization / X-Provider-Key)No, used per request, never storedNo, keys aren't saved server-sideProduction apps managing their own provider keys
2. Stored provider keysSaved in the dashboard (Provider Keys)Yes, encrypted at restYes, unlocks the full selectorFastest start; in-dashboard testing
3. Retrieval-onlyStays in your own stackNo, MemoryRouter never sees itNo, MR isn't in the model pathMax privacy; you own inference

All three modes use the same Memory Key, and the key mode suffixes (:read, :write, :off) work in every mode to control retrieval and storage.


To unlock the dashboard model selector, add a Provider Key

The model selector in the dashboard Testing and Playground pages can only offer models for providers you've configured. With no stored provider keys, you're limited to the default model. To see and test all available models in-dashboard, add a Stored provider key (mode 2) at app.memoryrouter.ai → Provider Keys. Once a provider key is saved, every model from that provider appears in the selector.

BYOK per-call (mode 1) and Retrieval-only (mode 3) are for your application code. They do not populate the in-dashboard model selector, because the dashboard has no provider key to call models with.

On this page