Overview
https://api.themigrator.appAll endpoints are versioned under /v1. TLS is required — HTTP requests are rejected.
All requests must include an Authorization header with a Bearer token. Generate API keys from Settings → API keys in your dashboard.
Authorization: Bearer tmk_live_••••••••••••••••••••••••••••••••
Keep your API key secret. Do not commit it to source control. Use environment variables.
Requests are rate-limited at 1,000 requests per minute per organisation. Exceeding this returns a 429 Too Many Requests response with a Retry-After header indicating how many seconds to wait.
All errors return a consistent JSON body with an error message, a machine-readable code, and the HTTP status.
{
"error": "Tenant not found",
"code": "TENANT_NOT_FOUND",
"status": 404
}Tenants
A tenant is a connected Microsoft 365 organisation. You must connect at least two tenants (source and destination) before creating a migration job.
Starts the Microsoft 365 OAuth 2.0 admin consent flow. Returns an authorization URL that a Global Admin must visit to grant the application the required Graph API permissions. After the admin completes consent, the callback endpoint stores the token and the tenant appears in your tenant list.
{
"authUrl": "https://login.microsoftonline.com/common/adminconsent?client_id=...",
"state": "tok_9Kx2mPqRv"
}curl -X POST https://api.themigrator.app/v1/tenants/connect \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "contoso.com",
"role": "source"
}'Returns all M365 tenants connected to the current organisation, including discovered object counts, storage quotas, and enabled workloads. Storage quota fields are populated during tenant discovery — they may be null if discovery has not completed.
{
"tenants": [
{
"id": "ten_01HXKP3B",
"domain": "contoso.com",
"type": "M365",
"role": "source",
"mailboxCount": 312,
"siteCount": 47,
"totalSizeBytes": 1099511627776,
"sharepointQuotaBytes": 26843545600000,
"sharepointUsedBytes": 8053063680000,
"onedriveQuotaPerUserBytes": 1099511627776,
"workloads": ["EMAIL", "SHAREPOINT", "ONEDRIVE", "TEAMS"],
"discoveredAt": "2026-04-10T09:23:00Z",
"connectedAt": "2026-04-10T09:00:00Z"
}
]
}curl https://api.themigrator.app/v1/tenants \ -H "Authorization: Bearer $API_KEY"
Returns detail for a single connected tenant.
{
"tenant": {
"id": "ten_01HXKP3B",
"domain": "contoso.com",
"type": "M365",
"role": "source",
"mailboxCount": 312,
"siteCount": 47,
"totalSizeBytes": 1099511627776,
"sharepointQuotaBytes": 26843545600000,
"sharepointUsedBytes": 8053063680000,
"onedriveQuotaPerUserBytes": 1099511627776,
"workloads": ["EMAIL", "SHAREPOINT", "ONEDRIVE", "TEAMS"],
"discoveredAt": "2026-04-10T09:23:00Z",
"connectedAt": "2026-04-10T09:00:00Z"
}
}curl https://api.themigrator.app/v1/tenants/ten_01HXKP3B \ -H "Authorization: Bearer $API_KEY"
Returns the list of users discovered in the tenant during the most recent discovery scan. Used by the wizard to populate the mailbox/user mapping step for Email, OneDrive, and Teams Chat migrations.
{
"users": [
{
"id": "dbu_01HXKP3C",
"tenantId": "ten_01HXKP3B",
"upn": "[email protected]",
"displayName": "John Smith",
"sourceSizeBytes": 3221225472
},
{
"id": "dbu_01HXKP3D",
"tenantId": "ten_01HXKP3B",
"upn": "[email protected]",
"displayName": "Lisa Nguyen",
"sourceSizeBytes": 1073741824
}
],
"latestJob": {
"id": "dis_01HXKP3E",
"status": "DONE",
"completedAt": "2026-04-10T09:23:00Z"
}
}curl https://api.themigrator.app/v1/tenants/ten_01HXKP3B/users \ -H "Authorization: Bearer $API_KEY"
Returns the list of SharePoint sites discovered in the tenant during the most recent discovery scan. Used by the wizard to populate the site mapping step for SharePoint migrations.
{
"sites": [
{
"id": "dbs_01HXKP3F",
"tenantId": "ten_01HXKP3B",
"siteId": "contoso.sharepoint.com,abc-123,...",
"name": "Marketing",
"url": "https://contoso.sharepoint.com/sites/marketing",
"sizeBytes": "10737418240"
}
],
"latestJob": {
"id": "dis_01HXKP3E",
"status": "DONE",
"completedAt": "2026-04-10T09:23:00Z"
}
}curl https://api.themigrator.app/v1/tenants/ten_01HXKP3B/sites \ -H "Authorization: Bearer $API_KEY"
Returns the list of Microsoft Teams workspaces discovered in the tenant during the most recent discovery scan. Used by the wizard to populate the team mapping step for Teams Channels migrations. Teams are discovered via the Microsoft Graph groups endpoint filtered by resourceProvisioningOptions eq 'Team'.
{
"teams": [
{
"id": "dbt_01HXKP3G",
"tenantId": "ten_01HXKP3B",
"teamId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
"name": "Engineering",
"description": "Core engineering team",
"memberCount": 24
},
{
"id": "dbt_01HXKP3H",
"tenantId": "ten_01HXKP3B",
"teamId": "ffffffff-0000-1111-2222-333333333333",
"name": "Sales",
"description": "",
"memberCount": 41
}
],
"latestJob": {
"id": "dis_01HXKP3E",
"status": "DONE",
"completedAt": "2026-04-10T09:23:00Z"
}
}curl https://api.themigrator.app/v1/tenants/ten_01HXKP3B/teams \ -H "Authorization: Bearer $API_KEY"
Revokes access and removes the tenant connection. Any running jobs that reference this tenant are paused before deletion.
{ "deleted": true }curl -X DELETE https://api.themigrator.app/v1/tenants/ten_01HXKP3B \ -H "Authorization: Bearer $API_KEY"
Jobs
A job represents a single migration task — one workload type between one source and one destination tenant. Jobs are processed asynchronously by the worker fleet via BullMQ.
Creates a new migration job and enqueues it for processing. The job starts immediately unless scheduledAt is provided. Scope options default to all available items for the selected type. The wizard UI runs pre-flight storage and licensing checks before calling this endpoint — when calling directly via API, ensure destination quotas are sufficient using the tenant storage fields.
{
"job": {
"id": "job_01HY2MQR",
"type": "EMAIL",
"status": "QUEUED",
"sourceTenantId": "ten_01HXKP3B",
"destTenantId": "ten_02HXZ9QW",
"scope": { "email": true, "calendar": true, "contacts": true },
"totalItems": 0,
"doneItems": 0,
"errorItems": 0,
"skippedItems": 0,
"dryRun": false,
"createdAt": "2026-05-09T08:00:00Z",
"startedAt": null,
"completedAt": null
}
}curl -X POST https://api.themigrator.app/v1/jobs \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceTenantId": "ten_01HXKP3B",
"destTenantId": "ten_02HXZ9QW",
"type": "EMAIL",
"scope": { "email": true, "calendar": true, "contacts": true }
}'Creates multiple migration jobs in a single request — one per batch item. Each batch item can target a different set of mailboxes, sites, or teams and can start at a different scheduled time. Useful for phased rollouts where different groups of users migrate at different times. The jobs are created in parallel and all share the same source tenant, destination tenant, type, and scope. Returns all job IDs in order.
The batches array must have at least one item. Jobs are created in declaration order — the first element of the response jobIds array corresponds to the first element of the request batches array.
{
"jobIds": [
"job_01HY2MQR",
"job_01HY2MQS",
"job_01HY2MQT"
]
}curl -X POST https://api.themigrator.app/v1/jobs/batch \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceTenantId": "ten_01HXKP3B",
"destTenantId": "ten_02HXZ9QW",
"type": "EMAIL",
"scope": { "email": true, "calendar": true, "contacts": true },
"batches": [
{
"name": "Wave 1 — Exec team",
"scheduledAt": "2026-06-01T22:00:00Z",
"options": {
"mailboxes": ["[email protected]", "[email protected]"],
"mailboxMappings": [
{ "source": "[email protected]", "dest": "[email protected]" },
{ "source": "[email protected]", "dest": "[email protected]" }
]
}
},
{
"name": "Wave 2 — Engineering",
"scheduledAt": "2026-06-02T22:00:00Z",
"options": {
"mailboxes": ["[email protected]", "[email protected]"],
"mailboxMappings": [
{ "source": "[email protected]", "dest": "[email protected]" },
{ "source": "[email protected]", "dest": "[email protected]" }
]
}
}
]
}'Returns a paginated list of migration jobs for the current organisation, ordered by creation date descending.
{
"jobs": [
{
"id": "job_01HY2MQR",
"type": "EMAIL",
"status": "RUNNING",
"sourceTenantId": "ten_01HXKP3B",
"destTenantId": "ten_02HXZ9QW",
"totalItems": 48210,
"doneItems": 31405,
"errorItems": 12,
"skippedItems": 3,
"bytesTransferred": 5368709120,
"createdAt": "2026-05-09T08:00:00Z",
"startedAt": "2026-05-09T08:01:12Z",
"completedAt": null
}
],
"nextCursor": "cur_KxP2Rv9",
"hasMore": true
}curl "https://api.themigrator.app/v1/jobs?status=RUNNING&limit=10" \ -H "Authorization: Bearer $API_KEY"
Returns the full detail for a single job, including live counters and configuration.
{
"job": {
"id": "job_01HY2MQR",
"type": "EMAIL",
"status": "RUNNING",
"sourceTenantId": "ten_01HXKP3B",
"destTenantId": "ten_02HXZ9QW",
"scope": { "email": true, "calendar": true, "contacts": true },
"totalItems": 48210,
"doneItems": 31405,
"errorItems": 12,
"skippedItems": 3,
"bytesTransferred": 5368709120,
"dryRun": false,
"createdAt": "2026-05-09T08:00:00Z",
"startedAt": "2026-05-09T08:01:12Z",
"completedAt": null
}
}curl https://api.themigrator.app/v1/jobs/job_01HY2MQR \ -H "Authorization: Bearer $API_KEY"
Signals the worker to pause after completing its current item batch. The job transitions to PAUSED status. In-flight items are completed; no new items are picked up.
{ "status": "PAUSED" }curl -X PATCH https://api.themigrator.app/v1/jobs/job_01HY2MQR/pause \ -H "Authorization: Bearer $API_KEY"
Re-queues a paused job. The worker picks it up and continues from where it left off — already-migrated items are skipped via delta tracking.
{ "status": "QUEUED" }curl -X PATCH https://api.themigrator.app/v1/jobs/job_01HY2MQR/resume \ -H "Authorization: Bearer $API_KEY"
Cancels and removes a job. Running jobs are stopped after the current batch. Data already migrated is not reversed.
{ "deleted": true }curl -X DELETE https://api.themigrator.app/v1/jobs/job_01HY2MQR \ -H "Authorization: Bearer $API_KEY"
Opens a Server-Sent Events stream that emits log lines in real time as the worker processes items. The connection stays open until the job completes, at which point a done event is emitted and the stream closes.
Set the Accept: text/event-stream header and use an SSE-compatible client. The stream emits log and done event types.
event: log
data: {"id":"log_01HY3A","level":"OK","message":"[email protected] → 4,210 items migrated","ts":"2026-05-09T08:05:00Z"}
event: log
data: {"id":"log_01HY3B","level":"WARN","message":"Throttled (429) — retrying in 8s","ts":"2026-05-09T08:05:01Z"}
event: log
data: {"id":"log_01HY3C","level":"ERROR","message":"[email protected] — 403 Forbidden on Mail.ReadWrite","ts":"2026-05-09T08:07:14Z"}
event: done
data: {"status":"DONE","completedAt":"2026-05-09T10:22:00Z"}curl -N https://api.themigrator.app/v1/jobs/job_01HY2MQR/logs \ -H "Authorization: Bearer $API_KEY" \ -H "Accept: text/event-stream"
Downloads the complete log history for a job as a CSV file. Returns a binary response with Content-Disposition: attachment; filename="job-logs.csv".
id,level,message,ts log_01HY3A,OK,[email protected] → 4210 items migrated,2026-05-09T08:05:00Z log_01HY3B,WARN,Throttled (429) — retrying in 8s,2026-05-09T08:05:01Z log_01HY3C,ERROR,[email protected] — 403 Forbidden on Mail.ReadWrite,2026-05-09T08:07:14Z
curl -o job-logs.csv \ https://api.themigrator.app/v1/jobs/job_01HY2MQR/logs/export \ -H "Authorization: Bearer $API_KEY"
Returns paginated per-mailbox migration progress for an EMAIL job. Each entry shows the source → destination mapping and current item counts.
{
"mailboxes": [
{
"id": "mbp_01HYA3X",
"email": "[email protected]",
"destEmail": "[email protected]",
"status": "DONE",
"totalItems": 4210,
"doneItems": 4210,
"errorItems": 0,
"sizeBytes": 1073741824,
"startedAt": "2026-05-09T08:02:00Z",
"completedAt": "2026-05-09T08:09:44Z"
},
{
"id": "mbp_01HYA3Y",
"email": "[email protected]",
"destEmail": "[email protected]",
"status": "ERROR",
"totalItems": 8920,
"doneItems": 0,
"errorItems": 1,
"sizeBytes": 2147483648,
"startedAt": "2026-05-09T08:07:00Z",
"completedAt": null
}
],
"nextCursor": null,
"hasMore": false
}curl "https://api.themigrator.app/v1/jobs/job_01HY2MQR/mailboxes?status=DONE&limit=50" \ -H "Authorization: Bearer $API_KEY"
Devices
The Devices API lets you manage Windows endpoints running the MigratorAgent service. Agents register themselves, check in for commands, and report results. You can list connected devices and send migration commands from the dashboard or directly via API.
Called automatically by the MigratorAgent installer. Registers a new Windows device with the organisation and returns a device ID and secret that the agent stores in the Windows registry for future check-ins. You do not normally call this endpoint directly.
{
"deviceId": "dev_01HXKP9A",
"secret": "a3f8c2d1e7b6..."
}curl -X POST https://api.themigrator.app/v1/devices/register \
-H "Content-Type: application/json" \
-d '{
"orgId": "org_01HXKP3A",
"hostname": "DESKTOP-ABC123",
"ipAddress": "192.168.1.42",
"domain": "contoso.local"
}'Called by the MigratorAgent every 3 minutes. Updates the device's last-seen timestamp and returns any pending commands queued for this device. Authentication uses the device secret returned at registration.
{
"commands": [
{
"id": "cmd_01HY4PQR",
"type": "FULL_MIGRATION",
"payload": {
"ppkgUrl": "https://storage.azure.com/migration-staging/enroll.ppkg",
"destTenantId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
}
]
}curl -X POST https://api.themigrator.app/v1/devices/checkin \
-H "Content-Type: application/json" \
-d '{
"deviceId": "dev_01HXKP9A",
"secret": "a3f8c2d1e7b6..."
}'Called by the agent after executing a command (or when a command fails). Updates the command status to DONE, RUNNING (Phase 1 complete, awaiting reboot), or ERROR, and records the result message.
{ "ok": true }curl -X POST https://api.themigrator.app/v1/devices/result \
-H "Content-Type: application/json" \
-d '{
"deviceId": "dev_01HXKP9A",
"secret": "a3f8c2d1e7b6...",
"commandId": "cmd_01HY4PQR",
"status": "DONE",
"result": "Phase 2: Entra join and Intune enrollment completed via provisioning package"
}'Returns all devices registered to the organisation, with their current status and most recent check-in time. Status is computed from lastSeenAt: ONLINE if seen within the last 10 minutes, MIGRATING if a command is in progress, otherwise OFFLINE.
{
"devices": [
{
"id": "dev_01HXKP9A",
"hostname": "DESKTOP-ABC123",
"ipAddress": "192.168.1.42",
"domain": "contoso.local",
"status": "ONLINE",
"lastSeenAt": "2026-05-13T10:55:00Z",
"agentVersion": "0.6.35",
"createdAt": "2026-05-13T09:00:00Z"
}
]
}curl https://api.themigrator.app/v1/devices \ -H "Authorization: Bearer $API_KEY"
Removes a device registration. The agent on the device will continue running but its check-ins will be rejected with 404 until it is re-registered or uninstalled.
{ "deleted": true }curl -X DELETE https://api.themigrator.app/v1/devices/dev_01HXKP9A \ -H "Authorization: Bearer $API_KEY"
Queues a command to be picked up by the device on its next check-in (within 3 minutes). The agent executes commands sequentially — if a command is already running, the new command waits until the current one completes.
{
"command": {
"id": "cmd_01HY4PQR",
"deviceId": "dev_01HXKP9A",
"type": "FULL_MIGRATION",
"status": "PENDING",
"createdAt": "2026-05-13T11:00:00Z"
}
}curl -X POST https://api.themigrator.app/v1/devices/dev_01HXKP9A/commands \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "FULL_MIGRATION",
"payload": {
"ppkgUrl": "https://storage.azure.com/migration-staging/enroll.ppkg",
"destTenantId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
}
}'Returns the command history for a device, ordered by creation date descending.
{
"commands": [
{
"id": "cmd_01HY4PQR",
"type": "FULL_MIGRATION",
"status": "DONE",
"result": "Phase 2: Entra join and Intune enrollment completed via provisioning package",
"createdAt": "2026-05-13T11:00:00Z",
"updatedAt": "2026-05-13T11:08:42Z"
}
]
}curl "https://api.themigrator.app/v1/devices/dev_01HXKP9A/commands?status=DONE" \ -H "Authorization: Bearer $API_KEY"
Cancels a PENDING command before the agent picks it up. Commands that are already RUNNING cannot be cancelled — the agent will complete execution and report the result.
{ "status": "CANCELLED" }curl -X PATCH https://api.themigrator.app/v1/devices/dev_01HXKP9A/commands/cmd_01HY4PQR/cancel \ -H "Authorization: Bearer $API_KEY"