Skip to content
EN

Export, Import & Clone

POST /api/rooms/:roomId/export (token permission: read) # empty body {} = full room → .gpkg
POST /api/rooms/:roomId/import (token permission: write) # multipart file=@room.gpkg, ≤ 2 GiB
Terminal window
curl -X POST "$API/api/rooms/$ROOM/export" -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" -d '{}' -o room.gpkg
curl -X POST "$API/api/rooms/$ROOM/import" -H "Authorization: Bearer $TOKEN" -F "file=@room.gpkg"

The export body/query mirror the app options (?include_tiffs=&include_tiles=).

GET /api/rooms/:roomId/export-size (token permission: read)

{ "bytes", "thresholdBytes", "recommended": "sync" | "async" }. Use it to decide between the sync route and async jobs (the app switches automatically above ~2 GiB).

POST /api/rooms/:roomId/export-jobs (read) → 202 { "jobId": "<uuid>" }
GET /api/rooms/:roomId/export-jobs/:jobId (read) → { status, bytes, error?, startedAt, finishedAt }
GET /api/rooms/:roomId/export-jobs/:jobId/artifact (read) → .gpkg stream

Job ids are room-bound (polling another room’s job → 404). Artifacts expire after 24 hours.

Very large rooms exceed the 2 GiB import cap, so they’re cloned instead of re-uploaded — the server copies the underlying data in place.

GET /api/rooms/:roomId/export-manifest (read) # small .json — no bulk data inside
POST /api/rooms/:roomId/clone-jobs (write) → 202 { "jobId": "job-<uuid>" }
GET /api/layers/jobs/:jobId # poll: { stage, progress, layersCloned, ... }

The manifest carries markers, icons, drawn shapes, and layer configs; bulky layer data is referenced by source room id only and copied server-side into the target room. Copied bytes count against the target owner’s storage quota.