---
title: "Export & import"
description: "Move a user's entire knowledge graph — account migration, backup, and data portability."
---

> Documentation Index
> Fetch the complete documentation index at: https://truememory-docs.mvstg.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Export & import

Memory is something a user accumulates over time — facts, preferences, relationships, and context that an agent has learned about them. There are three common reasons to move that memory around:

- **Account migration** — a user is switching to a new account and wants to take their memory with them
- **Backup** — capture a snapshot now so you can restore if something goes wrong later
- **Data portability** — give the user a copy of what Truememory has learned about them (useful for GDPR-style "export my data" requests)

The export endpoint produces a single JSON document. The import endpoint consumes that same document and writes it into the caller's graph. Both sides span every agent scope for the user in one call — you do not loop per-agent.

Think of it like `git clone` for a user's knowledge graph: one command pulls the whole repository, one command pushes it back somewhere else. Where this metaphor breaks down: embeddings (the vector representations Graphiti uses for semantic search) are not re-generated automatically on export, and they are rebuilt asynchronously on import — so searches against freshly imported data can return empty for a few minutes while the backfill runs.

## Export Memory

```bash
GET https://your-tie-host/memories/export
Authorization: Bearer $TOKEN
```

| Parameter | In | Required | Description |
|-----------|------|----------|-------------|
| `include_episodes` | query | No | Include raw `:Episodic` nodes (conversation chunks the graph was extracted from). Defaults to `false` — episodes are much larger than the extracted graph and contain raw PII. |
| `include_expired` | query | No | Include edges the user previously deleted (soft-deleted via `expired_at`). Defaults to `false`. Useful for full archival; skip for normal use. |
| `include_embeddings` | query | No | Include the vector embeddings on nodes and edges. Defaults to `false`. Embeddings are regeneratable and inflate payload size roughly 10x. |

**Response:**

```json
{
  "schema_version": "1",
  "exported_at": "2026-04-20T08:15:42.123456+00:00",
  "source_user_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "counts": {
    "entity_nodes": 142,
    "entity_edges": 389,
    "episodes": 0
  },
  "entity_nodes": [
    {
      "uuid": "n-abc",
      "labels": ["User"],
      "properties": {
        "name": "Alice",
        "summary": "Senior engineer at Mindvalley",
        "created_at": "2026-01-12T09:00:00+00:00"
      }
    }
  ],
  "entity_edges": [
    {
      "uuid": "e-xyz",
      "type": "RELATES_TO",
      "source_uuid": "n-abc",
      "target_uuid": "n-def",
      "properties": {
        "fact": "Alice works at Mindvalley",
        "valid_at": "2026-01-12T09:00:00+00:00"
      }
    }
  ],
  "episodes": []
}
```

Each envelope field:

- `schema_version` — envelope format version. The import endpoint only accepts `"1"` today.
- `source_user_id` — the user the export was taken from. Import uses this to rewrite scoping on the target user.
- `counts` — record totals, mirrored by the lengths of the arrays below.
- `entity_nodes` — extracted entities (people, places, projects, topics) with their attributes.
- `entity_edges` — facts connecting two entities. `fact` is the human-readable statement; `source_uuid` / `target_uuid` reference entries in `entity_nodes`.
- `episodes` — raw conversation chunks, populated only when `include_episodes=true`.

**Size cap:** exports above **50,000 total records** return `413 Payload Too Large`. If you hit this, export per-agent (`?agent_id=...`) is not currently supported on `/memories/export` — contact the Truememory team to raise the cap.

:::note[Embeddings are stripped by default]
Vector embeddings (`name_embedding` on nodes, `fact_embedding` on edges) are excluded from the response unless you pass `include_embeddings=true`. On import, Truememory regenerates them automatically — so leaving them out is almost always the right choice.
:::

## Import Memory

Accept an exported envelope and write it into the caller's graph. Intended for the same account (migration, restore) or across accounts (data transfer between users).

```bash
POST https://your-tie-host/memories/import
Authorization: Bearer $TOKEN
Content-Type: application/json
```

