Appearance
Migrate API
50 operations. Paths are relative to the API host (http://localhost:5080 in local development). Every operation accepts an OIDC bearer token (Authorization: Bearer …) or a workspace API key (X-Api-Key: keel_live_…); errors are RFC 9457 Problem Details with a code (error codes). Permissions: matrix.
| Method | Path | Summary |
|---|---|---|
| GET | /api/v1/workspaces/{workspaceId}/migrations | The workspace's migrations, newest first (filter by status, search by name). |
| POST | /api/v1/workspaces/{workspaceId}/migrations | Create a migration from one or more registered sources (Draft). |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId} | The migration overview: target, stage strip, KPIs, plan versions and generated code. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}:infer-mappings | Queue mapping inference: table/column mappings, transforms and code maps proposed with confidence and evidence. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/code-maps | Value translation tables with their coverage of the profiled source values. |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/code-maps/{name} | Create or replace a code map's pairs and default (saving accepts it). |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/execution | The write plane of a migration: write credential and its scope check, executors (migrate:execute), four-eyes, what you may do. |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/executors/{userId} | Grant migrate:execute on this migration to an Owner, Admin or Steward (Owner/Admin). |
| DELETE | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/executors/{userId} | Revoke migrate:execute on this migration (Owner/Admin). |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/four-eyes | Four-eyes on or off: the switch then needs a second, distinct Steward or Owner (Owner/Admin). |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generations | Code generation history, newest first. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generations | Queue dbt / SQL generation from the approved plan version (zip; with Git delivery also a branch + pull request). |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generations/{generationId} | One code generation: files, warnings and Git delivery. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generations/{generationId}/archive | The generated files as a zip (root folder {migration}-plan-v{n}). |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/mappings:bulk | Accept, reject or mark as needing work listed table/column mappings, or accept every proposal at or above minConfidence. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans | Every plan version, newest first. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans | Snapshot the accepted mappings as the next immutable plan version (waits for a Steward or Owner). |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans/{planVersion} | One plan version: its document and the changes since the previous version. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans/{planVersion}:approve | Approve the latest plan version (Steward/Owner): code generation and reconciliation use it; lineage and masks are registered with Governance. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans/{planVersion}/diff | What changed between two plan versions (?from=, default the previous one). |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations | Reconciliation runs, newest first. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations | Queue a reconciliation of the approved plan: read-only aggregate queries on both sides. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations/{runId} | Summary, per-table checks, failing keys (keys only), what blocks sign-off and the exceptions. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations/{runId}:sign-off | Sign off the latest reconciliation of the approved plan (Steward/Owner); 422 lists the Critical checks that still block it. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations/{runId}/exceptions | Accept a failing check with a reason (Steward/Owner) so it no longer blocks sign-off. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs | The migration's runs, newest first. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs | Hand the approved plan to the private agent: bulk load through staging on the target, then change capture until cutover. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId} | Run status: the write-plane banner, load (rows, bytes, rows/s, ETA), change capture lag, per-table progress, quarantine total. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}:pause | Queue Pause for the agent (delivered with its next report). |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}:resume | Queue Resume for a paused run. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}:retry | Retry failed chunks; a failed or stalled run is handed to the agent again and resumes from its last committed chunk. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutover | The cutover checklist: five steps with progress, four-eyes approval, what blocks the switch, your own switch steps, the rollback window. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutover | Open the cutover wizard of a syncing run. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutover:rollback | Roll serving back to the source during the rollback window (Steward/Owner); change capture stops. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutover/steps/{step}:confirm | Perform the active step (FreezeSource, FinalSync, FinalReconciliation, Switch, RollbackWindow = close it), or approve it as the second person. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/quarantine | Quarantined rows per table: counts and business keys only (at most 200 per table), never values. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/timeline | What happened in the run, newest first, with who did it (a person, an agent or Keel). |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/scope | Set the source tables the migration covers (empty: every table). Inference, the plan, code generation, reconciliation and runs skip excluded tables. Audited; with a committed plan it commits the next plan version under the new scope. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables | The workbench's table list: source → target, status, confidence, coverage and gaps. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId} | One table mapping with its column grid (sources, transform, target, confidence, evidence) and gaps. |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId} | Set a table mapping's source table(s), join, filter, dedupe keys and load pattern; accepted. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}:accept | Accept a table mapping and its proposed columns at or above minColumnConfidence (default: all). |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/columns/{targetColumn} | Set the source column(s) of a target column (creates the mapping for a gap column); accepted. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/columns/{targetColumn}:preview | The SQL a column mapping compiles to in the target dialect; a draft in the body is previewed without saving. |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/columns/{targetColumn}/transform | Set a column mapping's transform (parameters checked against the transform contract); accepted. |
| GET | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/evidence | Why Keel proposed the table mapping, or one of its column mappings (?column=). |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/target | Set the target: a registered data source (harvested like any source) or a semantic model's entities. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/target:upload | Set the target from uploaded CREATE TABLE statements (.sql) or a dbt project (schema .yml files, or a zip): parsed in memory, 10 MB uploaded / 20 MB unzipped at most; the files are not kept. format: Ddl or Dbt; dialect: a SourceKind (PostgreSql, SqlServer, Snowflake…); dataSourceId optionally names the database reconciliation reads. |
| PUT | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/write-credential | Register the separate write credential: a secret NAME on the private agent, its user and the target schemas it may write. Untested until checked. |
| POST | /api/v1/workspaces/{workspaceId}/migrations/{projectId}/write-credential:test | Queue the scope check on the agent: a credential that can write outside its schemas (or lacks what a run needs) is refused. |
ListMigrationProjects
http
GET /api/v1/workspaces/{workspaceId}/migrationsThe workspace's migrations, newest first (filter by status, search by name).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
status | query | MigrationStatus | no | |
search | query | string | no | |
page | query | int32 | no | |
pageSize | query | int32 | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | PagedResultOfMigrationProjectSummaryDto |
Response 200: PagedResultOfMigrationProjectSummaryDto
| Field | Type | Notes |
|---|---|---|
hasNext | boolean | |
items | MigrationProjectSummaryDto[] | |
page | int32 | |
pageSize | int32 | |
totalCount | int64 |
CreateMigrationProject
http
POST /api/v1/workspaces/{workspaceId}/migrationsCreate a migration from one or more registered sources (Draft).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes |
Request body (application/json): CreateMigrationProjectRequest
| Field | Type | Notes |
|---|---|---|
description | string? | |
name | string | |
sourceIds | uuid[] | |
strategy | MigrationStrategy | One of LiftAndShift, Remodel, Consolidate |
| Status | Description | Body |
|---|---|---|
| 201 | Created | CreatedResponse |
Response 201: CreatedResponse
| Field | Type | Notes |
|---|---|---|
id | uuid |
GetMigrationProject
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}The migration overview: target, stage strip, KPIs, plan versions and generated code.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | MigrationProjectDto |
Response 200: MigrationProjectDto
| Field | Type | Notes |
|---|---|---|
approvedPlan | PlanVersionSummaryDto? | |
createdAt | date-time | |
description | string? | |
id | uuid | |
kpis | MigrationKpisDto | |
lastInferenceError | InferenceErrorDto? | |
latestGeneration | CodeGenerationDto? | |
latestPlan | PlanVersionSummaryDto? | |
mappingsInferredAt | date-time? | |
name | string | |
owner | string | |
ownerName | string? | |
scope | ScopedTableDto[]? | |
signedOffAt | date-time? | |
signedOffBy | string? | |
sources | MigrationSourceDto[] | |
stages | MigrationStageDto[] | |
status | MigrationStatus | One of Draft, Mapping, Generated, Validating, SignedOff, Running, CutOver |
strategy | MigrationStrategy | One of LiftAndShift, Remodel, Consolidate |
target | MigrationTargetDto? | |
updatedAt | date-time? | |
workspaceId | uuid |
InferMappings
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}:infer-mappingsQueue mapping inference: table/column mappings, transforms and code maps proposed with confidence and evidence.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 202 | Accepted | JobAcceptedDto |
Response 202: JobAcceptedDto
| Field | Type | Notes |
|---|---|---|
jobId | uuid |
ListCodeMaps
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/code-mapsValue translation tables with their coverage of the profiled source values.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | CodeMapDto[] |
UpsertCodeMap
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/code-maps/{name}Create or replace a code map's pairs and default (saving accepts it).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
name | path | string | yes |
Request body (application/json): UpsertCodeMapRequest
| Field | Type | Notes |
|---|---|---|
default | string? | |
pairs | CodeMapPairRequest[] | |
sourceColumn | string? |
| Status | Description | Body |
|---|---|---|
| 200 | OK | CreatedResponse |
Response 200: CreatedResponse
| Field | Type | Notes |
|---|---|---|
id | uuid |
GetMigrationExecution
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/executionThe write plane of a migration: write credential and its scope check, executors (migrate:execute), four-eyes, what you may do.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | MigrationExecutionDto |
Response 200: MigrationExecutionDto
| Field | Type | Notes |
|---|---|---|
activeRunId | uuid? | |
approvedPlanVersion | int32? | |
canApprove | boolean | |
canExecute | boolean | |
canManageExecution | boolean | |
executors | MigrationExecutorDto[] | |
fourEyes | boolean | |
writeCredential | WriteCredentialDto? |
GrantMigrationExecution
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/executors/{userId}Grant migrate:execute on this migration to an Owner, Admin or Steward (Owner/Admin).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
userId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
RevokeMigrationExecution
http
DELETE /api/v1/workspaces/{workspaceId}/migrations/{projectId}/executors/{userId}Revoke migrate:execute on this migration (Owner/Admin).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
userId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
SetMigrationFourEyes
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/four-eyesFour-eyes on or off: the switch then needs a second, distinct Steward or Owner (Owner/Admin).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): SetFourEyesRequest
| Field | Type | Notes |
|---|---|---|
enabled | boolean |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
ListCodeGenerations
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generationsCode generation history, newest first.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
limit | query | int32 | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | CodeGenerationDto[] |
GenerateMigrationCode
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generationsQueue dbt / SQL generation from the approved plan version (zip; with Git delivery also a branch + pull request).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): GenerateMigrationCodeRequest
| Field | Type | Notes |
|---|---|---|
delivery | CodeDelivery? | |
output | CodeOutputKind | One of Dbt, Sql, Both |
| Status | Description | Body |
|---|---|---|
| 202 | Accepted | GenerationAcceptedDto |
Response 202: GenerationAcceptedDto
| Field | Type | Notes |
|---|---|---|
generationId | uuid | |
jobId | uuid |
GetCodeGeneration
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generations/{generationId}One code generation: files, warnings and Git delivery.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
generationId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | CodeGenerationDto |
Response 200: CodeGenerationDto
| Field | Type | Notes |
|---|---|---|
branch | string? | |
commitSha | string? | |
completedAt | date-time? | |
contentHash | string? | |
delivery | CodeDelivery | One of Download, Git |
downloadUrl | string? | |
error | string? | |
filePaths | string[] | |
files | int32 | |
groups | CodeFileGroupDto[] | |
id | uuid | |
output | CodeOutputKind | One of Dbt, Sql, Both |
planVersion | int32 | |
pullRequestNumber | int32? | |
pullRequestUrl | string? | |
requestedAt | date-time | |
requestedBy | string | |
status | CodeGenerationStatus | One of Queued, Succeeded, Failed |
warnings | string[] |
DownloadMigrationCode
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/generations/{generationId}/archiveThe generated files as a zip (root folder {migration}-plan-v{n}).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
generationId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | byte |
BulkReviewMappings
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/mappings:bulkAccept, reject or mark as needing work listed table/column mappings, or accept every proposal at or above minConfidence.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): BulkReviewMappingsRequest
| Field | Type | Notes |
|---|---|---|
action | ReviewAction | One of Accept, Reject, NeedsWork |
columnMappingIds | uuid[]? | |
minConfidence | number? | |
tableMappingIds | uuid[]? |
| Status | Description | Body |
|---|---|---|
| 200 | OK | BulkReviewResultDto |
Response 200: BulkReviewResultDto
| Field | Type | Notes |
|---|---|---|
columns | int32 | |
tables | int32 |
ListMigrationPlans
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plansEvery plan version, newest first.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | PlanVersionSummaryDto[] |
CommitMigrationPlan
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plansSnapshot the accepted mappings as the next immutable plan version (waits for a Steward or Owner).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): CommitMigrationPlanRequest?
| Status | Description | Body |
|---|---|---|
| 201 | Created | PlanCommittedDto |
Response 201: PlanCommittedDto
| Field | Type | Notes |
|---|---|---|
version | int32 |
GetMigrationPlan
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans/{planVersion}One plan version: its document and the changes since the previous version.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
planVersion | path | int32 | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | PlanVersionDto |
Response 200: PlanVersionDto
| Field | Type | Notes |
|---|---|---|
changesFromPrevious | PlanDiff? | |
document | MigrationPlanDocument | |
summary | PlanVersionSummaryDto |
ApproveMigrationPlan
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans/{planVersion}:approveApprove the latest plan version (Steward/Owner): code generation and reconciliation use it; lineage and masks are registered with Governance.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
planVersion | path | int32 | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
GetMigrationPlanDiff
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/plans/{planVersion}/diffWhat changed between two plan versions (?from=, default the previous one).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
planVersion | path | int32 | yes | |
from | query | int32 | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | PlanDiff |
Response 200: PlanDiff
| Field | Type | Notes |
|---|---|---|
codeMapsAdded | string[] | |
codeMapsChanged | string[] | |
codeMapsRemoved | string[] | |
fromVersion | int32 | |
isEmpty | boolean | |
strategyChanged | boolean | |
tablesAdded | string[] | |
tablesChanged | TableChange[] | |
tablesRemoved | string[] | |
toVersion | int32 |
ListReconciliations
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliationsReconciliation runs, newest first.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
limit | query | int32 | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | ReconciliationSummaryDto[] |
RunReconciliation
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliationsQueue a reconciliation of the approved plan: read-only aggregate queries on both sides.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 202 | Accepted | ReconciliationAcceptedDto |
Response 202: ReconciliationAcceptedDto
| Field | Type | Notes |
|---|---|---|
jobId | uuid | |
runId | uuid |
GetReconciliationReport
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations/{runId}Summary, per-table checks, failing keys (keys only), what blocks sign-off and the exceptions.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | ReconciliationReportDto |
Response 200: ReconciliationReportDto
| Field | Type | Notes |
|---|---|---|
blocking | BlockingCheckDto[] | |
canSignOff | boolean | |
completedAt | date-time? | |
error | string? | |
exceptionList | CheckExceptionDto[] | |
exceptions | int32 | |
failures | int32 | |
id | uuid | |
passed | int32 | |
planVersion | int32 | |
projectId | uuid | |
requestedAt | date-time | |
requestedBy | string | |
signedOffAt | date-time? | |
signedOffBy | string? | |
sourceRowsCompared | int64? | |
startedAt | date-time? | |
status | ReconciliationStatus | One of Queued, Running, Completed, Failed |
tables | TableReconciliationDto[] | |
targetRowsCompared | int64? | |
warnings | int32 |
SignOffReconciliation
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations/{runId}:sign-offSign off the latest reconciliation of the approved plan (Steward/Owner); 422 lists the Critical checks that still block it.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
RecordReconciliationException
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/reconciliations/{runId}/exceptionsAccept a failing check with a reason (Steward/Owner) so it no longer blocks sign-off.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
Request body (application/json): RecordExceptionRequest
| Field | Type | Notes |
|---|---|---|
checkKey | string | |
reason | string |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
ListMigrationRuns
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runsThe migration's runs, newest first.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
limit | query | int32 | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | MigrationRunSummaryDto[] |
ScheduleMigrationRun
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runsHand the approved plan to the private agent: bulk load through staging on the target, then change capture until cutover.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): ScheduleMigrationRunRequest
| Field | Type | Notes |
|---|---|---|
changeCapture | ChangeCapture | None (load only), SqlServerChangeTracking, SqlServerCdc, PostgresLogicalReplication, OracleLogMiner or IncrementalPolling. One of None, SqlServerChangeTracking, SqlServerCdc, PostgresLogicalReplication, IncrementalPolling, OracleLogMiner |
chunkRows | int32? | |
parallelism | int32? | |
pollIntervalSeconds | int32? | How often change capture polls the source when idle (1–300 s; default 5). |
reportIntervalSeconds | int32? | How often the agent reports (1–60 s, and under half the run's lease; default 5). |
| Status | Description | Body |
|---|---|---|
| 201 | Created | MigrationRunScheduledDto |
Response 201: MigrationRunScheduledDto
| Field | Type | Notes |
|---|---|---|
runId | uuid | |
workId | uuid |
GetRunStatus
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}Run status: the write-plane banner, load (rows, bytes, rows/s, ETA), change capture lag, per-table progress, quarantine total.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | MigrationRunDto |
Response 200: MigrationRunDto
| Field | Type | Notes |
|---|---|---|
actions | string[] | |
agentPhase | AgentRunPhase? | |
attempt | int32 | |
completedAt | date-time? | |
cutoverStarted | boolean | |
error | string? | |
errorCode | string? | |
lastReconciliation | ReconciliationSummaryDto? | |
lastReportAt | date-time? | |
leaseExpiresAt | date-time | |
load | RunLoadDto | |
pendingCommands | RunCommand[] | |
planVersion | int32 | |
projectId | uuid | |
quarantinedRows | int64 | |
runId | uuid | |
scheduledAt | date-time | |
scheduledBy | string | |
state | RunState | One of Scheduled, Loading, Syncing, Paused, ReadyForCutover, CuttingOver, Completed, RolledBack, Failed |
stateLabel | string | |
stateReason | string? | |
sync | RunSyncDto | |
tables | RunTableDto[] | |
writePlane | RunWritePlaneDto |
PauseMigrationRun
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}:pauseQueue Pause for the agent (delivered with its next report).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
ResumeMigrationRun
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}:resumeQueue Resume for a paused run.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
RetryFailedChunks
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}:retryRetry failed chunks; a failed or stalled run is handed to the agent again and resumes from its last committed chunk.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
GetCutoverChecklist
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutoverThe cutover checklist: five steps with progress, four-eyes approval, what blocks the switch, your own switch steps, the rollback window.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | CutoverChecklistDto |
Response 200: CutoverChecklistDto
| Field | Type | Notes |
|---|---|---|
callerCanRollBack | boolean | |
canRollBack | boolean | |
customerSteps | string[] | |
endpointsRepointed | int32 | |
forcedBy | string? | |
fourEyes | boolean | |
impact | CutoverImpactDto? | |
impactError | string? | |
modelsRepointed | int32 | |
planVersion | int32 | |
reconciliationId | uuid? | |
rollbackWindowEndsAt | date-time? | |
runId | uuid | |
started | boolean | |
startedAt | date-time? | |
startedBy | string? | |
state | RunState | One of Scheduled, Loading, Syncing, Paused, ReadyForCutover, CuttingOver, Completed, RolledBack, Failed |
steps | CutoverStepDto[] |
StartCutover
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutoverOpen the cutover wizard of a syncing run.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
RollbackCutover
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutover:rollbackRoll serving back to the source during the rollback window (Steward/Owner); change capture stops.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
ConfirmCutoverStep
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/cutover/steps/{step}:confirmPerform the active step (FreezeSource, FinalSync, FinalReconciliation, Switch, RollbackWindow = close it), or approve it as the second person.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes | |
step | path | CutoverStepKind | yes |
Request body (application/json): ConfirmCutoverStepRequest?
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
GetRunQuarantine
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/quarantineQuarantined rows per table: counts and business keys only (at most 200 per table), never values.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | RunQuarantineDto |
Response 200: RunQuarantineDto
| Field | Type | Notes |
|---|---|---|
runId | uuid | |
tables | QuarantineTableDto[] | |
total | int64 |
GetRunTimeline
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/runs/{runId}/timelineWhat happened in the run, newest first, with who did it (a person, an agent or Keel).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
runId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | RunTimelineDto |
Response 200: RunTimelineDto
| Field | Type | Notes |
|---|---|---|
entries | RunTimelineEntryDto[] | |
planVersion | int32 | |
runId | uuid |
SetMigrationScope
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/scopeSet the source tables the migration covers (empty: every table). Inference, the plan, code generation, reconciliation and runs skip excluded tables. Audited; with a committed plan it commits the next plan version under the new scope.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): SetMigrationScopeRequest
| Field | Type | Notes |
|---|---|---|
tables | ScopedTableInput[]? | The included source tables; null or empty covers every table of the migration's sources (F18 #36). |
| Status | Description | Body |
|---|---|---|
| 200 | OK | MigrationScopeSetDto |
Response 200: MigrationScopeSetDto
| Field | Type | Notes |
|---|---|---|
includedTables | int32? | |
planVersion | int32? |
GetTableMappings
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tablesThe workbench's table list: source → target, status, confidence, coverage and gaps.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
status | query | MappingStatus | no | |
search | query | string | no | |
page | query | int32 | no | |
pageSize | query | int32 | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | PagedResultOfTableMappingSummaryDto |
Response 200: PagedResultOfTableMappingSummaryDto
| Field | Type | Notes |
|---|---|---|
hasNext | boolean | |
items | TableMappingSummaryDto[] | |
page | int32 | |
pageSize | int32 | |
totalCount | int64 |
GetTableMapping
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}One table mapping with its column grid (sources, transform, target, confidence, evidence) and gaps.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 200 | OK | TableMappingDto |
Response 200: TableMappingDto
| Field | Type | Notes |
|---|---|---|
band | ConfidenceBand | One of High, Medium, Low |
columns | ColumnMappingDto[] | |
confidence | number | |
coverage | number | |
decidedAt | date-time? | |
decidedBy | string? | |
dedupeKeys | string[] | |
droppedSourceColumns | SourceColumnDto[] | |
evidence | MigrateEvidenceDto[] | |
filter | string? | |
id | uuid | |
incrementalColumn | string? | |
join | string? | |
loadPattern | LoadPattern | One of Full, IncrementalByKey, IncrementalByTimestamp |
origin | Origin | One of Discovered, Inferred, LlmSuggested, UserDefined, Imported |
projectId | uuid | |
sourceColumns | SourceColumnDto[] | |
sourceRowCount | int64? | |
sources | string[] | |
status | MappingStatus | One of Proposed, Accepted, Rejected, NeedsWork |
target | string | |
targetColumns | TargetColumnDto[] | |
unmappedTargetColumns | TargetColumnDto[] |
EditTableMapping
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}Set a table mapping's source table(s), join, filter, dedupe keys and load pattern; accepted.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes |
Request body (application/json): EditTableMappingRequest
| Field | Type | Notes |
|---|---|---|
dedupeKeys | string[]? | |
filter | string? | Source WHERE predicate. |
incrementalColumn | string? | |
join | string? | Join condition in source SQL when there are several sources. |
loadPattern | LoadPattern | One of Full, IncrementalByKey, IncrementalByTimestamp |
sources | string[] | Source tables as schema.table (from the migration's sources' latest scans). |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
AcceptTableMapping
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}:acceptAccept a table mapping and its proposed columns at or above minColumnConfidence (default: all).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes |
Request body (application/json): AcceptTableMappingRequest?
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
EditColumnMapping
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/columns/{targetColumn}Set the source column(s) of a target column (creates the mapping for a gap column); accepted.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes | |
targetColumn | path | string | yes |
Request body (application/json): EditColumnMappingRequest
| Field | Type | Notes |
|---|---|---|
notes | string? | |
sources | ColumnSourceRequest[] |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
PreviewTransformSql
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/columns/{targetColumn}:previewThe SQL a column mapping compiles to in the target dialect; a draft in the body is previewed without saving.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes | |
targetColumn | path | string | yes |
Request body (application/json): PreviewTransformRequest?
| Status | Description | Body |
|---|---|---|
| 200 | OK | PreviewSqlDto |
Response 200: PreviewSqlDto
| Field | Type | Notes |
|---|---|---|
dialect | SourceKind | One of PostgreSql, SqlServer, MySql, Snowflake, BigQuery, Databricks, Oracle, Redshift |
sql | string | |
targetColumn | string |
SetTransform
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/columns/{targetColumn}/transformSet a column mapping's transform (parameters checked against the transform contract); accepted.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes | |
targetColumn | path | string | yes |
Request body (application/json): SetTransformRequest
| Field | Type | Notes |
|---|---|---|
kind | TransformKind | One of None, Cast, Trim, Case, Default, CodeMap, Concat, Split, DateParse, UnitConversion, CurrencyConversion, SurrogateKey, Hash, CustomSql |
parameters | object? | Keys per kind as in TransformParameters (e.g. format for DateParse, codeMap for CodeMap). |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
GetMappingEvidence
http
GET /api/v1/workspaces/{workspaceId}/migrations/{projectId}/tables/{tableMappingId}/evidenceWhy Keel proposed the table mapping, or one of its column mappings (?column=).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes | |
tableMappingId | path | uuid | yes | |
column | query | string | no |
| Status | Description | Body |
|---|---|---|
| 200 | OK | MappingEvidenceDto |
Response 200: MappingEvidenceDto
| Field | Type | Notes |
|---|---|---|
band | ConfidenceBand | One of High, Medium, Low |
classification | string? | |
confidence | number | |
evidence | MigrateEvidenceDto[] | |
origin | Origin | One of Discovered, Inferred, LlmSuggested, UserDefined, Imported |
sensitive | boolean | |
tableMappingId | uuid | |
target | string | |
targetColumn | string? |
SetMigrationTarget
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/targetSet the target: a registered data source (harvested like any source) or a semantic model's entities.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): SetMigrationTargetRequest
| Field | Type | Notes |
|---|---|---|
dataSourceId | uuid? | The target data source (Kind DataSource), or for a model the database reconciliation reads (optional). |
kind | TargetKind | One of DataSource, SemanticModel, UploadedSpec |
modelId | uuid? |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
UploadMigrationTarget
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/target:uploadSet the target from uploaded CREATE TABLE statements (.sql) or a dbt project (schema .yml files, or a zip): parsed in memory, 10 MB uploaded / 20 MB unzipped at most; the files are not kept. format: Ddl or Dbt; dialect: a SourceKind (PostgreSql, SqlServer, Snowflake…); dataSourceId optionally names the database reconciliation reads.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (multipart/form-data): object
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
RegisterWriteCredential
http
PUT /api/v1/workspaces/{workspaceId}/migrations/{projectId}/write-credentialRegister the separate write credential: a secret NAME on the private agent, its user and the target schemas it may write. Untested until checked.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
Request body (application/json): RegisterWriteCredentialRequest
| Field | Type | Notes |
|---|---|---|
agentId | uuid | The private agent that holds the secret and runs the migration (the sources' agent). |
schemas | string[] | Target schemas the credential may write (the staging schema keel_stage is added). |
secretName | string | The NAME of the write credential's secret in the agent's local store (never the secret). |
username | string |
| Status | Description | Body |
|---|---|---|
| 204 | No Content | — |
TestWriteCredential
http
POST /api/v1/workspaces/{workspaceId}/migrations/{projectId}/write-credential:testQueue the scope check on the agent: a credential that can write outside its schemas (or lacks what a run needs) is refused.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
workspaceId | path | uuid | yes | |
projectId | path | uuid | yes |
| Status | Description | Body |
|---|---|---|
| 202 | Accepted | JobAcceptedDto |
Response 202: JobAcceptedDto
| Field | Type | Notes |
|---|---|---|
jobId | uuid |