
Poll Origin mirror transition jobs via the Migration API
Follow a mirror transition with GET https://api.cursor.com/v1/origin/repos/{ownerSlug}/{repoName}/mirror/transition-jobs:active and GET https://api.cursor.com/v1/origin/repos/{ownerSlug}/{repoName}/mirror/transition-jobs/{jobId}. Official reference: Origin Migration API → Get Active Mirror Transition Job / Get Mirror Transition Job.
Origin is in Early Beta and subject to change. Call these endpoints from a migration script you run as a Cursor user, not from an Origin App. Sign in with origin auth login, or pass a Cursor API key through origin api. Availability: Early Beta per the API overview.
Required scope: repository:metadata:read (user policy). An Origin App cannot call these endpoints.
After you start a transition or force cutover, poll until the job reaches a terminal status. Prefer the active endpoint for a live follow: once activeJob disappears, read lastJob for how it ended.
Get active (and last) job
curl --request GET \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/mirror/transition-jobs:active' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN'
| Field | Meaning |
|---|---|
activeJob |
Currently active transition job (same shape as Get Mirror Transition Job). Absent when nothing is in progress. |
lastJob |
Most recent job that reached a terminal status. Absent when the repository has never completed a transition. |
A repository that has never transitioned returns an empty object.
Example:
{
"activeJob": {
"id": "rmt_01k2ja2000e0080000000000m4",
"transition": "outbound_to_inbound",
"status": "running",
"phase": "draining-writes",
"attemptCount": 1,
"drainUntil": "2026-08-02T15:05:00Z",
"startedAt": "2026-08-02T15:00:00Z",
"createdAt": "2026-08-02T14:59:30Z",
"updatedAt": "2026-08-02T15:01:00Z"
},
"lastJob": {
"id": "rmt_01k2ja2000e0080000000000m3",
"transition": "inbound_to_outbound",
"status": "succeeded",
"phase": "completed",
"attemptCount": 1,
"startedAt": "2026-08-01T10:00:00Z",
"completedAt": "2026-08-01T10:12:00Z",
"createdAt": "2026-08-01T09:59:30Z",
"updatedAt": "2026-08-01T10:12:00Z"
}
}
Get one job by id
curl --request GET \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/mirror/transition-jobs/JOB_ID' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN'
An unknown jobId returns HTTP 404.
Job fields
| Field | Meaning |
|---|---|
id |
Job identifier (for example rmt_…). |
transition |
initial_to_inbound, inbound_to_outbound, or outbound_to_inbound. |
status |
Lifecycle: queued, running, succeeded, failed_rolled_back, requires_attention, superseded. Terminal: succeeded, failed_rolled_back, superseded. requires_attention needs operator intervention or a forced cutover. |
phase |
Progress detail for display/debugging (for example draining-writes, snapshotting-refs, completed). New phases can appear — poll status for completion, not phase equality. |
attemptCount |
Times this job has been attempted. |
drainUntil |
RFC 3339 end of the write-drain window; absent outside the draining phase. |
lastErrorCode / lastErrorMessage |
Stable failure code (for example InboundMirrorDrainTimeout, MirrorIntegrityMismatch) and human detail; absent while the job has not failed. |
startedAt / completedAt / createdAt / updatedAt |
RFC 3339 timestamps; startedAt absent while queued; completedAt absent until terminal. |
Succeeded example:
{
"id": "rmt_01k2ja2000e0080000000000m3",
"transition": "inbound_to_outbound",
"status": "succeeded",
"phase": "completed",
"attemptCount": 1,
"startedAt": "2026-08-02T15:00:00Z",
"completedAt": "2026-08-02T15:12:00Z",
"createdAt": "2026-08-02T14:59:30Z",
"updatedAt": "2026-08-02T15:12:00Z"
}
Pair these reads with Transition Repo Mirror and Force Repo Mirror Cutover in the same migration script.