Skip to main content

Command Palette

Search for a command to run...

API

API de migración de Origin

La API de migración de Origin está pensada para operadores que migran repositorios entre GitHub y réplicas de Origin. Llama a estos endpoints desde un script de migración que ejecutes como usuario de Cherri Code, no desde una Origin App.

Inicia sesión con origin auth login o pasa una clave de API de Cherri Code mediante origin api. Consulta Solicitudes de CLI autenticadas por usuario.

Los endpoints usan la URL base de la API de Origin, https://api.cursor.com/v1/origin, y el mismo modelo de errores.

Scopes

repository:mirror:write, repository:mirror:delete y repository:metadata:read son scopes de policy de usuario. Transition Repo Mirror y Force Repo Mirror Cutover requieren Write (repository:mirror:write). Desvincular réplica de repositorio requiere Admin (repository:mirror:delete). Obtener job de transición de réplica y Obtener el job de transición de réplica activo requieren repository:metadata:read. Además, debes ser administrador del repositorio en su origen de GitHub.

Estos scopes no se pueden solicitar durante la instalación de una Origin App. Una Origin App no puede llamar a estos endpoints.

Referencia de endpoints

Transition Repo Mirror

POST/v1/origin/repos/{ownerSlug}/{repoName}/mirror:transition
Scoperepository:mirror:writeAuthUser access token

Inicia una transición de mirror state en un repositorio replicado y devuelve el job que le hace un seguimiento. El repositorio pasa a un mirror status de transición mientras el job se ejecuta, por lo que debes consultar periódicamente Get Active Mirror Transition Job o Get Mirror Transition Job hasta que el job alcance un status terminal.

Si un repositorio no se encuentra en el estado inicial esperado por la transición, o ya tiene un job de transición activo, se devuelve FailedPrecondition (HTTP 400). El caller debe administrar el repositorio en el origen del mirror; si no tiene ese acceso, se devuelve 403.

Path Parameters

ownerSlug string Obligatorio

Unique slug de la owning entity.

repoName string Obligatorio

Repo name, único dentro de la owner entity.

Request Body

transition string Obligatorio

El cambio de mirror state que se va a iniciar. Valores permitidos: initial_to_inbound, inbound_to_outbound, outbound_to_inbound.

Response Fields

repository object

El repositorio, con su mirror state en transición. Incluye los mismos campos que Get Repo.

job object

El job que hace un seguimiento de la transición, con los mismos campos que Get Mirror Transition Job. Consúltalo periódicamente hasta que alcance un status terminal.
curl --request POST \  --url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/mirror:transition' \  --header 'Authorization: Bearer YOUR_ORIGIN_TOKEN' \  --header 'Content-Type: application/json' \  --data '{  "transition": "inbound_to_outbound"}'

Estructura de la respuesta:

{  "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": "inbound"    }  },  "job": {    "id": "rmt_01k2ja2000e0080000000000m3",    "transition": "inbound_to_outbound",    "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"  }}

Forzar el cambio de mirror del repositorio

POST/v1/origin/repos/{ownerSlug}/{repoName}/mirror:forceCutover
Scoperepository:mirror:writeAuthUser access token

Fuerza un cambio outbound_to_inbound sin enviar de vuelta al origen el estado divergente de este host. El origen se adopta como fuente de verdad tal como está, y las referencias que solo existen en este host se guardan como instantánea y se descartan. Devuelve el job que hace un seguimiento del cambio forzado.

Solo se acepta para un repositorio en estado outbound, o para uno bloqueado en una transición de outbound a inbound cuyo job activo informa de requires_attention, en cuyo caso ese job queda sustituido. Cualquier otro estado, incluido un job de transición en cola o en ejecución, devuelve FailedPrecondition (HTTP 400). El caller debe tener permisos de administración sobre el repositorio en el origen del mirror; si no cuenta con ese acceso, recibirá un 403.

Parámetros de ruta

ownerSlug string Obligatorio

Slug único de la entidad propietaria.

repoName string Obligatorio

Nombre del repositorio, único dentro de la entidad propietaria.

Cuerpo de la solicitud

La solicitud no admite campos. Envía un objeto JSON vacío.

Campos de la respuesta

repository object

El repositorio, con su estado de mirror en transición. Incluye los mismos campos que Get Repo.

job object

El job que hace un seguimiento de la transición, con los mismos campos que Get Mirror Transition Job. Consúltalo periódicamente hasta que alcance un estado terminal.
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 '{}'

Estructura de la respuesta:

{  "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"  }}

Desvincular réplica de repositorio

DELETE/v1/origin/repos/{ownerSlug}/{repoName}/mirror
Scoperepository:mirror:deleteAuthUser access token

