Eden REST API
Migration APIs
/api/v1This reference covers the API surfaces used to run and operate migrations in Gateway.
There are two layers:
- Guided Redis workflow API: recommended for operators, dashboards, and supervised agents. It owns sequencing and reduces the chance of running steps out of order.
- Raw migration API: lower-level migration record, analysis, compatibility, testing, traffic, rollback, and completion controls.
All paths below are shown with the generated /api/v1 prefix.
Authentication
Most calls require:
Authorization: Bearer <token>Examples assume:
export EDEN=http://localhost:8000/api/v1
export AUTH_HEADER="Authorization: Bearer $TOKEN"Guided Redis Workflow
The guided workflow currently targets Redis-compatible migrations. Use it when you want Gateway to own the normal sequence: create run, collect setup, prepare, run analysis and validation, wait for approval, execute, monitor, and complete.
Create Workflow Run
POST /api/v1/migration-workflows/rediscurl -sS -X POST "$EDEN/migration-workflows/redis" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{}'The response includes run.id. Store it as RUN_ID.
List Workflow Runs
GET /api/v1/migration-workflows/redis?limit=20Optional filters include workflow phase. Common phases are:
| Phase | Meaning |
|---|---|
setup | The run exists but still needs source, target, and strategy selections. |
target_provisioning | Target creation or target details are in progress. |
validation | Gateway is preparing analysis, compatibility, and test inputs. |
awaiting_approval | The run is ready for a human approval gate. |
executing | Migration execution is active. |
monitoring | Execution finished enough to monitor before completion. |
awaiting_completion | The target can be accepted or the workflow can be cancelled. |
completed | Workflow completed. |
failed | Workflow failed and may be retried. |
cancelled | Workflow was cancelled. |
Get Workflow Run
GET /api/v1/migration-workflows/redis/{run_id}Use this for polling, recovery, and UI refreshes. The response includes current phase, source/target endpoint ids, interlay id, lower-level migration id, step results, blocked reason when present, and allowed actions.
Subscribe To Workflow Events
GET /api/v1/migration-workflows/redis/{run_id}/eventsThis endpoint streams server-sent events.
curl -N "$EDEN/migration-workflows/redis/$RUN_ID/events" \
-H "$AUTH_HEADER"Event names:
| Event | Meaning |
|---|---|
snapshot | Initial workflow state. |
workflow | Workflow state changed. |
heartbeat | Keepalive during quiet periods. |
terminal | Workflow reached completed, failed, or cancelled. |
Submit Setup
POST /api/v1/migration-workflows/redis/{run_id}/setupcurl -sS -X POST "$EDEN/migration-workflows/redis/$RUN_ID/setup" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d "{
\"source_endpoint_uuid\": \"$SOURCE_ENDPOINT_UUID\",
\"target_choice\": \"existing_endpoint\",
\"target_endpoint_uuid\": \"$TARGET_ENDPOINT_UUID\",
\"strategy\": \"blue_green\",
\"conflict_policy\": \"Replace\",
\"data_movement_mode\": \"scan\",
\"unify_conflict_resolution\": \"newest_write\",
\"write_consistency\": \"SourceAuthoritative\",
\"preserve_ttl\": true,
\"require_manual_approval\": true
}"| Field | Values |
|---|---|
target_choice | existing_endpoint, provision_new_aws, provision_new_azure, self_hosted |
strategy | big_bang, canary, blue_green |
conflict_policy | Replace, None, Merge |
data_movement_mode | scan, bidirectional_unify |
unify_conflict_resolution | newest_write, source_wins, target_wins, manual |
write_consistency | SourceAuthoritative, BestEffort, TargetAuthoritative, BothRequired |
Submit Target Details
POST /api/v1/migration-workflows/redis/{run_id}/targetUse this when target_choice requires a target to be provisioned or described.
curl -sS -X POST "$EDEN/migration-workflows/redis/$RUN_ID/target" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"cloud_provider": "aws_elasticache",
"instance_type": "cache.m7g.large",
"region": "us-east-1"
}'Cloud provider values include aws_elasticache, azure_cache_for_redis, and self_hosted.
Get Recommendations
POST /api/v1/migration-workflows/redis/{run_id}/recommendationsReturns target recommendations based on available workload analysis and endpoint metadata.
Prepare Workflow
POST /api/v1/migration-workflows/redis/{run_id}/preparePrepare resolves endpoints, prepares the interlay, creates the lower-level migration record, runs analysis, compatibility checks, and validation tests, then moves the workflow to either awaiting_approval or execution depending on setup.
curl -sS -X POST "$EDEN/migration-workflows/redis/$RUN_ID/prepare" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{}'Approve Workflow
POST /api/v1/migration-workflows/redis/{run_id}/approvecurl -sS -X POST "$EDEN/migration-workflows/redis/$RUN_ID/approve" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{}'Only approve after compatibility issues, validation results, rollback ownership, and monitoring have been reviewed.
Retry, Complete, Or Cancel Workflow
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migration-workflows/redis/{run_id}/retry | Retry a failed workflow. |
POST | /api/v1/migration-workflows/redis/{run_id}/complete | Complete a workflow after target acceptance. |
POST | /api/v1/migration-workflows/redis/{run_id}/cancel | Cancel a workflow before completion. |
All three accept an empty JSON object:
curl -sS -X POST "$EDEN/migration-workflows/redis/$RUN_ID/complete" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{}'Raw Migration API
The raw migration API is useful when building a custom dashboard or when debugging a guided workflow. It does not protect you from running steps in the wrong order.
For the stage-by-stage operator flow, including planning, execution preflight, live-write mode readiness, and cutover preflight, see Live Migration API Stage Map.
Create Migration
POST /api/v1/migrations
Content-Type: application/json
Authorization: Bearer <token>curl -sS -X POST "$EDEN/migrations" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"id": "redis-bluegreen",
"description": "Redis source to target migration",
"strategy": {
"type": "blue_green",
"active_is_new": false,
"write_mode": {
"mode": "dual_write",
"policy": "SourceAuthoritative"
}
},
"data": {
"Snapshot": {
"replace": "Replace"
}
},
"preserve_ttl": true,
"skip_testing": false
}'skip_analysis:true is rejected. Use the governed migration-stage API after creation when an eligible advisory analysis result requires an audited operator decision.
List Migrations
GET /api/v1/migrationscurl -sS "$EDEN/migrations" \
-H "$AUTH_HEADER"Add X-Eden-Verbose: true for expanded details.
Get Migration
GET /api/v1/migrations/{migration_id}curl -sS "$EDEN/migrations/$MIGRATION_ID" \
-H "$AUTH_HEADER"Attach API Or Interlay
Migration attachment belongs to Live Migrations. Use these routes to associate an approved API or an Gateway interlay with the migration record before execution; do not configure migration lifecycle through the Interlays API.
An interlay can be attached to one active migration at a time. Complete, cancel, or roll back its current association before attaching it to another migration. For the complete operator sequence, see Live Migration API Stage Map.
Attach an API:
POST /api/v1/migrations/{migration_id}/api/{api_id}Attach an interlay:
POST /api/v1/migrations/{migration_id}/interlay/{interlay_id}curl -sS -X POST "$EDEN/migrations/$MIGRATION_ID/interlay/$INTERLAY_UUID" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d "{
\"target_endpoint\": \"$TARGET_ENDPOINT_UUID\"
}"Analysis
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migrations/{migration_id}/analysis/run | Start or rerun analysis. |
GET | /api/v1/migrations/{migration_id}/analysis/info | Read analysis status. |
GET | /api/v1/migrations/{migration_id}/analysis/history | Read the historical window used by analysis. |
GET | /api/v1/migrations/{migration_id}/analysis/timeseries | Read analysis timeseries. |
PATCH | /api/v1/migrations/{migration_id}/analysis/config | Configure automatic analysis. |
POST | /api/v1/migrations/{migration_id}/analysis/stop | Stop an active analysis run. |
Analysis requires enough interlay traffic and Redis poll metrics to represent the workload.
Compatibility
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migrations/{migration_id}/compatibility/start | Start the initial check or explicitly refresh raw observations. |
GET | /api/v1/migrations/{migration_id}/compatibility/info | Read all immutable raw generations and effective dispositions. |
POST | /api/v1/migrations/{migration_id}/compatibility/resolve | Mark one issue resolved with notes. |
POST | /api/v1/migrations/{migration_id}/compatibility/unresolve | Reopen one issue. |
POST | /api/v1/migrations/{migration_id}/compatibility/acknowledge-all | Acknowledge every eligible accept_risk issue atomically. |
Redis checks include version, DUMP/RESTORE compatibility, module mismatch warnings, ACL/write permission checks, and cluster topology checks.
Guided workflow retries reuse the current completed compatibility generation and do not refresh it automatically. This means an acknowledgement remains effective on retry. An explicit compatibility/start refresh preserves earlier snapshots and carries a disposition only when the finding fingerprint and policy semantics are unchanged; new, changed, removed-then-reintroduced, or expired findings remain blocking.
Failed refresh attempts remain in raw history and consume generation numbers, but they do not become disposition sources. The next successful refresh reconciles against the latest earlier successfully completed generation, so a transient check failure does not erase a still-matching acknowledgement.
compatibility/info exposes the snapshot revision, raw and disposition generations, is_latest_generation, generation_order_trusted, policy/check versions, and issue fingerprints. Raw generations are allocated atomically per migration, stored in a unique indexed database column, and are the only ordering authority; service host timestamps and response list position do not determine which result is current. Pre-generation rows remain visible after upgrade but are marked generation_order_trusted:false; they cannot authorize execution, disposition mutation or carry-forward, workflow reuse, or Redis topology. An explicit compatibility refresh creates the first trusted generation. If an untrusted row remains running or not_started, refresh atomically marks it failed and durably superseded before inserting the trusted row. The service logs each actual row transition from the allocator transaction with migration and compatibility UUIDs, generation/trust, status, revision and fence before/after, and the decision; it does not infer a transition from the latest history row. At most 64 transitions are allowed per refresh, and exceeding that bound rolls the allocator transaction back before any compatibility row changes. PostgreSQL and embedded Turso enforce the superseded marker with a trigger, so current CAS writers and old UUID-only writers are rejected after supersession and after restart. The old worker observes a database write failure; the preserved superseded row and the trusted generation remain the recovery authority. observed_status and observed_issues are immutable; effective_status, effective_dispositions, and issues show the current disposition projection. Send the latest successfully completed trusted compatibility_uuid and its expected_revision with compatibility/resolve or compatibility/unresolve to detect stale clients; historical, failed, and untrusted snapshots cannot be mutated. Concurrent updates—and disposition writes attempted while a refresh is running—return 409 Conflict instead of overwriting a decision. An exact retry is idempotent and can repair a migration-status projection without replacing the original audit decision. Bulk acknowledgement is all-or-nothing and rejects the entire request when any blocking finding lacks the explicit safe accept_risk option, is expired, or is malformed. Execution preflight and /migrate recheck the latest effective generation, so an untrusted/running/failed refresh, unhandled finding, or expired disposition cannot execute from a stale Ready state; /migrate also repairs a stale pre-execution status from the durable effective result before data movement.
Heterogeneous Planning
Heterogeneous migrations require a finalized schema mapping and request mapping plan before execution. The migration constructor intentionally does not accept the final mapping; Gateway discovers source schema and live query shapes first, then operators or agents patch the plan.
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migrations/{migration_id}/planning/run | Discover source schema, source keys, query coverage, and planning blockers. |
POST | /api/v1/migrations/{migration_id}/planning/validate | Validate the current schema and request mapping plan without advancing execution. |
POST | /api/v1/migrations/{migration_id}/planning/finalize | Mark planning complete only when schema and request mapping blockers are gone. |
GET | /api/v1/migrations/{migration_id}/planning/schema-mapping | Read the current schema mapping. |
PATCH | /api/v1/migrations/{migration_id}/planning/schema-mapping | Patch schema mapping with a source-key map or full route mapping. |
GET | /api/v1/migrations/{migration_id}/planning/schema-mapping/missing | List unmapped source objects and fields discovered from the source. |
GET | /api/v1/migrations/{migration_id}/planning/target-schema-plan | Preview target objects, fields, primary keys, foreign keys, and index counts generated by the mapping. |
GET | /api/v1/migrations/{migration_id}/planning/request-mapping | Read the request and response mapping plan. |
PATCH | /api/v1/migrations/{migration_id}/planning/request-mapping | Replace the request mapping plan. |
GET | /api/v1/migrations/{migration_id}/planning/request-mapping/missing | List unmapped live writes, reads, procedures, response templates, blocked DDLs, and unsupported query shapes. |
GET | /api/v1/migrations/{migration_id}/planning/request-mapping/query/{query_key} | Read one request mapping. |
PATCH | /api/v1/migrations/{migration_id}/planning/request-mapping/query/{query_key} | Patch one request mapping. |
PATCH | /api/v1/migrations/{migration_id}/planning/request-mapping/queries | Patch multiple request mappings in one request. |
GET | /api/v1/migrations/{migration_id}/planning/agent | Read the planning agent configuration. |
PATCH | /api/v1/migrations/{migration_id}/planning/agent | Configure the planning agent used for mapping recommendations. |
Query seeding is available when live request analysis is enabled:
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migrations/{migration_id}/planning/query-seeding/start | Start a timed window that records normalized live source query shapes. |
GET | /api/v1/migrations/{migration_id}/planning/query-seeding/status | Read seeding progress and query counts. |
GET | /api/v1/migrations/{migration_id}/planning/query-seeding/queries | List discovered source query shapes. |
GET | /api/v1/migrations/{migration_id}/planning/query-seeding/queries/{query_key} | Read one discovered query shape. |
Agent recommendation APIs are available when agent support is enabled:
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migrations/{migration_id}/planning/agent/recommend | Recommend schema mappings from discovered source shape. |
POST | /api/v1/migrations/{migration_id}/planning/agent/recommend-request-mapping | Recommend request and response mappings from seeded query shapes. |
HA Redis Migration Control
HA Redis Cluster migrations use a lane plan so several Eden nodes can own different Redis lanes while moving migration stages together. The HA plan is the authority for lane leases, checkpoints, validation digests, stage barriers, and cutover commitment. DBOS workflow tables may share the same Postgres deployment, but DBOS is a durable driver rather than a second HA stage authority.
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/migrations/{migration_id}/ha/plan | Read the current HA lane plan, revision, and canonical state digest. |
PUT | /api/v1/migrations/{migration_id}/ha/plan | Install the participant set and lane plan. |
POST | /api/v1/migrations/{migration_id}/ha/lanes/{lane_id}/lease | Claim or renew one lane owner lease. |
PATCH | /api/v1/migrations/{migration_id}/ha/lanes/{lane_id}/checkpoint | Publish progress, replay watermarks, and validation evidence under the active owner epoch. |
POST | /api/v1/migrations/{migration_id}/ha/confirm | Confirm that one Eden participant observes the current stage and exact state digest. |
POST | /api/v1/migrations/{migration_id}/ha/stage | Advance the stage after every participant confirmation and every lane barrier pass. |
Production evidence covers 3, 5, and 7 Eden participants. Forward stage movement requires every configured participant to confirm the identical state digest, even though the HA control plane uses a supermajority threshold for ordinary consensus-control progress.
See HA Redis Cluster Migrations for the deployment contract and examples.
Testing
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/migrations/{migration_id}/test/info | Get configured tests and current test status. |
POST | /api/v1/migrations/{migration_id}/test | Create one test definition. |
PATCH | /api/v1/migrations/{migration_id}/test/config | Replace the full suite. |
GET | /api/v1/migrations/{migration_id}/test/{test_name} | Get one test status. |
PATCH | /api/v1/migrations/{migration_id}/test/{test_name} | Replace one test definition. |
DELETE | /api/v1/migrations/{migration_id}/test/{test_name} | Delete one test definition. |
POST | /api/v1/migrations/{migration_id}/test/runs | Start a full run or a named test run. |
GET | /api/v1/migrations/{migration_id}/test/runs | List test run history. |
GET | /api/v1/migrations/{migration_id}/test/runs/{run_uuid} | Read one test run. |
GET | /api/v1/migrations/{migration_id}/test/runs/{run_uuid}/logs?since=0 | Tail run logs. |
POST | /api/v1/migrations/{migration_id}/test/cancel | Cancel active test run. |
GET | /api/v1/migrations/{migration_id}/test/logs?since=0 | Back-compatible active log tail. |
Start a full test run:
curl -sS -X POST "$EDEN/migrations/$MIGRATION_ID/test/runs" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{}'Start one named test:
curl -sS -X POST "$EDEN/migrations/$MIGRATION_ID/test/runs" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"test_name": "BatchSmokeTest"
}'Execute Migration
POST /api/v1/migrations/{migration_id}/migratecurl -sS -X POST "$EDEN/migrations/$MIGRATION_ID/migrate" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"interlay_ids": ["redis-live-interlay"],
"preserve_ttl": true,
"redis_settings": {
"enabled": false
},
"run_tests": true,
"require_analysis": true
}'If interlay_ids is omitted or empty, Gateway migrates all interlays attached to the migration.
Traffic Controls
| Method | Path | Purpose |
|---|---|---|
PATCH | /api/v1/migrations/{migration_id}/traffic | Adjust canary read percentage. |
PATCH | /api/v1/migrations/{migration_id}/toggle | Toggle blue/green active environment. |
GET | /api/v1/migrations/{migration_id}/live-write-mode | Read the current heterogeneous live-write execution mode. |
GET | /api/v1/migrations/{migration_id}/live-write-mode/readiness | Check whether LogAndReplay is caught up enough to switch to strict dual-write. |
PATCH | /api/v1/migrations/{migration_id}/live-write-mode | Switch a ready LogAndReplay migration to strict dual-write. |
Canary example:
curl -sS -X PATCH "$EDEN/migrations/$MIGRATION_ID/traffic" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"read_percentage": 0.25,
"reason": "Metrics healthy after initial canary."
}'Blue/green example:
curl -sS -X PATCH "$EDEN/migrations/$MIGRATION_ID/toggle" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"activate_new": true,
"reason": "Target validated under live traffic."
}'Runtime Status And Metrics
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/migrations/{migration_id}/live-metrics | Read runtime migration metrics. |
GET | /api/v1/migrations/{migration_id}/error-keys?limit=100 | Read Redis keys that failed migration or need review. |
GET | /api/v1/migrations/{migration_id}/write-log/status | Read LogAndReplay captured, replayed, lag, gap, and high-watermark status. |
GET | /api/v1/migrations/{migration_id}/write-log/events?limit=100 | List recent captured write-log events without raw payload bytes. |
GET | /api/v1/migrations/{migration_id}/write-log/gaps?limit=100 | List write-log consistency gaps that block replay readiness or cutover. |
GET | /api/v1/migrations/{migration_id}/runtime-query-misses?limit=100 | List runtime query misses recorded as consistency gaps. |
POST | /api/v1/migrations/{migration_id}/refresh | Refresh migration state. |
GET | /api/v1/migrations/jobs | List migration jobs in the current organization. |
GET | /api/v1/migrations/jobs/{job_uuid} | Read one tenant-owned job. |
POST | /api/v1/migrations/jobs/verify | Verify durable tenant/job linkage for all jobs or an optional job_uuid; it is read-only and reports worker-error counts. |
Pause, Resume, Complete, Cancel
| Method | Path | Purpose |
|---|---|---|
POST | /api/v1/migrations/{migration_id}/pause | Pause execution. |
POST | /api/v1/migrations/{migration_id}/resume | Resume execution. |
POST | /api/v1/migrations/{migration_id}/complete | Complete migration. |
POST | /api/v1/migrations/{migration_id}/cancel | Cancel migration. |
DELETE | /api/v1/migrations/{migration_id} | Delete migration record when allowed. |
Completion example:
curl -sS -X POST "$EDEN/migrations/$MIGRATION_ID/complete" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"reason": "Target stable after cutover.",
"force": false
}'Rollback
Rollback one interlay:
POST /api/v1/migrations/{migration_id}/interlay/{interlay_id}/rollbackRollback all interlays:
POST /api/v1/migrations/{migration_id}/interlays/rollbackcurl -sS -X POST "$EDEN/migrations/$MIGRATION_ID/interlays/rollback" \
-H "$AUTH_HEADER" \
-H "Content-Type: application/json" \
-d '{
"reason": "Rollback migration.",
"force": false,
"preserve_config": true,
"overwrite_on_reverse": false
}'