Import / Export
Your memory data is never locked in. Both directions are NDJSON over the same API: take a backup, bring memories in from another Uteke workspace, or leave with everything. On Free you can export 4 times a month.
Export
curl https://uteke.app/api/v2/export \ -H "Authorization: Bearer utk_live_YOUR_KEY" \ -o workspace.ndjson
The response is a stream of JSON objects, one per line. Line 1 is a manifest describing the
export; the memories follow, then your documents (lines with "type": "document").
Embeddings are not included, entries are
re-embedded automatically after an import, so files stay small and portable.
Import
curl https://uteke.app/api/v2/import \
-H "Authorization: Bearer utk_live_YOUR_KEY" \
-H "content-type: application/json" \
-d "$(jq -Rs '{data: .}' workspace.ndjson)" The body takes { "data": "…" } where data is the raw NDJSON
text (or a JSON array of entries). Entries that carry a namespace (older
open-source exports) keep it as tag ns:<name>. The request body is limited to
8 MiB per call on Free (64 MiB on Pro). Set "extract": true to treat each memory entry as raw text and queue it for LLM
extraction (paid plans, metered against your daily LLM tokens).
The jq -Rs wrapper reads the file and wraps it as a JSON string safely.
What import preserves
- IDs and created_at: entries exported from a cloud or OSS workspace keep their identity on re-import.
- Dedup: identical content is skipped, so re-running an import does not duplicate memories.
- Atomicity: a malformed entry fails the whole request fast (400 with the line number); there are no partial imports.
Response shape:
{
"imported": 128, "duplicates_skipped": 3, "id_conflicts_skipped": 0, "ignored": 1,
"documents_imported": 6, "documents_updated": 1, "parent_unresolved": 0,
"extraction_queued": 0, "extraction_job_ids": [], "total": 139
} ignored counts non-memory lines such as the export manifest, which is skipped
automatically when you re-import a cloud export file. parent_unresolved counts
documents whose parent could not be found in the same import (they stay at the top level).
Re-importing a document with a different parent moves it together with its sub-documents.
Moving in from the open-source Uteke
- Run
/exportagainst your current Uteke server (same Bearer auth, same NDJSON format). - Generate a cloud key at /portal/keys.
- Run
/importagainst the cloud with the same file. Search is usable immediately; vector recall warms up as re-embedding completes.