Skip to main content
Preview. Part of the Migration API — in active design and not yet generally available. Endpoints and payloads may change. See the overview.
This walks through one customer migration from start to finish. All requests authenticate with an x-api-key header — see Authentication.
1

Publish your migration logic (one time, in the UI)

Before any API calls, set up the source in the Vern dashboard: define your templates, then author and publish an import plan. This is the interactive part — you do it once, and every customer migration replays it. See Core concepts.
2

Discover sources and templates (optional)

To let your customer pick which system they’re migrating from and which objects to import, list your sources and templates and render them in your own UI. Skip this if you already know the IDs.
curl https://app.vern.so/api/v1/sources   -H "x-api-key: $VERN_API_KEY"
curl https://app.vern.so/api/v1/templates -H "x-api-key: $VERN_API_KEY"
Feed the chosen source into source and the chosen templates into template_ids below. See List sources and List templates. (Preview — until these ship, read the IDs from the Vern dashboard.)
3

Provision a company for the customer

Create a company bound to your source. You get back the IDs used by every later call.
curl -X POST https://app.vern.so/api/v1/companies \
  -H "x-api-key: $VERN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "source": "01234567-89ab-cdef-0123-456789abcdef",
    "external_id": "acme-001",
    "template_ids": ["9e8d7c6b-5a4f-4321-8b2c-1d0e9f8a7b6c"]
  }'
{
  "company": { "id": "c0a8012e-4f1b-4d3a-9b2c-7e6f5a4b3c2d", "external_id": "acme-001" },
  "workbook_id": "b3d9f2a1-6c4e-4a8b-9f1d-2e3c4b5a6d7f",
  "sheets": [{ "id": "7a1c2b3d-4e5f-4061-8a9b-0c1d2e3f4a5b", "name": "Contacts", "template_id": "9e8d7c6b-5a4f-4321-8b2c-1d0e9f8a7b6c" }],
  "magic_link_url": "https://app.vern.so/link/abc123"
}
Every ID in the response is a UUID. Use company.id for every later call.See Provision a company for every field.
4

Import the customer's files

Push files and Vern replays your plan. The call is async — it returns a run to poll. (Small tabular sets can be sent inline as rows instead of files.)
curl -X POST https://app.vern.so/api/v1/companies/c0a8012e-4f1b-4d3a-9b2c-7e6f5a4b3c2d/imports \
  -H "x-api-key: $VERN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [{ "name": "contacts.csv", "upload_ref": "<from-signed-upload>" }],
    "idempotency_key": "acme-001-imp-1"
  }'
{ "run_id": "d4c3b2a1-9f8e-47d6-b5a4-c3d2e1f0a9b8", "status": "queued", "poll_url": "/api/v1/companies/c0a8012e-4f1b-4d3a-9b2c-7e6f5a4b3c2d/imports/d4c3b2a1-9f8e-47d6-b5a4-c3d2e1f0a9b8" }
See Import files for upload options.
5

Poll until the import finishes

Poll the run every couple of seconds until status is terminal.
curl https://app.vern.so/api/v1/companies/c0a8012e-4f1b-4d3a-9b2c-7e6f5a4b3c2d/imports/d4c3b2a1-9f8e-47d6-b5a4-c3d2e1f0a9b8 \
  -H "x-api-key: $VERN_API_KEY"
{
  "status": "completed",
  "report": {
    "inserted": 1450,
    "perSheet": [{ "templateName": "Contacts", "sheetId": "7a1c2b3d-4e5f-4061-8a9b-0c1d2e3f4a5b", "rowCount": 1450 }],
    "invalidCellCount": 12
  }
}
A completed run with invalidCellCount > 0 means that many rows still have at least one cell that failed validation — the rest are clean. The default CSV download (?filter=valid) excludes those rows entirely. See Poll an import for recovery and every status shape.
6

Resolve flagged rows (only if needed)

If the run comes back needs_attention instead of completed, Vern paused because some rows failed validation and it has a fix waiting. The poll response carries self-describing questions and a proposed_patch — render them in your own UI, then send the customer’s answer:
curl -X POST https://app.vern.so/api/v1/companies/c0a8012e-4f1b-4d3a-9b2c-7e6f5a4b3c2d/imports/d4c3b2a1-9f8e-47d6-b5a4-c3d2e1f0a9b8/decisions \
  -H "x-api-key: $VERN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "decision": "approve",
    "answers": [{ "question_id": "fq0", "option_id": "a" }]
  }'
Vern applies the fix, writes a new plan version, and re-runs — poll again until the run is completed (or it re-parks with fresh questions). To take Vern’s suggestion as-is, approve with no answers. See Resolve flagged rows.
7

Deliver the clean data

Download the validated rows as a clean CSV (valid rows only, by default):
curl "https://app.vern.so/api/v1/companies/c0a8012e-4f1b-4d3a-9b2c-7e6f5a4b3c2d/export.csv?sheet_id=7a1c2b3d-4e5f-4061-8a9b-0c1d2e3f4a5b" \
  -H "x-api-key: $VERN_API_KEY" \
  -o contacts-clean.csv
Or push the validated records straight to a destination API with Export to a destination.

Next