Transfer and Graft
Copy memories between Memory Keys. Transfer all memories, or graft only the memories that match a search.
Transfer and Graft
Transfer and Graft copy memories from one Memory Key to another.
Both operations are non-destructive. The source vault is never changed.
Use them when you need to move memory between keys:
- Transfer: copy every memory from one key to another. Use this for migrations, backups, and full vault duplication.
- Graft: search one key, filter by similarity score, and copy only matching memories to another key. Use this to seed a team or org key from a personal key without copying unrelated memories.
The authenticated key is always the source key. destination_key is the key that receives the copied memories.
Base URL: https://api.memoryrouter.ai
Recommended workflow: dry run first
Always start with dry_run: true.
A dry run returns the memories that would be copied, including snippets, scores for graft, count, and estimated tokens. It does not write to the destination.
curl -X POST https://api.memoryrouter.ai/v1/memory/graft \
-H "Authorization: Bearer $SOURCE_MEMORY_KEY" \
-H "Content-Type: application/json" \
-d '{
"destination_key": "mk_destination",
"queries": ["architecture decisions", "deployment process", "customer context"],
"threshold": 0.5,
"limit": 50,
"dry_run": true
}'Response:
{
"dry_run": true,
"operation": "graft",
"source_key": "mk_abc…123456",
"destination_key": "mk_def…789012",
"queries": ["architecture decisions", "deployment process", "customer context"],
"threshold": 0.5,
"limit": 50,
"count": 3,
"estimated_tokens": 420,
"memories": [
{
"id": 184,
"snippet": "[USER] We decided to keep auth in the worker and avoid client-side provider keys...",
"role": "user",
"timestamp": 1781191200000,
"score": 0.78,
"estimated_tokens": 86
}
]
}If the preview looks right, send the same request with dry_run: false or omit dry_run.
Transfer all memories
POST /v1/memory/transfer
Copies every memory in the source key's core vault to the destination key.
curl -X POST https://api.memoryrouter.ai/v1/memory/transfer \
-H "Authorization: Bearer $SOURCE_MEMORY_KEY" \
-H "Content-Type: application/json" \
-d '{
"destination_key": "mk_destination",
"dry_run": true
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
destination_key | string | Yes | Writable Memory Key that receives the copied memories. |
dry_run | boolean | No | If true, preview only. No memories are written. |
embeddings | string | No | Embedding model vault to transfer. Defaults to the API default. |
Successful write response
{
"dry_run": false,
"operation": "transfer",
"source_key": "mk_abc…123456",
"destination_key": "mk_def…789012",
"copied": 128,
"deduped_or_skipped": 0,
"failed": 0,
"estimated_tokens": 18420,
"provenance": {
"origin_key": "mk_abc…123456",
"transferred_at": "2026-06-11T17:30:00.000Z"
}
}Graft selected memories
POST /v1/memory/graft
Runs one or more semantic searches against the source key. Memories with a score greater than or equal to threshold are copied to the destination key.
curl -X POST https://api.memoryrouter.ai/v1/memory/graft \
-H "Authorization: Bearer $SOURCE_MEMORY_KEY" \
-H "Content-Type: application/json" \
-d '{
"destination_key": "mk_org_team",
"queries": [
"business strategy for MemoryRouter",
"Claude Code integration decisions",
"customer onboarding lessons"
],
"threshold": 0.55,
"limit": 75,
"dry_run": false
}'Request body
| Field | Type | Required | Description |
|---|---|---|---|
destination_key | string | Yes | Writable Memory Key that receives the copied memories. |
queries | string[] | Yes | One or more semantic search queries. Empty arrays are rejected. |
threshold | number | No | Minimum similarity score from 0 to 1. Defaults to 0.5. |
limit | number | No | Max results per query. Defaults to 50. Max 500. |
dry_run | boolean | No | If true, preview only. No memories are written. |
embeddings | string | No | Embedding model vault to search and graft. Defaults to the API default. |
Successful write response
{
"dry_run": false,
"operation": "graft",
"source_key": "mk_abc…123456",
"destination_key": "mk_org…789012",
"queries": [
"business strategy for MemoryRouter",
"Claude Code integration decisions",
"customer onboarding lessons"
],
"threshold": 0.55,
"limit": 75,
"copied": 24,
"deduped_or_skipped": 3,
"failed": 0,
"estimated_tokens": 6120,
"provenance": {
"origin_key": "mk_abc…123456",
"transferred_at": "2026-06-11T17:30:00.000Z"
}
}Threshold guidance
Start broad, then tighten.
| Threshold | Behavior | Use |
|---|---|---|
0.4 to 0.5 | Broad recall | First-pass discovery, messy personal vaults, exploratory dry runs |
0.5 to 0.65 | Balanced | Team/org seeding from personal memory |
0.65 and up | Strict | Sensitive grafts where precision matters more than coverage |
Use multiple focused queries instead of one vague query. For example, use deployment process, customer objections, and pricing decisions instead of business stuff.
Dedupe behavior
Transfer and Graft are safe to re-run.
The destination vault dedupes by memory content hash. If the same memory is copied again, it is skipped instead of written a second time. The response reports skipped duplicates in deduped_or_skipped.
This makes retry safe after partial failure.
Provenance behavior
Copied memories are stamped with provenance metadata:
origin_key: a safe truncated form of the source keytransferred_at: the time the copy operation wrote the memory
Provenance is stored as metadata on the copied memory. It is not added to the memory text, so it does not pollute future retrieval context.
Permissions
The authenticated key is the source key.
Source requirements:
- The source key must be valid and active.
:readsource keys are allowed because they can read memory.:offsource keys are rejected.
Destination requirements:
destination_keymust be valid and active.destination_keymust be writable.mk_xxx:readis rejected.mk_xxx:offis rejected.- Source and destination cannot be the same key.
Any key can copy to any other key if the caller has the source key and the destination key is writable. There are no personal/org walls.
Errors
| Status | When |
|---|---|
400 | Missing or invalid destination_key, same source and destination, empty graft queries, invalid threshold, read-only destination, off destination |
401 | Missing or invalid source key auth |
403 | Source key has memory disabled with :off |
413 | Source vault is too large for a single transfer request |
500 | Unexpected transfer or graft failure |
Example same-key error:
{
"error": "destination_key must be different from the source key"
}When to use each
Use Transfer when:
- You are migrating a key.
- You want a full backup copy.
- You are consolidating all memories into a new key.
Use Graft when:
- You want to seed a team or org key from personal memory.
- You need only business memories, project memories, or client memories.
- You want to avoid copying unrelated personal context.
For team onboarding, the best pattern is:
- Each team member runs a dry-run graft from their personal key into the shared org key.
- They tune queries and threshold until the preview is clean.
- They run the real graft.
- The org key starts useful on day one.