API / handle-origin-repository-webhooks

API

Handle Origin repository webhooks

Subscribe to repository.created, repository.deleted, repository.pushed, and repository.metadata.updated. Official reference: llms-full.txt → Events. OpenAPI: RepositoryCreatedWebhookPayload, RepositoryDeletedWebhookPayload, RepositoryPushWebhookPayload, RepositoryMetadataUpdatedWebhookPayload.

Origin is in Early Beta and subject to change. Subscribe when you configure the app's webhook events list. Subscribing needs repository:metadata:read for created / deleted / metadata.updated (and the push event per the Events table). Delivery uses the same signed envelope as other Origin webhooks.

Events

event.type When it fires
repository.created A repository is created.
repository.deleted A repository is deleted (product delete, or stopping sync on an inbound mirror).
repository.pushed One or more refs change in a push on a native Origin repo or an outbound mirror.
repository.metadata.updated A repository's default branch changes.

Origin does not deliver repository.pushed for repositories it mirrors in from GitHub (GitHub owns those pushes). repository.deleted is delivered for a GitHub-mirrored repo when Cursor-side sync stops.

Payload fields

repository.created

Field Meaning
repository Full created Repo snapshot (id, name, fullName, owner, defaultBranch, cloneUrl, timestamps)

repository.deleted

Field Meaning
repository Reference only (id, name, owner) — the repo no longer resolves through the API
deletedAt When the repository was deleted

repository.pushed

Field Meaning
repository Repository reference
refUpdates Refs in this push (capped at 100), each with ref, before, after, created / deleted / forced, optional headCommit
refUpdatesCount Total ref updates in the atomic push (may exceed refUpdates.length when capped)
pushedAt When Origin observed the push
pusher Principal that pushed; absent when Origin itself pushed (for example a merge advancing the base ref)

repository.metadata.updated

Field Meaning
repository Full post-write Repo snapshot (no delta, no updating actor)

Sample repository.deleted event.payload:

{
  "repository": {
    "id": "repo_01k2ja2000e0080000000000q4",
    "name": "rocket",
    "owner": {
      "slug": "acme",
      "id": "ns_01k2ja2000e0080000000000p3",
      "type": "team"
    }
  },
  "deletedAt": "2026-08-03T08:15:00Z"
}

Sample repository.pushed event.payload:

{
  "repository": {
    "id": "repo_01k2ja2000e0080000000000q4",
    "name": "rocket",
    "owner": {
      "slug": "acme",
      "id": "ns_01k2ja2000e0080000000000p3",
      "type": "team"
    }
  },
  "refUpdates": [
    {
      "ref": "refs/heads/add-telemetry",
      "before": "5c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d",
      "after": "9a41f0c3d2b8e7f6a5c4d3e2f1b0a9c8d7e6f5a4",
      "created": false,
      "deleted": false,
      "forced": false,
      "headCommit": {
        "sha": "9a41f0c3d2b8e7f6a5c4d3e2f1b0a9c8d7e6f5a4",
        "message": "Add launch telemetry"
      }
    }
  ],
  "pushedAt": "2026-08-02T14:45:00Z",
  "pusher": {
    "user": {
      "id": "user_01k2ja2000e0080000000000c3",
      "email": "jane@acme.dev"
    }
  },
  "refUpdatesCount": 1
}

Receiver tips

  1. Branch on event.type. On deleted, drop local caches keyed by repository.id — follow-up Get Repo calls will 404.
  2. On metadata.updated, compare successive snapshots (or refetch Get Repo) to see what moved; the payload has no delta.
  3. On pushed, there is no commits array — use each refUpdates[].headCommit tip metadata, then fetch commits/contents as needed.
  4. Keep the receiver answering within the 10-second delivery deadline.

Pitfalls

  • Do not expect repository.pushed on inbound GitHub mirrors; subscribe on GitHub for those pushes.
  • A merge that advances the base ref still delivers repository.pushed with no pusher.
  • Pull-request lifecycle events (pull_request.created, head_ref.pushed, …) are a separate family from these repository events.