Reference
Move from Umami v2
On this page
Vane accepts a JSON response from Umami v2's documented
GET /api/websites/:websiteId/events.
The response has data, count, page, and pageSize at the root. It is not a
database dump or the event-data endpoint. Download pages of up to 500 events and
import each independently. Vane never requests a Umami credential. count is the
complete Umami result count; only the supplied data page is imported.
Each event needs id, a UTC ISO createdAt, urlPath, and eventType. Type 1
maps to pageview. Type 2 requires an eventName configured as a Vane goal, on the
goal's approved path. Every path must exactly match the site's approved list.
Unknown paths, types, goals and goal/path mismatches stop the entire page with an
explicit row-number error.
The public tests/fixtures/umami-events.json is deliberately synthetic. To try
it, approve paths / and /thanks, goal signup at /thanks, campaign launch,
and source search.example. It demonstrates approved and discarded values; it
is not a customer export or evidence of real traffic.
Preview shows normalized events, mapped/duplicate counts, discard counts and a fingerprint. Confirm the fingerprint to apply the same page. It binds sanitized events, discard counts, site configuration/version and the owner. Changed policy or safe event values require a fresh preview. Ignored private values do not enter the fingerprint. Apply records owner ID and UTC approval time before publishing. The HTTP integration requires native owner sessions and CSRF protection; an agent API key cannot approve through that integration.
Only sanitized events enter Base import-kit source custody. Session IDs, page
titles, website IDs, raw source event IDs, referrer paths/queries, unknown fields
and raw URL queries are discarded before planning. Event identity is a stable
hash of the destination site and source event ID; no visitor/session identity is
kept. Only an approved utm_campaign token is extracted. Missing campaigns become
none; unknown or ambiguous campaigns become other. Empty referrer domains
become direct; approved hostnames remain; unknown domains become other.
Neither raw upload nor original bytes are retained. Artifact hashes describe
only sanitized values. Imported consent and sampling are unknown (null).
Apply publishes up to 20 entries per call. Repeat the same document/fingerprint
until complete: true; completed replays are idempotent. Reusing an event ID with
changed safe content fails. Journal exposes approval, checkpoints, committed
batches, discard counts and event provenance. Repeat undo until complete: true.
Undo removes imported events and refuses rows edited since import. Base jobs are
bound to the owner who previewed them; another owner cannot take over a job.
Call eraseSite while the site exists. Base retires all import custody for that
site and deletes import rows, revisions and approvals in one atomic batch. A
durable fence and append-only receipt retain IDs, counts and time; retired jobs
cannot resume or undo. The caller owns deletion of live events and site records.
Portability must preserve fences and reject archives predating erasure; a fence
alone cannot enforce that outer archive policy.
Server API
src/vane/movein/index.ts exports:
preview(env, actor, {siteId, document})apply(env, actor, {siteId, document, fingerprint})journal(env, actor, {siteId, jobId})undo(env, actor, {siteId, jobId})eraseSite(env, actor, siteId, nativeStatements?)expireBefore(env, actor, siteId, beforeDay, nativeStatements?)
env.DB is a real D1 binding; actor is native {id, role}. All operations reject
non-owners, check active owner authority in oa_operators, and fence site policy
inside Base transactions. MoveinError supplies a safe code and HTTP status.
Do not log documents or expose arbitrary engine diagnostics in HTTP errors.
Portability
Export/import vane_import_events, vane_import_revisions,
vane_import_approvals, vane_import_erasure_fences, and every ik_* table in
migrations/core/0015_import_kit.sql, including empty staging tables. These hold
jobs, source/provenance custody, original availability manifests, chunks, batches,
reversal history, preparation guards and erasure journals/receipts. Preserve
append-only journals and monotonic fences when checking restore eligibility.
Reports union vane_import_events with vane_events and preserve null consent
and sampling.
Base runtime source under src/modules/import-kit is copied byte-for-byte from
fc0e1041efa55771142bbb57c4ab4743147e264d, limited to transitive dependencies of
D1 planning, create, apply, read, undo and retirement. No tests or proof apps are
copied. The migration embeds Base's fresh D1 schemas plus Vane's import tables.
Deletion accepts optional inert SQL descriptors {sql, params} (not prepared
statements). Native deletes and deletion-ledger inserts commit in the same Base
retirement batch and import erasure fence. Do not delete the site row in these
statements: current site policy must still authorize the transaction's final
check. expireBefore erases one expired imported event per call, plus the caller's
idempotent native deletion descriptors, returning remaining and complete.
Repeat until complete. It tombstones that event's source custody while preserving
other imported events. If there are no expired imports, the native statements and
fence still commit with the same active-owner/site-policy checks. A partial run
can be resumed, and its deletion receipt already fences older archives.
Preview also returns carry: {format: 'vane-umami-preview/1', events, discarded}.
Use this sanitized carry as apply's document to avoid returning raw uploads in
HTML. Carry validation rejects unknown keys, unhashed IDs, unapproved paths,
goals, sources/campaigns and non-null consent/sampling. Raw response and carry
produce the same fingerprint under the same site policy. archiveTables exports
the complete table inventory from the public server entry point.