Export and import rooms
Sometimes you want to take a conversation with you — move it to another workspace, archive it locally, share it with a different tenant, or hand it off to compliance. Room export gives you a portable ZIP bundle.
Export#
From the UI#
Chat header → ⋯ menu → Export room. Browser downloads a
.zip.
From the CLI#
bash
1 | |
From the API#
bash
1 2 3 | |
Requires join membership on the room (you must be a member to
export). Power level 0 is enough.
What's in the bundle#
text
1 2 | |
The manifest is a single JSON document with:
- Room metadata (name, topic, type, scope, created_at).
- An ordered list of every event in the room with full content.
- For each foreign sender (federated, bridged, imported-from-export),
an
_imported_senderblock with their display name, avatar, and original FQID. Shadow participants are not created on import — the original author identity is preserved inline rather than polluting the destination tenant's member list. - Media references by sha256 → matches a file in
media/.
Import#
Into the UI#
Workspace settings → Rooms → Import room → drop the zip. Creates a new room in this workspace; you become its creator.
CLI#
bash
1 2 3 | |
API#
bash
1 2 3 4 | |
Requires create_note permission in the target workspace (the
same gate as creating any room).
What import preserves#
- Message bodies and timestamps.
- Original author identities — embedded inline as
content._imported_sender(you'll see them in the UI as "[Original: Alice from acme.scaiwave.com]"). - Media — re-uploaded into the destination tenant's storage with the same sha256.
- Reactions, edits, redactions — re-played in order.
What import strips#
- Read markers — they're per-participant; meaningless in a new tenant.
- Sidekick metadata — imported rooms don't carry their sidekick forest.
do_not_indexflag — imported events getdo_not_index=True. They never enter the destination's search index. (If you want them indexed, an admin can flip the room's scope and re-run the indexer.)- Live presence — obviously.
Refused exports / imports#
Room export and import both refuse on:
room_type=sidekick(sidekick rooms are tied to their parent; export the parent if needed).room_type=bridge(state lives on the bridge config, not the room).scope_kind=incognito(by design).room_type=federated— there's nothing to export, the events live on the foreign server.
The export endpoint returns a 400 with a clear reason in each case.
When to use it#
- Archive a sensitive conversation locally, then close the room.
- Move a project room to a different workspace after a re-org.
- Hand off to compliance as evidence.
- Demo — package a conversation as a portable artifact for documentation or training.
What to not use it for#
- Backup — there's no automatic backup-on-export; if you want
reliable backup of all rooms, use the GDPR export job for your
tenant (
POST /v1/gdpr/export) instead. - Migration to another product — the manifest format is ScaiWave-specific; nothing else reads it. (We'd love to define an interop format; not yet.)