
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
- Verify the Standard Webhooks signature against
https://api.cursor.com/v1/origin/keys, then branch onevent.type. - Treat
stateplusmerged/drafttogether: a merged PR isstate: "closed"withmerged: true. - On
head_ref.pushed/base_ref.updated, read the new tip frompullRequest.head/pullRequest.baseand theversionblock; refetch Get Pull Request when you need labels or mergeability. - Keep the receiver answering within the 10-second delivery deadline; queue heavy work after
2xx.
Pitfalls
- Do not look for an
actionfield on the payload — route withevent.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}/mergewith 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.