Skip to main content

02 - First Movement (Dry-Run)

Experience the full flow in dry-run mode: register a template -> create a movement -> approve it -> check status. Confirm behavior through the API layer only, without live exchange integration.
Prerequisite: In 01-local-setup.md, the server is running on localhost:8100 with MG_AUTH_ENABLED=false and MG_WORKERS_ENABLED=false.

Full Flow


Step 1: Register a Template

Register a CEX 3-node template (Upbit -> Bybit XRP):
risk_controls is free-form, and only max_amount binds. max_amount is enforced fail-closed at dispatch. asset_allowlist is descriptive — it is pinned into the plan hash, but nothing rejects a movement whose intent.asset falls outside it. See the v3 endpoints reference for the full enforced set.
Check these fields in the success response:
  • graph_shape: "linear" - executable in v3.0
  • executable_in_v3_0: true
  • topological_order: ["withdraw", "withdraw_observe", "deposit_observe"]

Step 2: Create a Movement

Create a movement from the registered template:
Check these fields in the response:
  • movement_id: UUID - used in later API calls
  • request_state: "PENDING_APPROVAL" - waiting for approval
  • compiled_plan_hash: "sha256:..." - required for approval
You can create a movement without callback. It still works, but no state-change notifications are sent. The callback URL is a nested field — callback: {"url": "..."}, not a top-level callback_url (a top-level callback_url is silently ignored).

Step 3: Approve the Movement

Send the approval request with compiled_plan_hash:
Check these fields in the response:
  • request_state: "APPROVED" -> if workers are enabled, it transitions to "EXECUTING"
  • approval_status: "approved"
Why compiled_plan_hash is required: it guarantees the plan was not altered between creation and approval. Sending the wrong hash returns 409 Conflict.

Step 4: Check Status

In dry-run mode (MG_WORKERS_ENABLED=false):
  • request_state stays at "APPROVED" (because the dispatcher is off)
  • Node state stays "BLOCKED" (the first frontier node) or remains inactive
If workers are enabled and exchange credentials are configured:
  • request_state: "EXECUTING" -> "COMPLETED"
  • Node states advance per node kind. The representative path for a signing on-chain action node is BLOCKED -> READY -> PREPARING -> AWAITING_SIGNATURE -> SUBMITTING -> SUBMITTED -> OBSERVING -> COMPLETED. Common variants: a node needing no signature skips AWAITING_SIGNATURE; a sync-terminal submit (e.g. cex_withdrawal) goes SUBMITTING -> COMPLETED directly; an observe-only node (e.g. cex_deposit_status) goes READY -> OBSERVING -> COMPLETED.

Step 5: List Movements


Python Client Example


Movement State Flow Summary

  • PENDING_APPROVAL: Waiting for approval. POST .../approve or POST .../reject
  • APPROVED: Approved. If workers are enabled, it automatically transitions to EXECUTING
  • EXECUTING: Nodes are running
  • COMPLETED: All nodes finished
  • FAILED: An unrecoverable failure occurred
For the full state machine, see the States and Transitions reference.

Troubleshooting


Next: 03-template-cookbook.md - template examples by lane