---
title: "Migrator — API v1 and MCP | Nodea Documentation"
description: "Full reference for the Migrator module: REST API v1 endpoints (list, detail, logs, start, execute, retry failed, delete), account:* scopes, MCP tools and curl / JSON-RPC examples. Source credentials are write-only."
url: "https://nodea.io/en/api-docs/migrations"
lang: "en"
updated: "2026-07-16"
---

# Migrator — API v1 and MCP | Nodea Documentation

> Migrator module reference — API v1 endpoints (filtered list, detail with resources, logs, start run, execute, retry failed resources, delete), account:read/write/delete scopes, MCP tools and examples. Source-provider credentials are never returned.

The **Migrator** module imports monitors, contacts, status pages and WHMCS entities from external providers into Nodea. A migration run (MigratorRun) follows the lifecycle: start → discovery (reading resources through the provider API) → review → execute (plan + import). This document describes the REST API v1 layer (/api/v1) and the module's MCP tools.

## Authentication and scopes

API v1 authenticates with a Passport personal access token via the Authorization: Bearer \<token\> header. This module's routes are guarded by the account scope matching the operation tier:

- account:read — listing, detail, logs.
- account:write — start a run, execute, retry failed resources.
- account:delete — permanently delete a run (cascades resources and logs).

The whole module is additionally gated by the Pennant flag features:migrator — disabling it hides the module from the web UI and the API. Rate limit: throttle:api-v1 = 240/min per token user. Additionally, **starting a run is limited to 5 attempts per minute** per user (a shared budget across web and MCP, code discovery\_rate\_limited / 429). In MCP, each tool additionally requires the transport scope mcp:use and the migrator flag.

## Ownership and visibility

Migration runs have no policy class or sharing model — every access is strictly owner-scoped by user\_id. A foreign or unknown id consistently yields 404 (not 403), so the API never confirms that a foreign run exists. In MCP this maps to a single "not found or not accessible" error. The run id is a **UUID** (string).

## Sensitive-data safety

**Source-provider credentials are write-only: accepted on start, stored encrypted (encrypted:json + $hidden on the model) and never returned by any resource.** Internal columns — the resumable checkpoint cursor, the raw plan blob, discovery\_summary internals, credentials\_purge\_at — are likewise not exposed. Run resources do not reveal the raw provider blobs (external\_data/normalized\_data) or the internal import linkage (target\_model/target\_id).

## Side effects — asynchronous and run state

Start, execute and retry run out-of-band through the queue (dedicated discovery/planning/resources queues) — those actions return 202 Accepted, while starting a run returns 201 Created with the resource. Only a run in awaiting\_review can be executed (otherwise 422, code run\_not\_awaiting\_review). Retry is rejected when there are no failed resources (422, code no\_failed\_resources).

## API v1 — endpoints

MethodPathScopeDescriptionGET/api/v1/migrationsaccount:readOwner's runs (newest first), paginated. Filters status, provider. Each row: total\_resources, failed\_resources. GET/api/v1/migrations/{run}account:readRun detail with resources (capped at 500) and meta.resource\_counts (per-status breakdown). GET/api/v1/migrations/{run}/logsaccount:readRun log ledger (newest first), paginated. Filter errors\_only. POST/api/v1/migrationsaccount:writeStart a run (provider + write-only credentials). Queues discovery. Returns 201; 5/min limit → 429. POST/api/v1/migrations/{run}/executeaccount:writeExecute the run (plan + import). Only in awaiting\_review. Returns 202/422. POST/api/v1/migrations/{run}/retry-failedaccount:writeRetry failed resources (reset to pending + redispatch). Returns 202 with retried; none failed → 422. DELETE/api/v1/migrations/{run}account:deletePermanently delete the run (cascade). Returns 204.

### GET /migrations — query parameters

