Source — the system you migrate from
A source is one system you migrate customers off of (Salesforce, a legacy CRM, a pile of spreadsheets). You set it up once, in the Vern UI. Over the API a source is addressed by its name — Vern never exposes a source ID. You can list your sources to let a customer pick which system they’re migrating from, then pass that name assource when you
create a migration.
A source is optional. A migration that doesn’t name one is “sourceless” — the
agent works purely from the uploaded files. A source is not a frozen import
plan, either: there’s nothing to hand-author and publish. The import logic is
produced by the managed agent at run time, and reused across
customers as an optimization.
Template — the object
A template is the target schema for one importable object — a sheet like Contacts or Companies — with its columns and validation rules (which columns exist, which are required, which must be unique, how they link to other objects). Templates are scoped to your account, not to a single source: the same set of objects is available to every source you migrate from. Over the API a template is addressed by its slug — a stable snake_case identifier derived from its name (e.g.contacts). When you create a migration, each template you select becomes
one sheet on its workbook. You can
list your templates over the API — columns and
all — to show a customer what they can import and let them choose.
Migration — the instance
A migration is one customer’s migration — their isolated workspace. You create it with the first API call and it holds a workbook: their data, with one sheet per template. Theid returned at creation is the migration ID
you pass to every later call.
A migration is created against a source (or none), but nothing is bound to
it — there’s no frozen plan to replay. Your run and export calls only ever
reference the migration; you never pass plan or recipe IDs. The agent decides
what logic to run each time.
A migration moves through a small set of overall states, derived from what’s
happened so far:
awaiting_files— created, with no data source yet: no files uploaded and no live source connected.ready— a data source is in place (files uploaded or a source connected), no preview generated yet.awaiting_approval— a preview has been generated and is waiting for you to execute or refine it.completed— an execute run has imported the data.
Live sources
A migration’s data can come from uploaded files, a live API source, or both. A live source is a connector the agent reads from directly at run time — you attach one withPOST /source-connection.
Once a connection exists, the migration leaves awaiting_files even with nothing
uploaded, and a generate run can extract from it (see
extract_via_api). If the connector
needs secrets, the run pauses for credentials.
The managed agent
Every run executes on one durable, tool-using agent — the same agent that powers Vern’s interactive import UI, driven headlessly. Across a migration’s runs the agent:- Builds. On a
generaterun it reuses-or-authors the import logic — a portable mapping + transform recipe — and verifies it in a sandbox before touching real data, stopping at a preview. - Self-heals. When a customer’s file drifts from what the recipe expected, it edits and re-verifies until it passes.
- Asks, when it has to. If a mapping is genuinely ambiguous and neither the
data nor your templates settle it, the run pauses at
blockedwith a plain-language question. You answer through the run’s messages sub-resource and it resumes. - Executes. On an
executerun it runs the real import, then self-heals invalid cells. Surviving invalid cells are reported, not parked — the run completes and the bad cells show up in the report.
Reuse and pinning
By default the agent reuses the source’s most-recent working recipe as a starting point, adapting only what each customer’s upload changed. Because every successful generate writes a fresh recipe, “latest” naturally drifts as different end-customers import slightly different shapes. If you’d rather isolate that drift, you can pin one known-good run’s recipe for a source. Pinned runs read it as a starting point and don’t promote their adapted recipe back to the shared “latest”, so one customer’s run can’t change the starting point other runs draw from. See Pin a source.Runs
Anything the agent does is a run. You start a run withPOST /migrations/{id}/runs and a kind:
generate— author the recipe and produce a preview.update— edit the recipe per a message, producing a new preview.clarify— a read-only question about the current preview (changes nothing).execute— run the approved preview for real.
409. A generate opens a preview run and update/clarify/execute
resume that same run, so a single run_id stays pollable from preview through
the real import. Each run you poll until it reaches a terminal state:
queued— accepted, not started yet.running— the agent is working; the poll response carries a human-readablemessage.blocked— the agent is waiting on you.blocked_reasonsays which kind:"question"(an ambiguous decision; the poll carriesquestions, answered via the run’s messages sub-resource) or"credentials"(a live source needs secrets; the poll carries acredential_request, answered via credentials).awaiting_approval— agenerate/updaterun finished and produced a preview. Fetch it fromGET /preview, then refine or execute.completed— finished. Anexecuterun carries areport(rows inserted, per-sheet counts, how many rows still carry an invalid cell). Aclarifyrun completes with no report.failed— the agent couldn’t produce a working result even after self-healing. For an execute, nothing was inserted.canceled— the run was stopped before it finished (see cancel a run).
Identifiers
- Migrations and runs are identified by a UUID — store them as opaque strings; don’t assume a typed prefix.
- Sources are addressed by their name, templates by their slug — there are no public source or template IDs.
- The
external_idyou set on a migration is your own string, echoed back untouched, and makes creation idempotent.
Next
- Quickstart — see all of this in one flow.
- Create a migration — the first call.