Desconecta de forma permanente un repositorio replicado de su origen. El repositorio conserva su contenido actual y pasa a ser un repositorio nativo, la sincronización se detiene en ambas direcciones y se elimina la credencial de implementación de la réplica. El cuerpo de la respuesta está vacío.

La desvinculación no se puede revertir mediante esta API. Un repositorio que nunca tuvo una réplica devuelve FailedPrecondition (HTTP 400); desvincular un repositorio ya desvinculado se completa correctamente, pero no tiene ningún efecto.

Parámetros de ruta

ownerSlug string Obligatorio

Slug único de la entidad propietaria.

repoName string Obligatorio

Nombre del repositorio, único dentro de la entidad propietaria.

Campos de la respuesta

Las solicitudes correctas no devuelven cuerpo de respuesta.

curl --request DELETE \  --url 'https://api.cursor.com/v1/origin/repos/OWNER_SLUG/REPO_NAME/mirror' \  --header 'Authorization: Bearer YOUR_ORIGIN_TOKEN'

Respuesta:

204 No Content

Obtener job de transición de réplica

GET/v1/origin/repos/{ownerSlug}/{repoName}/mirror/transition-jobs/{jobId}
Scoperepository:metadata:readAuthUser access token

Devuelve un job de transición de réplica por id. Un id de job desconocido devuelve 404.

Parámetros de ruta

ownerSlug string Obligatorio

Slug único de la entidad propietaria.

repoName string Obligatorio

Nombre del repo, único dentro de la entidad propietaria.

jobId string Obligatorio

Identificador del trabajo de transición, tal como se devuelve en job.id.

Campos de la respuesta

id string

Identificador único del job.

transition string

El cambio de dirección de replicación que realiza este job. Valores permitidos: initial_to_inbound, inbound_to_outbound, outbound_to_inbound.

status string

Estado del ciclo de vida. Valores permitidos: queued, running, succeeded, failed_rolled_back, requires_attention, superseded. succeeded, failed_rolled_back y superseded son estados terminales. requires_attention requiere la intervención de un operador o una conmutación forzada.

phase string

Detalle del progreso dentro de status, para visualización y depuración. Uno de queued, starting, draining-writes, initializing-mirror-fetch, finalizing-mirror-fetch, finalizing-mirror-push, snapshotting-refs, verifying-integrity, reopening-inbound-mirror, committing-target-status, rolling-back o completed. Pueden aparecer nuevas fases a medida que evoluciona el proceso de transición, así que consulta status periódicamente para detectar la finalización en lugar de basarte en las fases.

attemptCount entero

Número de veces que se ha intentado este job.

drainUntil string

Timestamp RFC 3339 del momento en que termina la ventana de drenaje de escrituras de una transición en curso. Ausente fuera de la fase de drenaje.

lastErrorCode string

Código estable que identifica por qué falló el job la última vez, como InboundMirrorDrainTimeout o MirrorIntegrityMismatch. No se incluye mientras el job no haya fallado.

lastErrorMessage string

Detalle legible para personas de lastErrorCode. Ausente mientras el trabajo no haya fallado.

startedAt string

Timestamp RFC 3339 del momento en que el job comenzó a ejecutarse. Absent mientras está queued.

completedAt string

Timestamp RFC 3339 del momento en que el job alcanzó un status terminal. Ausente hasta entonces.

createdAt string

Timestamp RFC 3339 de creación del job.

updatedAt string

Timestamp RFC 3339 de la actualización del job.
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'

Estructura de la respuesta:

{  "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"}

Obtener el job de transición de réplica activo

GET/v1/origin/repos/{ownerSlug}/{repoName}/mirror/transition-jobs:active
Scoperepository:metadata:readAuthUser access token

Devuelve el job de transición de réplica activo del repositorio y el último que alcanzó un estado terminal. Ambos campos son opcionales, así que un repositorio que nunca ha hecho una transición devuelve un objeto vacío. Consulta este endpoint periódicamente para seguir una transición: cuando activeJob desaparece, lastJob te indica cómo terminó.

Parámetros de ruta

ownerSlug string Obligatorio

Slug único de la entidad propietaria.

repoName string Obligatorio

Nombre del repositorio, único dentro de la entidad propietaria.

Campos de la respuesta

activeJob object

El job de transición activo en este momento, con los mismos campos que Obtener job de transición de réplica. Ausente cuando no hay ninguna transición en curso.

lastJob object

El job más reciente que alcanzó un estado terminal, con los mismos campos que Obtener job de transición de réplica. Ausente cuando el repositorio nunca ha completado una transición.
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'

Estructura de la respuesta:

{  "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"  }}