API / handle-origin-pull-request-webhooks

API

Handle Origin pull request lifecycle webhooks

Subscribe to the eight pull_request.* lifecycle events that share OpenAPI PullRequestWebhookPayload. Official reference: llms-full.txt → Events and Pull Request Events. The lifecycle action is the envelope's event.type; there is no separate action field.

Origin is in Early Beta and subject to change. Declare the event slugs on the app's webhook events list. Subscribing needs repository:pull_requests:read. Delivery uses the same signed envelope as other Origin webhooks (10-second answer deadline).

Events

event.type When it fires
pull_request.created A pull request opens.
pull_request.published A draft becomes open.
pull_request.reopened A closed pull request reopens.
pull_request.closed A pull request closes without merging, including when Origin closes it because a push left its head with no history in common with its base.
pull_request.merged A pull request merges.
pull_request.metadata.updated The title or description changes.
pull_request.head_ref.pushed The pull request head advances.
pull_request.base_ref.updated The base ref or resolved base commit changes.

Label, comment, review, and reviewer events are separate families with their own payloads.

Payload fields

Field Meaning
pullRequest Full PR snapshot for this delivery (id, number, state, draft, merged, title, body, head / base, author, timestamps, line stats, optional stack, version)
repository Repository reference (id, name, owner)

Assigned labels are omitted from the webhook snapshot — call Get Pull Request (or List Pull Request Labels) when you need them. Sep 22, 2026 changelog: every pull_request.* payload can carry stack (id plus optional parentPullRequest) reflecting topology at event time.

Sample event.payload (pull_request.created shape):

{
  "pullRequest": {
    "id": "pr_01k2ja2000e0080000000000d4",
    "number": "17",
    "state": "open",
    "draft": false,
    "merged": false,
    "title": "Add launch telemetry",
    "body": "Adds structured launch telemetry to the ignition path.",
    "head": {
      "ref": "add-telemetry",
      "sha": "9a41f0c3d2b8e7f6a5c4d3e2f1b0a9c8d7e6f5a4"
    },
    "base": {
      "ref": "main",
      "sha": "3b1f9c2d8a7e6f5049c8b7a6d5e4f3a2b1c0d9e8"
    },
    "author": {
      "user": {
        "id": "user_01k2ja2000e0080000000000c3",
        "email": "jane@acme.dev"
      }
    },
    "createdAt": "2026-08-01T09:30:00Z",
    "updatedAt": "2026-08-02T14:45:00Z",
    "additions": 128,
    "deletions": 46,
    "changedFiles": 5,
    "stack": {
      "id": "stk_01k2ja2000e0080000000000s1",
      "parentPullRequest": {
        "id": "pr_01k2ja2000e0080000000000d3",
        "number": "16",
        "repository": {
          "id": "repo_01k2ja2000e0080000000000q4",
          "name": "rocket",
          "owner": {
            "slug": "acme",
            "id": "ns_01k2ja2000e0080000000000p3",
            "type": "team"
          }
        }
      }
    },
    "version": {
      "number": "3",
      "headSha": "9a41f0c3d2b8e7f6a5c4d3e2f1b0a9c8d7e6f5a4",
      "baseSha": "3b1f9c2d8a7e6f5049c8b7a6d5e4f3a2b1c0d9e8",
      "createdAt": "2026-08-01T09:30:00Z"
    }
  },
  "repository": {
    "id": "repo_01k2ja2000e0080000000000q4",
    "name": "rocket",
    "owner": {
      "slug": "acme",
      "id": "ns_01k2ja2000e0080000000000p3",
      "type": "team"
    }
  }
}

Receiver tips

  1. Verify the Standard Webhooks signature against https://api.cursor.com/v1/origin/keys, then branch on event.type.
  2. Treat state plus merged / draft together: a merged PR is state: "closed" with merged: true.
  3. On head_ref.pushed / base_ref.updated, read the new tip from pullRequest.head / pullRequest.base and the version block; refetch Get Pull Request when you need labels or mergeability.
  4. Keep the receiver answering within the 10-second delivery deadline; queue heavy work after 2xx.

Pitfalls

  • Do not look for an action field on the payload — route with event.type.
  • Do not expect assigned labels on this family; they were removed from lifecycle payloads (Aug 21, 2026 changelog).
  • Pull request webhook payloads do not carry the merge preview commit — read pull/{pullNumber}/merge with Get Git Ref after the event if you need it.
  • A disjoint head/base push can close the PR and deliver pull_request.closed; a later related push does not reopen it.