**Request body** — a JSON envelope produced by `GET /memories/export`. Unchanged envelopes can be re-sent; see the idempotency note below.

**Response** (`202 Accepted`):

```json
{
  "status": "processing",
  "import_id": "b7a1c3ef9e5c4d80b6ab1b3b5b5c2c9d",
  "nodes_written": 142,
  "edges_written": 387,
  "episodes_written": 0,
  "edges_skipped": ["e-orphaned-1", "e-orphaned-2"]
}
```

Response fields:

- `import_id` — pass to `GET /memories/import/{import_id}` to poll for embedding regeneration status.
- `nodes_written` / `edges_written` / `episodes_written` — counts of records freshly created in the target graph. Records whose UUID already exists are skipped (see below).
- `edges_skipped` — UUIDs of edges whose `source_uuid` or `target_uuid` did not match any node in the target graph. These are dropped silently; fix the source export or ignore them.

**Scoping — what happens to `group_id`.** Memory in Truememory is scoped by `group_id`, which looks like `{user_id}_{agent_id}`. On import, the envelope's `source_user_id` is stripped from every record's `group_id` and the caller's user ID is substituted. The agent suffix (e.g. `__shared__`, `chatbot`) is preserved. A record originally under `source-user_chatbot` becomes `caller-user_chatbot` in the target graph.

**Idempotency — skip-if-exists by UUID.** Import is safe to re-run. Any node, edge, or episode whose UUID already exists in the target graph is left untouched — nothing is overwritten, and no duplicates are created. This means:

- Re-sending the same envelope produces `nodes_written: 0` on the second call.
- Facts the user has accumulated *since* the export are not clobbered.
- There is no partial-state concern: a crashed import can be retried safely.

:::caution[Embeddings regenerate asynchronously]
The import endpoint returns `202` once the graph records are written. Vector embeddings are regenerated in a background task that can take several minutes for a large import. **Semantic search (`POST /memories/search`, `/memories/graph/{user_id}/warm`) will return empty results for freshly imported facts until the backfill finishes.** Poll `GET /memories/import/{import_id}` to know when search is ready.
:::

**Error cases:**

| Status | When |
|--------|------|
| `400` | `schema_version` is unsupported, `source_user_id` is missing, or the envelope is malformed |
| `413` | Total records exceed the import cap (50,000) |
| `501` | The memory backend is disabled for this deployment |

## Check Import Status

Poll the status of an async import. Useful for showing a progress indicator or gating the UI until semantic search is ready.

```bash
GET https://your-tie-host/memories/import/{import_id}
Authorization: Bearer $TOKEN
```

**Response:**

```json
{
  "import_id": "b7a1c3ef9e5c4d80b6ab1b3b5b5c2c9d",
  "status": "ready",
  "nodes_written": 142,
  "edges_written": 387,
  "episodes_written": 0,
  "nodes_embedded": 142,
  "edges_embedded": 387,
  "edges_skipped_count": 2,
  "started_at": "2026-04-20T08:15:42.123456+00:00",
  "finished_at": "2026-04-20T08:18:07.456789+00:00",
  "error": null
}
```

Status values:

- `processing` — the embedding backfill is still running. Search will miss freshly imported data.
- `ready` — backfill complete, semantic search fully covers the imported records.
- `failed` — backfill hit an error. Inspect `error` for details. The graph records themselves are still written; only embeddings are missing. Contact support or re-trigger by importing the same envelope again (idempotent).

`nodes_embedded` and `edges_embedded` count only records from *this* import, not pre-existing records in the user's graph. They will stop incrementing once `status` is `ready` or `failed`.

:::note[Status is in-memory only]
Import status is held in server memory and cleaned up 10 minutes after completion. If Truememory restarts between your POST and your GET, the status endpoint returns `404` — but the imported data is already committed to Neo4j, so no action is needed.
:::

Source: https://truememory-docs.mvstg.com/memory/export-import/index.mdx
