
Force an Origin repo mirror cutover via the Migration API
Force an outbound_to_inbound cutover without pushing this host's divergent state back to the upstream source with POST https://api.cursor.com/v1/origin/repos/{ownerSlug}/{repoName}/mirror:forceCutover. Official reference: Origin Migration API → Force Repo Mirror Cutover.
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:mirror:write (user policy). You must also administer the repository on its upstream GitHub source. An Origin App cannot call this endpoint.
The source is adopted as the source of truth as it stands. Refs that exist only on this host are snapshotted and abandoned. The response returns the job tracking the forced cutover — poll it until terminal.
When this is accepted
| Repo state | Accepted? |
|---|---|
Mirror status outbound |
Yes |
Stuck in an outbound_to_inbound transition whose active job reports requires_attention |
Yes (that job is superseded) |
| Any other state, including a queued or running transition job | No — FailedPrecondition (HTTP 400) |
Path parameters
| Param | Required | Meaning |
|---|---|---|
ownerSlug |
yes | Owning entity's unique slug. |
repoName |
yes | Repo name, unique to the owner entity. |
Request body
Send an empty JSON object. The request takes no fields.
curl --request POST \
--url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/mirror:forceCutover' \
--header 'Authorization: Bearer YOUR_ORIGIN_TOKEN' \
--header 'Content-Type: application/json' \
--data '{}'
Response
| Field | Meaning |
|---|---|
repository |
The repository reflecting its transitioning mirror state (same fields as Get Repo). |
job |
The job tracking the forced cutover (same fields as Get Mirror Transition Job). |
Example:
{
"repository": {
"id": "repo_01k2ja2000e0080000000000q4",
"name": "rocket",
"fullName": "acme/rocket",
"owner": {
"slug": "acme",
"id": "ns_01k2ja2000e0080000000000p3",
"type": "team"
},
"defaultBranch": "main",
"createdAt": "2026-08-01T09:30:00Z",
"updatedAt": "2026-08-02T15:00:00Z",
"pushedAt": "2026-08-02T14:45:00Z",
"cloneUrl": "https://origin.cursor.com/git/acme/rocket.git",
"mirror": {
"source": "github",
"sourceId": "R_kgDOAbc123",
"status": "outbound"
}
},
"job": {
"id": "rmt_01k2ja2000e0080000000000m4",
"transition": "outbound_to_inbound",
"status": "running",
"phase": "snapshotting-refs",
"attemptCount": 1,
"startedAt": "2026-08-02T15:00:00Z",
"createdAt": "2026-08-02T14:59:30Z",
"updatedAt": "2026-08-02T15:01:00Z"
}
}
Errors
| Condition | Result |
|---|---|
| Wrong mirror state / active non-attention job | FailedPrecondition (HTTP 400) |
| Caller does not administer the upstream GitHub source | HTTP 403 |
Use a normal Transition Repo Mirror when you want an orderly outbound_to_inbound that still pushes divergent state back. Reach for force cutover when you need to abandon host-only refs and adopt the upstream source as-is.