---
title: "Create a migration"
method: POST
path: "/migrations"
tags: ["Migrations"]
---

# Create a migration

`POST /migrations`

## Request

- Base URL: `https://app.vern.so/api/v1`
- URL: `https://app.vern.so/api/v1/migrations`
- Auth: API key in header `x-api-key`
- TypeScript: <https://skmtc.dev/vern-so/apis/vern-api/docs/migrations/post.ts> (a function with typed inputs; its response is checked against the schema)

Create a migration workspace for one customer — a workbook with one sheet per template. Requires API-key auth specifically and an active plan. `external_id` makes creation idempotent: re-sending the same one (with the same source) returns the existing migration with a 200, unchanged — use `PATCH /migrations/{migration_id}` to change it. If that migration is archived the answer is 409 with `code: migration_archived` and its `id`.

## Request body

- object
  - `name` string, required: Display name for the migration (e.g. the customer's org name).
  - `source` string: The source name this migration comes from. Optional — omit for a sourceless migration.
  - `external_id` string: Your own identifier for this customer. Alphanumeric, hyphens, underscores. Makes creation idempotent.
  - `templates` string[]: Template slugs to create sheets from. Omit to use every active template.

## Response `200`

An existing migration matched `external_id` (and the same source); nothing was created and it is returned unchanged.

- object
  - `migration` Migration
    - `id` string, uuid: The migration ID — pass it to every later call.
    - `name` string
    - `external_id` string, nullable: Your own identifier for this customer.
    - `source` string, nullable
    - `status` 'awaiting_files' | 'ready' | 'awaiting_approval' | 'completed': Omitted from `GET /migrations` list items.
    - `templates` object[]
      - `slug` string
      - `name` string
    - `archived` boolean: Archived migrations stay readable and exportable but refuse uploads, runs and edits. Restore one from the Archived page in Vern.
    - `created_at` string, date-time
    - `url` string, uri: Opens the company in Vern. `/companies/open/{key}` also accepts the `external_id`.

## Other responses

- `201`: The created migration (200 when an existing migration is returned via external_id idempotency).
- `400`: Malformed request.
- `401`: API key missing, malformed, or revoked.
- `403`: Your account has no active plan. Only endpoints that create work (creating a migration, starting a run, starting an export) require one; reads are unaffected.
- `404`: The referenced resource isn't in your account.
- `409`: The `external_id` is already used by a migration under another source; the migration it names is archived (`code: migration_archived`, with its `id`); the source name is ambiguous; or your account's data region isn't live yet.
- `429`: Rate limit hit. Counted per account (company), not per API key or IP. Each endpoint is in one class: reads 30/minute, writes 30/minute, jobs (starting an export) 15/hour, agent (starting a run, answering, submitting credentials) 30/hour. Creating a migration and starting a `generate` run also have their own 30/hour caps. A separate per-IP ceiling absorbs floods before authentication. `Retry-After` gives the seconds until the window resets, alongside `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`.
- `500`: Unexpected server error.

## Changes

- **2026-11-08** `0ae6ef5f1887`: 12 info
  - added the non-success response with the status `403`
  - added the non-success response with the status `500`
  - added the optional property `code` to the response with the `400` status
  - added the optional property `code` to the response with the `401` status
  - …8 more
- **2026-06-18** `c5a09eb23a64`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/vern-so/apis/vern-api/changes/migrations/post.md)

---

[API](https://skmtc.dev/vern-so/apis/vern-api.md) - [All operations](https://skmtc.dev/vern-so/apis/vern-api/llms.txt) - [OpenAPI document](https://skmtc.dev/vern-so/apis/vern-api/revisions/0ae6ef5f1887?raw)
