---
title: "Generate a SQL migration script from a free-text intent"
method: POST
path: "/v1/migrations/generate"
tags: ["migrations"]
---

# Generate a SQL migration script from a free-text intent

`POST /v1/migrations/generate`

## Request

- Base URL: `https://data.thinair.co`
- URL: `https://data.thinair.co/v1/migrations/generate`
- Auth: API key in header `x-api-key`

Parse a plain-English migration intent (e.g. 'add index on positions(deviceid, fixtime desc)') and emit dialect-correct up + down SQL plus warnings. Never executes — output is for the caller to review and run manually. Costs 1 quota unit per call. Build tier (or higher) required.

## Request body

- MigrationsGenerateRequest: Generate a SQL migration script (up + down + warnings) from a free-text intent. Costs 1 quota unit. Build tier (or higher) required.
  - `connection` string: Connection name (display) or id (uuid). When omitted, the tenant's default (first added) connection is used. Same fallback as the MCP `generate_migration` tool.
  - `intent` string, required: Plain-English description of the migration. Examples: 'add soft delete to drivers', 'add index on trips(driver_id, created_at)', 'rename email to email_address on drivers'. Phrasing matters: name the table, the column, and the action explicitly — the intent parser extracts those three and will reject a request it cannot resolve rather than guess.
  - `target_dialect` 'postgres' | 'mysql' | 'mssql': Optional target dialect. The handler currently derives dialect from the resolved connection — this hint is informational only and reserved for future cross-dialect translation. Mismatches between hint and resolved dialect surface in response meta but don't override.
  - `dry_run` boolean: Reserved for future support. The current handler NEVER executes the generated SQL — it only emits up + down strings — so dry_run is effectively always true. Echoed in response meta when set.

## Response `200`

Generated migration. Always review `data.warnings[]` before running — some operations (drop column, create unique index) are destructive or fail when constraints aren't met.

- MigrationsGenerateResponse: Generated migration. `data.up_sql` runs the change, `data.down_sql` rolls it back, `data.warnings[]` flags caveats (PG `CONCURRENTLY` outside a tx, NULL backfill required, irreversible drops, …). Mirrors the MCP `generate_migration` tool output. Some intents emit `-- TODO:` skeletons + a parser-couldn't-resolve warning when the phrasing isn't recognized.
  - `data` object, required
  - `display` object, required
  - `summary` string
  - `insights` object[]
  - `meta` object, required

## Other responses

- `400`: Invalid request body.
- `401`: Authentication required or failed.
- `403`: Tier gate — requires Build plan or higher (caller is on Discover).
- `404`: Connection not found, or the tenant has no connections registered.
- `429`: Quota exceeded for this tenant.
- `502`: Upstream database unreachable during schema introspection — no quota debited.

---

[API](https://skmtc.dev/thinair/apis/thinair-data-api.md) · [All operations](https://skmtc.dev/thinair/apis/thinair-data-api/llms.txt) · [OpenAPI document](https://skmtc.dev/thinair/apis/thinair-data-api/revisions/8a2a2d1b2400?raw)