- status (enum, optional) — pending, discovering, awaiting\_review, executing, paused\_conflicts, completed, completed\_with\_errors, failed, cancelled.
- provider (enum, optional) — uptime\_robot, statuscake, pingdom, better\_stack, oh\_dear, hetrix\_tools, site24x7, whmcs, phpipam.
- per\_page (int 1–100, default 20), page (int ≥1).

Run row (MigrationRunResource): id (UUID), provider, status, stats, total\_resources, failed\_resources, error\_message, started\_at, finished\_at, created\_at, updated\_at. Detail adds resources\[\] (resource: id, resource\_type, external\_id, action, status, attempts, error\_message). Log (MigrationLogResource): id, level, message, context, logged\_at.

### POST /migrations — body parameters

- provider (string, required) — one of the providers above.
- credentials (object of key→string, optional) — **write-only**. Required fields depend on the provider: the credentials\_schema in config/migrator.php enforces the presence of fields marked required (missing → 422 on credentials.\<field\>).

### Error codes

- 401 — missing/invalid token.
- 403 — missing required scope.
- 404 — unknown or foreign run.
- 422 — validation, executing a run outside awaiting\_review (run\_not\_awaiting\_review), or no failed resources to retry (no\_failed\_resources).
- 429 — start limit exceeded (discovery\_rate\_limited).

## Examples — API

### List runs filtered by status and provider

curl -s "https://app.nodea.io/api/v1/migrations?status=awaiting\_review&provider=uptime\_robot" \\ -H "Authorization: Bearer $NODEA\_TOKEN" \\ -H "Accept: application/json"

### Start a migration run (write-only credentials)

curl -s -X POST https://app.nodea.io/api/v1/migrations \\ -H "Authorization: Bearer $NODEA\_TOKEN" \\ -H "Content-Type: application/json" \\ -d '{ "provider": "uptime\_robot", "credentials": { "api\_key": "u123456-abcdef..." } }'

### Execute a reviewed run

curl -s -X POST https://app.nodea.io/api/v1/migrations/{run}/execute \\ -H "Authorization: Bearer $NODEA\_TOKEN" \\ -H "Accept: application/json"

### Retry failed resources

curl -s -X POST https://app.nodea.io/api/v1/migrations/{run}/retry-failed \\ -H "Authorization: Bearer $NODEA\_TOKEN" \\ -H "Accept: application/json"

## MCP — tools

The MCP tools share the authentication and scope model with API v1 (Bearer + scope in ensureScope) and the migrator flag (a tool on an inactive flag disappears from tools/list). The run id is a UUID (string). A missing and a foreign id return the same error. Start, execute and retry are asynchronous (a queued acknowledgement). The destructive tool migration-delete is marked destructive and requires an explicit confirm: true. Provider credentials remain write-only.

NameScopeModeDescriptionmigrations-listaccount:readread-onlyRun history (newest first) with total\_resources/failed\_resources. Filters status, provider; page, per\_page (max 50). migration-getaccount:readread-onlyRun detail: header, resources (capped at 500), the 50 most recent logs and resource\_counts. Param: id. Credentials never returned. migration-createaccount:writewriteStart a run; provider, credentials (object, write-only). Queues discovery. 5/min limit. migration-executeaccount:writewriteExecute the run (plan + import); id. Only in awaiting\_review. migration-retry-failedaccount:writewriteRetry failed resources; id. Rejected when none failed. migration-deleteaccount:deletedestructive (confirm)Permanently delete the run with its resources and logs. Requires confirm: true; id.

### Examples — MCP (JSON-RPC)

{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "migration-create", "arguments": { "provider": "uptime\_robot", "credentials": { "api\_key": "u123456-abcdef..." } } } } { "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "migration-delete", "arguments": { "id": "9b1f...uuid", "confirm": true } } }

## Related

- [Domains — API v1 and MCP | Nodea Documentation](https://nodea.io/en/api-docs/domains)
- [Hosting](https://nodea.io/en/glossary/hosting)

---

Languages: [pl](https://nodea.pl/pl/dokumentacja-api/migrations.md)  
Site index: [llms.txt](https://nodea.io/en/llms.txt)
