Export and import CortexDB data for migration, backup, and portability.

Export & Import

CortexDB supports full data export and import for backups, migrations, and one-time data loads from peer systems.

Export

Export a scope's events and derived layers. The JSONL payload comes back inline in the data field (format currently supports jsonl only).

import requests, os
H = {
    "Authorization": f"Bearer {os.environ['CORTEX_TOKEN']}",
    "X-Cortex-Actor":  os.environ["CORTEX_ACTOR"],
    "Content-Type":    "application/json",
}
r = requests.post(
    "https://api-v1.cortexdb.ai/v1/export",
    headers=H,
    json={
        "scope":  "org:acme/dept:eng",
        "format": "jsonl",
    },
).json()

with open("decisions-q1.jsonl", "w") as f:
    f.write(r["data"])
curl -X POST https://api-v1.cortexdb.ai/v1/export \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "X-Cortex-Actor: $CORTEX_ACTOR" \
  -H "Content-Type: application/json" \
  -d '{
    "scope": "org:acme/dept:eng",
    "format": "jsonl"
  }' | jq -r .data > decisions.jsonl

See POST /v1/export for the request and response shape.

Import — from CortexDB exports

Exported lines are complete experience envelopes. Feed them back through POST /v1/import/jsonl — it accepts a scope_template plus the raw lines, returns 202 with an import_id, and progresses on the lifecycle stream:

lines = [l.rstrip("\n") for l in open("decisions-q1.jsonl") if l.strip()]
r = requests.post(
    "https://api-v1.cortexdb.ai/v1/import/jsonl",
    headers=H,
    json={"scope_template": "org:acme/dept:eng", "lines": lines},
).json()
print(r["import_id"], r["status"])

For small, hand-built batches, the SDK's experience_bulk(scope, items=[...]) (up to 1000 items per call) also works — its items are flat dicts (text, role, observed_at, labels, idempotency_key), not raw envelope lines.

The same import from the shell:

curl -X POST https://api-v1.cortexdb.ai/v1/import/jsonl \
  -H "Authorization: Bearer $CORTEX_TOKEN" \
  -H "X-Cortex-Actor: $CORTEX_ACTOR" \
  -H "Content-Type: application/json" \
  -d "$(jq -Rs '{scope_template: "org:acme/user:{user_id}", lines: split("\n")}' decisions-q1.jsonl)"

Import — from peer systems

CortexDB ships native importers for Mem0, Zep, Letta, and OpenAI memory exports. The Mem0 and Zep importers accept a scope_template with {placeholders} filled per row; the Letta and OpenAI importers land everything in a single scope.

# Mem0 → CortexDB
requests.post("https://api-v1.cortexdb.ai/v1/import/mem0", headers=H, json={
    "scope_template": "org:acme/user:{user_id}",
    "rows":           mem0_export["memories"],
})

# Zep → CortexDB (preserves bi-temporal valid_from / valid_to)
requests.post("https://api-v1.cortexdb.ai/v1/import/zep", headers=H, json={
    "scope_template": "org:acme/user:{user_id}",
    "rows":           zep_export["facts"],
})

# Letta → CortexDB (archival blocks land as documents)
requests.post("https://api-v1.cortexdb.ai/v1/import/letta", headers=H, json={
    "scope": "org:acme/user:alice",
    "rows":  letta_export["archival_memory"],
})

All importers return 202 with an import_id — track progress on GET /v1/import/{id} or via the lifecycle stream's import_progress / import_complete events.

Operational Backups

Export/import is the logical portability path. For disaster recovery on self-hosted deployments, CortexDB supports a verified cold backup flow (scripts/cold_backup.py): stop the server, back up the data directory with a per-file SHA-256 manifest, and restore into an empty target. The tool refuses to back up a live data directory, restore over a non-empty target, or restore a tampered or truncated archive.

Online (hot) backup and point-in-time recovery are planned, not yet available — there are no /v1/admin/backup endpoints in v0.7.1.

For operator details, see Backups & Disaster Recovery.

Migration Between Instances

# 1. Export from source
curl -X POST https://api-v1.source.example.com/v1/export \
  -H "Authorization: Bearer $SRC_TOKEN" -H "X-Cortex-Actor: $SRC_ACTOR" \
  -H "Content-Type: application/json" \
  -d '{"scope":"org:acme/dept:eng","format":"jsonl"}' | jq -r .data > backup.jsonl

# 2. Import to destination
curl -X POST https://api-v1.dest.example.com/v1/import/jsonl \
  -H "Authorization: Bearer $DST_TOKEN" -H "X-Cortex-Actor: $DST_ACTOR" \
  -H "Content-Type: application/json" \
  -d "$(jq -Rs '{scope_template: "org:acme/dept:eng", lines: split("\n")}' backup.jsonl)"