API

Migration

Discover, adopt, and move services between servers.

The Migration API brings workloads you deployed to a server by hand — Compose stacks and stray containers — under Synq management. It inspects a server's Docker over SSH, returns the stacks it can adopt, and then creates an Synq services project from the ones you pick. In the dashboard this is the migration wizard; there is no CLI equivalent.

Self-hosted only

This module is mounted only when your instance runs in self-hosted mode — adopting a deployment requires SSH into a server you manage, which a hosted cloud has no notion of. On a cloud instance these routes are not mounted and return 404.

Scan a server

Read-only. Enumerates the server's Docker — Compose stacks plus hand-run containers — reconciles them with any Compose files found on disk, and returns the discovered stack for the wizard to preview. Nothing on the server changes.

POST /api/migration/scan

Prop

Type

curl -X POST "$SYNQ_URL/api/migration/scan" \
  -H "Authorization: Bearer $SYNQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"serverId":"srv_123"}'

On success the response is { "success": true, "stack": … }, where stack describes the discovered Compose stacks and containers that can be adopted.

Adopt discovered services

Creates an Synq services project from the services you selected. The server is re-discovered server-side (the server is the source of truth, not client-sent config), and existing named volumes are reused in place — this records the project only; deploy and cutover are separate steps.

POST /api/migration/adopt

Prop

Type

curl -X POST "$SYNQ_URL/api/migration/adopt" \
  -H "Authorization: Bearer $SYNQ_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"serverId":"srv_123","projectName":"legacy-stack","serviceNames":["web","worker"]}'

On success the response is { "success": true, … } with the created project's details.

Run a reviewed migration

POST /api/migration/migrate starts the complete migration. Per-service options use the discovered container IDs as keys; legacy service-name keys remain accepted. routesByServiceName accepts an array of routes per service, preserving aliases, listen ports, path prefixes and exact matches. Environment values are saved in the service's production environment scope.

When routes are selected, migration prepares the target edge before changing source containers. If another proxy must be replaced, the run waits for consent. Read pendingPrompt from GET /api/migration/migrations/:id (also included in the stream snapshot), then answer it with:

POST /api/migration/migrations/:id/respond
Content-Type: application/json

{"promptId":"<pendingPrompt.promptId>","action":"migrate"}

Use an action ID from the current prompt. An expired, already answered or invalid prompt returns 409. Answering requires write access to both migration servers. Cancelling keeps the original proxy and source containers intact. After attachment or deployment, Synq applies the owned routes and retries pending domain verification; unresolved routing failures remain visible on the run.

Errors

400 — missing or empty field

serverId is required on both routes; adopt additionally requires a non-empty projectName and at least one entry in serviceNames. The response body names the missing field.

404 — server not found

The serverId doesn't belong to your organization (or doesn't exist). List your servers with synq server list to get valid IDs. On a cloud instance the module isn't mounted at all, so every path here returns 404.

502 — scan or adopt failed

Synq couldn't reach or inspect the server's Docker (SSH unreachable, Docker not running, permission denied), or the adoption failed. The message includes the underlying reason. Confirm the server is online and its Docker is accessible, then retry.

Operations

OperationREST API
List active server migration sessions.GET /api/migration/active
server:read · Self-hosted
Create an Synq project from the selected discovered services.POST /api/migration/adopt
server:write · Self-hosted
Start a server migration from the reviewed plan.POST /api/migration/migrate
server:write · Self-hosted
Delete an eligible migration record.DELETE /api/migration/migrations/:id
server:write · Self-hosted
Read migration progress and state.GET /api/migration/migrations/:id
server:read · Self-hosted
Request cancellation of a migration.POST /api/migration/migrations/:id/cancel
server:write · Self-hosted
Clean up resources created on the migration target.POST /api/migration/migrations/:id/cleanup-target
server:write · Self-hosted
Switch traffic to the prepared migration target.POST /api/migration/migrations/:id/cutover
server:write · Self-hosted
Resume an interrupted migration.POST /api/migration/migrations/:id/resume
server:write · Self-hosted
Answer a pending migration prompt, including edge takeover consent.POST /api/migration/migrations/:id/respond
server:write · Self-hosted
Stream migration progress.GET /api/migration/migrations/:id/stream
server:read · Self-hosted
Preview a migration plan.POST /api/migration/preview
server:write · Self-hosted
Import a discovered project.POST /api/migration/project
server:write · Self-hosted
Refresh an imported project from its source.POST /api/migration/reimport
server:write · Self-hosted
Read Compose configuration from a repository for import.POST /api/migration/repo-compose
server:read · Self-hosted
Reveal explicitly requested environment values for an authorized import.POST /api/migration/reveal-env
server:write · Self-hosted
List migration history.GET /api/migration/runs
server:read · Self-hosted
Inspect a server's Docker and return the adoptable stack — read-only, changes nothing.POST /api/migration/scan
server:write · Self-hosted
Stream server-discovery progress.GET /api/migration/scan/stream
server:write · Self-hosted

On this page