API de migración de Origin
Origin está en fase beta inicial y puede cambiar. Revisa la especificación de OpenAPI al actualizar una integración.
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
/v1/origin/repos/{ownerSlug}/{repoName}/mirror:transitionInicia 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
repoName string Obligatorio
Request Body
transition string Obligatorio
initial_to_inbound, inbound_to_outbound, outbound_to_inbound.Response Fields
repository object
job object
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
/v1/origin/repos/{ownerSlug}/{repoName}/mirror:forceCutoverFuerza 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
repoName string Obligatorio
Cuerpo de la solicitud
La solicitud no admite campos. Envía un objeto JSON vacío.
Campos de la respuesta
repository object
job object
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
/v1/origin/repos/{ownerSlug}/{repoName}/mirrorDesconecta 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
repoName string Obligatorio
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 ContentObtener job de transición de réplica
/v1/origin/repos/{ownerSlug}/{repoName}/mirror/transition-jobs/{jobId}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
repoName string Obligatorio
jobId string Obligatorio
job.id.Campos de la respuesta
id string
transition string
initial_to_inbound, inbound_to_outbound, outbound_to_inbound.status string
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
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
drainUntil string
lastErrorCode string
InboundMirrorDrainTimeout o MirrorIntegrityMismatch. No se incluye mientras el job no haya fallado.lastErrorMessage string
lastErrorCode. Ausente mientras el trabajo no haya fallado.startedAt string
completedAt string
createdAt string
updatedAt string
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
/v1/origin/repos/{ownerSlug}/{repoName}/mirror/transition-jobs:activeDevuelve 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
repoName string Obligatorio
Campos de la respuesta
activeJob object
lastJob object
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" }}