API / force-origin-repo-mirror-cutover-via-api

API

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.