From 62ece167d16ab7249c9b2da4da8a67c34ce741f0 Mon Sep 17 00:00:00 2001
From: Nathan Gendron <nato@coderabbit.ai>
Date: Fri, 20 Sep 2024 13:42:02 -0400
Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20server=20webhooks?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/server/index.ts                           |   3 +-
 src/server/webhooks/events/event.ts           |   9 ++
 src/server/webhooks/events/index.ts           |   4 +
 .../webhooks/events/pr/comment_added.ts       |  91 ++++++++++++++++
 .../webhooks/events/pr/comment_deleted.ts     |  87 +++++++++++++++
 .../webhooks/events/pr/comment_edited.ts      |  93 ++++++++++++++++
 src/server/webhooks/events/pr/declined.ts     |  73 +++++++++++++
 src/server/webhooks/events/pr/deleted.ts      |  72 +++++++++++++
 src/server/webhooks/events/pr/event.ts        |  44 ++++++++
 .../webhooks/events/pr/from_ref_updated.ts    |  95 +++++++++++++++++
 src/server/webhooks/events/pr/index.ts        |  13 +++
 src/server/webhooks/events/pr/merged.ts       |  83 +++++++++++++++
 src/server/webhooks/events/pr/modified.ts     |  86 +++++++++++++++
 src/server/webhooks/events/pr/opened.ts       |  75 +++++++++++++
 .../webhooks/events/pr/reviewer_approved.ts   |  83 +++++++++++++++
 .../events/pr/reviewer_changes_requested.ts   |  78 ++++++++++++++
 .../webhooks/events/pr/reviewer_unapproved.ts |  78 ++++++++++++++
 .../webhooks/events/pr/reviewer_updated.ts    |  75 +++++++++++++
 src/server/webhooks/events/project/event.ts   |   5 +
 src/server/webhooks/events/project/index.ts   |   2 +
 .../webhooks/events/project/modified.ts       |  30 ++++++
 .../webhooks/events/repo/comment_added.ts     |  66 ++++++++++++
 .../webhooks/events/repo/comment_deleted.ts   |  55 ++++++++++
 .../webhooks/events/repo/comment_edited.ts    |  68 ++++++++++++
 src/server/webhooks/events/repo/event.ts      |  28 +++++
 src/server/webhooks/events/repo/forked.ts     |  56 ++++++++++
 src/server/webhooks/events/repo/index.ts      |   9 ++
 src/server/webhooks/events/repo/modified.ts   |  42 ++++++++
 .../webhooks/events/repo/refs_changed.ts      | 100 ++++++++++++++++++
 .../webhooks/events/repo/secret_detected.ts   |  56 ++++++++++
 .../webhooks/events/repo/synchronized.ts      |  82 ++++++++++++++
 src/server/webhooks/headers.ts                |  60 +++++++++++
 src/server/webhooks/index.ts                  |   2 +
 33 files changed, 1802 insertions(+), 1 deletion(-)
 create mode 100644 src/server/webhooks/events/event.ts
 create mode 100644 src/server/webhooks/events/index.ts
 create mode 100644 src/server/webhooks/events/pr/comment_added.ts
 create mode 100644 src/server/webhooks/events/pr/comment_deleted.ts
 create mode 100644 src/server/webhooks/events/pr/comment_edited.ts
 create mode 100644 src/server/webhooks/events/pr/declined.ts
 create mode 100644 src/server/webhooks/events/pr/deleted.ts
 create mode 100644 src/server/webhooks/events/pr/event.ts
 create mode 100644 src/server/webhooks/events/pr/from_ref_updated.ts
 create mode 100644 src/server/webhooks/events/pr/index.ts
 create mode 100644 src/server/webhooks/events/pr/merged.ts
 create mode 100644 src/server/webhooks/events/pr/modified.ts
 create mode 100644 src/server/webhooks/events/pr/opened.ts
 create mode 100644 src/server/webhooks/events/pr/reviewer_approved.ts
 create mode 100644 src/server/webhooks/events/pr/reviewer_changes_requested.ts
 create mode 100644 src/server/webhooks/events/pr/reviewer_unapproved.ts
 create mode 100644 src/server/webhooks/events/pr/reviewer_updated.ts
 create mode 100644 src/server/webhooks/events/project/event.ts
 create mode 100644 src/server/webhooks/events/project/index.ts
 create mode 100644 src/server/webhooks/events/project/modified.ts
 create mode 100644 src/server/webhooks/events/repo/comment_added.ts
 create mode 100644 src/server/webhooks/events/repo/comment_deleted.ts
 create mode 100644 src/server/webhooks/events/repo/comment_edited.ts
 create mode 100644 src/server/webhooks/events/repo/event.ts
 create mode 100644 src/server/webhooks/events/repo/forked.ts
 create mode 100644 src/server/webhooks/events/repo/index.ts
 create mode 100644 src/server/webhooks/events/repo/modified.ts
 create mode 100644 src/server/webhooks/events/repo/refs_changed.ts
 create mode 100644 src/server/webhooks/events/repo/secret_detected.ts
 create mode 100644 src/server/webhooks/events/repo/synchronized.ts
 create mode 100644 src/server/webhooks/headers.ts
 create mode 100644 src/server/webhooks/index.ts

diff --git a/src/server/index.ts b/src/server/index.ts
index 959f0af..dc5e26e 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -1,2 +1,3 @@
 export * from "./client.js"
-export * as server from "./openapi/index.js"
+export * from "./openapi/index.js"
+export * from "./webhooks/index.js"
diff --git a/src/server/webhooks/events/event.ts b/src/server/webhooks/events/event.ts
new file mode 100644
index 0000000..fb0b8d1
--- /dev/null
+++ b/src/server/webhooks/events/event.ts
@@ -0,0 +1,9 @@
+import type { PrEvent } from "./pr/event.js"
+import type { ProjectEvent } from "./project/event.js"
+import type { RepoEvent } from "./repo/event.js"
+
+export type Event = PrEvent | ProjectEvent | RepoEvent
+export type EventKey =
+	| PrEvent["eventKey"]
+	| ProjectEvent["eventKey"]
+	| RepoEvent["eventKey"]
diff --git a/src/server/webhooks/events/index.ts b/src/server/webhooks/events/index.ts
new file mode 100644
index 0000000..be1f14c
--- /dev/null
+++ b/src/server/webhooks/events/index.ts
@@ -0,0 +1,4 @@
+export * from "./event.js"
+export * as pr from "./pr/index.js"
+export * as project from "./project/index.js"
+export * as repo from "./repo/index.js"
diff --git a/src/server/webhooks/events/pr/comment_added.ts b/src/server/webhooks/events/pr/comment_added.ts
new file mode 100644
index 0000000..3e63843
--- /dev/null
+++ b/src/server/webhooks/events/pr/comment_added.ts
@@ -0,0 +1,91 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Comment {
+	readonly author: Actor
+	readonly comments: unknown[]
+	readonly createdDate: number
+	readonly id: number
+	readonly properties: Properties
+	readonly tasks: unknown[]
+	readonly text: string
+	readonly updatedDate: number
+	readonly version: number
+}
+
+/** A user comments on a pull request. This payload comes with an event key of `pr:comment:added`. */
+export interface PRCommentAdded {
+	/** The user that created the comment. */
+	readonly actor: Actor
+	/** The comment created. */
+	readonly comment: Comment
+	/** Id of the parent comment if one exists. */
+	readonly commentParentId: number
+	readonly date: string
+	readonly eventKey: "pr:comment:added"
+	/** The pull request comment on. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Properties {
+	readonly repositoryId: number
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: unknown[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/comment_deleted.ts b/src/server/webhooks/events/pr/comment_deleted.ts
new file mode 100644
index 0000000..90a181c
--- /dev/null
+++ b/src/server/webhooks/events/pr/comment_deleted.ts
@@ -0,0 +1,87 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Comment {
+	readonly author: Actor
+	readonly comments: unknown[]
+	readonly createdDate: number
+	readonly id: number
+	readonly tasks: unknown[]
+	readonly text: string
+	readonly updatedDate: number
+	readonly version: number
+}
+
+/** A user deletes a comment on a pull request. This payload comes with an event
+ * key of `pr:comment:deleted`. */
+export interface PRCommentDeleted {
+	/** The user that deleted the comment. */
+	readonly actor: Actor
+	/** The comment deleted. */
+	readonly comment: Comment
+	/** Id of the parent comment if one exists. */
+	readonly commentParentId: number
+	readonly date: string
+	readonly eventKey: "pr:comment:deleted"
+	/** The pull request where the comment existed. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: unknown[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/comment_edited.ts b/src/server/webhooks/events/pr/comment_edited.ts
new file mode 100644
index 0000000..0b12f91
--- /dev/null
+++ b/src/server/webhooks/events/pr/comment_edited.ts
@@ -0,0 +1,93 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Comment {
+	readonly author: Actor
+	readonly comments: unknown[]
+	readonly createdDate: number
+	readonly id: number
+	readonly properties: Properties
+	readonly tasks: unknown[]
+	readonly text: string
+	readonly updatedDate: number
+	readonly version: number
+}
+
+/** This payload comes with an event key of `pr:comment:edited`. */
+export interface PRCommentEdited {
+	/** The user that edited the comment. */
+	readonly actor: Actor
+	/** The comment edited. */
+	readonly comment: Comment
+	/** Id of the parent comment if one exists. */
+	readonly commentParentId: number
+	readonly date: string
+	readonly eventKey: "pr:comment:edited"
+	/** Text of the previous comment. */
+	readonly previousComment: string
+	/** The pull request where the comment exists. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Properties {
+	readonly repositoryId: number
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: unknown[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/declined.ts b/src/server/webhooks/events/pr/declined.ts
new file mode 100644
index 0000000..ac3d1a2
--- /dev/null
+++ b/src/server/webhooks/events/pr/declined.ts
@@ -0,0 +1,73 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+/** A user declines a pull request for a repository. This payload comes with an
+ * event key of `pr:declined`. */
+export interface PRDeclined {
+	/** The user who declined the pull request. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:declined"
+	/** Details of the pull request declined. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly closedDate: number
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Author[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/deleted.ts b/src/server/webhooks/events/pr/deleted.ts
new file mode 100644
index 0000000..a8dbcf0
--- /dev/null
+++ b/src/server/webhooks/events/pr/deleted.ts
@@ -0,0 +1,72 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+/** A user deletes a pull request for a repository. This payload comes with an
+ * event key of `pr:deleted`. */
+export interface PRDeleted {
+	/** The user who deleted the pull request. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:deleted"
+	/** Details of the pull request deleted. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Author[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/event.ts b/src/server/webhooks/events/pr/event.ts
new file mode 100644
index 0000000..caee61f
--- /dev/null
+++ b/src/server/webhooks/events/pr/event.ts
@@ -0,0 +1,44 @@
+import type { PRCommentAdded } from "./comment_added.js"
+import type { PRCommentDeleted } from "./comment_deleted.js"
+import type { PRCommentEdited } from "./comment_edited.js"
+import type { PRDeclined } from "./declined.js"
+import type { PRDeleted } from "./deleted.js"
+import type { PRFromRefUpdated } from "./from_ref_updated.js"
+import type { PRMerged } from "./merged.js"
+import type { PRModified } from "./modified.js"
+import type { PROpened } from "./opened.js"
+import type { PRReviewerApproved } from "./reviewer_approved.js"
+import type { PRReviewerChangesRequested } from "./reviewer_changes_requested.js"
+import type { PRReviewerUnapproved } from "./reviewer_unapproved.js"
+import type { PRReviewerUpdated } from "./reviewer_updated.js"
+
+/** You can create webhooks for events that occur on a pull request. */
+export type PrEvent =
+	| PRCommentAdded
+	| PRCommentDeleted
+	| PRCommentEdited
+	| PRDeclined
+	| PRDeleted
+	| PRFromRefUpdated
+	| PRMerged
+	| PRModified
+	| PROpened
+	| PRReviewerApproved
+	| PRReviewerChangesRequested
+	| PRReviewerUnapproved
+	| PRReviewerUpdated
+
+export type PrEventKey =
+	| PRCommentAdded["eventKey"]
+	| PRCommentDeleted["eventKey"]
+	| PRCommentEdited["eventKey"]
+	| PRDeclined["eventKey"]
+	| PRDeleted["eventKey"]
+	| PRFromRefUpdated["eventKey"]
+	| PRMerged["eventKey"]
+	| PRModified["eventKey"]
+	| PROpened["eventKey"]
+	| PRReviewerApproved["eventKey"]
+	| PRReviewerChangesRequested["eventKey"]
+	| PRReviewerUnapproved["eventKey"]
+	| PRReviewerUpdated["eventKey"]
diff --git a/src/server/webhooks/events/pr/from_ref_updated.ts b/src/server/webhooks/events/pr/from_ref_updated.ts
new file mode 100644
index 0000000..7027d8a
--- /dev/null
+++ b/src/server/webhooks/events/pr/from_ref_updated.ts
@@ -0,0 +1,95 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly links: ActorLinks
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface ActorLinks {
+	readonly self: Self[]
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Clone {
+	readonly href: string
+	readonly name: string
+}
+
+export interface PRFromRefUpdated {
+	/** The user who created the pull request. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:from_ref_updated"
+	/** Previous from-ref hash */
+	readonly previousFromHash: string
+	/** Details of the pull request created. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly links: ActorLinks
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly links: ActorLinks
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: unknown[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly hierarchyId: string
+	readonly id: number
+	readonly links: RepositoryLinks
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
+
+export interface RepositoryLinks {
+	readonly clone: Clone[]
+	readonly self: Self[]
+}
+
+export interface Self {
+	readonly href: string
+}
diff --git a/src/server/webhooks/events/pr/index.ts b/src/server/webhooks/events/pr/index.ts
new file mode 100644
index 0000000..45aa667
--- /dev/null
+++ b/src/server/webhooks/events/pr/index.ts
@@ -0,0 +1,13 @@
+export * as commentAdded from "./comment_added.js"
+export * as commentEdited from "./comment_edited.js"
+export * as declined from "./declined.js"
+export * as deleted from "./deleted.js"
+export * from "./event.js"
+export * as fromRefUpdated from "./from_ref_updated.js"
+export * as merged from "./merged.js"
+export * as modified from "./modified.js"
+export * as opened from "./opened.js"
+export * as reviewerApproved from "./reviewer_approved.js"
+export * as reviewerChangesRequested from "./reviewer_changes_requested.js"
+export * as reviewerUnapproved from "./reviewer_unapproved.js"
+export * as reviewerUpdated from "./reviewer_updated.js"
diff --git a/src/server/webhooks/events/pr/merged.ts b/src/server/webhooks/events/pr/merged.ts
new file mode 100644
index 0000000..9fca710
--- /dev/null
+++ b/src/server/webhooks/events/pr/merged.ts
@@ -0,0 +1,83 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface MergeCommit {
+	readonly displayId: string
+	readonly id: string
+}
+
+/** A user merges a pull request for a repository. This payload comes with an
+ * event key of `pr:merged`. */
+export interface PRMerged {
+	/** The user who merged the pull request. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:merged"
+	/** Details of the pull request merged. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Properties {
+	readonly mergeCommit: MergeCommit
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly closedDate: number
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: Author[]
+	readonly properties: Properties
+	readonly reviewers: unknown[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/modified.ts b/src/server/webhooks/events/pr/modified.ts
new file mode 100644
index 0000000..40d421d
--- /dev/null
+++ b/src/server/webhooks/events/pr/modified.ts
@@ -0,0 +1,86 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface PRModified {
+	/** The user who created the pull request. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:modified"
+	/** Previous description of the pull request, may not have changed */
+	readonly previousDescription: string
+	readonly previousDraft: boolean
+	/** Previous target of the pull request, may not have changed */
+	readonly previousTarget: PreviousTarget
+	/** Previous title of the pull request, may not have changed */
+	readonly previousTitle: string
+	/** Details of the pull request created. */
+	readonly pullRequest: PullRequest
+}
+
+export interface PreviousTarget {
+	readonly displayId: string
+	readonly id: string
+	readonly latestChangeset: string
+	readonly latestCommit: string
+	readonly type: string
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly owner: Actor
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly description: string
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Author[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/opened.ts b/src/server/webhooks/events/pr/opened.ts
new file mode 100644
index 0000000..02c2235
--- /dev/null
+++ b/src/server/webhooks/events/pr/opened.ts
@@ -0,0 +1,75 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Links {
+	readonly self: null[]
+}
+
+export interface PROpened {
+	/** The user who created the pull request. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:opened"
+	/** Details of the pull request created. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly links: Links
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: unknown[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/reviewer_approved.ts b/src/server/webhooks/events/pr/reviewer_approved.ts
new file mode 100644
index 0000000..be58366
--- /dev/null
+++ b/src/server/webhooks/events/pr/reviewer_approved.ts
@@ -0,0 +1,83 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Links {
+	readonly self: null[]
+}
+
+/** A user approves a pull request for a repository. This payload comes with an
+ * event key of `pr:reviewer:approved`. */
+export interface PRReviewerApproved {
+	/** The user which made the approval. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:reviewer:approved"
+	/** Details of the PR participant status of the user making the change */
+	readonly participant: Participant
+	/** The state of the approval before this change */
+	readonly previousStatus: string
+	/** Details of the pull request approved. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Participant {
+	readonly approved: boolean
+	readonly lastReviewedCommit?: string
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Participant
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly description: string
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly links: Links
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Participant[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/reviewer_changes_requested.ts b/src/server/webhooks/events/pr/reviewer_changes_requested.ts
new file mode 100644
index 0000000..4bb745a
--- /dev/null
+++ b/src/server/webhooks/events/pr/reviewer_changes_requested.ts
@@ -0,0 +1,78 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+/** A user marks a pull request as changes requested. This payload comes with an
+ * event key of `pr:reviewer:needs_work`. */
+export interface PRReviewerChangesRequested {
+	/** The user who marked the PR as "Changes requested". */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:reviewer:changes_requested"
+	/** Details of the PR participant status of the user making the change. */
+	readonly participant: Participant
+	/** The state of the approval before this change. */
+	readonly previousStatus: string
+	/** Details of the pull request marked "Changes requested". */
+	readonly pullRequest: PullRequest
+}
+
+export interface Participant {
+	readonly approved: boolean
+	readonly lastReviewedCommit?: string
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Participant
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly description: string
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Participant[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/reviewer_unapproved.ts b/src/server/webhooks/events/pr/reviewer_unapproved.ts
new file mode 100644
index 0000000..87b59ff
--- /dev/null
+++ b/src/server/webhooks/events/pr/reviewer_unapproved.ts
@@ -0,0 +1,78 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+/** A user removes an approval from a pull request for a repository. This
+ * payload comes with an event key of `pr:reviewer:unapproved`. */
+export interface PRReviewerUnapproved {
+	/** The user which removed the approval. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "pr:reviewer:unapproved"
+	/** Details of the PR participant status of the user making the change */
+	readonly participant: Participant
+	/** The state of the approval before this change */
+	readonly previousStatus: string
+	/** Details of the pull request unapproved. */
+	readonly pullRequest: PullRequest
+}
+
+export interface Participant {
+	readonly approved: boolean
+	readonly lastReviewedCommit?: string
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Participant
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly description: string
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Participant[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/pr/reviewer_updated.ts b/src/server/webhooks/events/pr/reviewer_updated.ts
new file mode 100644
index 0000000..c727db3
--- /dev/null
+++ b/src/server/webhooks/events/pr/reviewer_updated.ts
@@ -0,0 +1,75 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly approved: boolean
+	readonly role: string
+	readonly status: string
+	readonly user: Actor
+}
+
+export interface PRReviewerUpdated {
+	/** The user who created the pull request. */
+	readonly actor: Actor
+	/** Users that have been added as reviewers */
+	readonly addedReviewers: Actor[]
+	readonly date: string
+	readonly eventKey: "pr:reviewer:updated"
+	/** Details of the pull request created. */
+	readonly pullRequest: PullRequest
+	/** Users that are no longer reviewers */
+	readonly removedReviewers: Actor[]
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly owner: Actor
+	readonly type: string
+}
+
+export interface PullRequest {
+	readonly author: Author
+	readonly closed: boolean
+	readonly createdDate: number
+	readonly description: string
+	readonly draft: boolean
+	readonly fromRef: Ref
+	readonly id: number
+	readonly locked: boolean
+	readonly open: boolean
+	readonly participants: unknown[]
+	readonly reviewers: Author[]
+	readonly state: string
+	readonly title: string
+	readonly toRef: Ref
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly latestCommit: string
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/project/event.ts b/src/server/webhooks/events/project/event.ts
new file mode 100644
index 0000000..797c216
--- /dev/null
+++ b/src/server/webhooks/events/project/event.ts
@@ -0,0 +1,5 @@
+import type { ProjectModified } from "./modified.js"
+
+/** You can create webhooks for events that occur in a project. */
+export type ProjectEvent = ProjectModified
+export type ProjectEventKey = ProjectModified["eventKey"]
diff --git a/src/server/webhooks/events/project/index.ts b/src/server/webhooks/events/project/index.ts
new file mode 100644
index 0000000..941f40a
--- /dev/null
+++ b/src/server/webhooks/events/project/index.ts
@@ -0,0 +1,2 @@
+export * from "./event.js"
+export * from "./modified.js"
diff --git a/src/server/webhooks/events/project/modified.ts b/src/server/webhooks/events/project/modified.ts
new file mode 100644
index 0000000..3bd8a01
--- /dev/null
+++ b/src/server/webhooks/events/project/modified.ts
@@ -0,0 +1,30 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+/** A user updates the **Name** of a project. This payload comes with an event
+ * key of `project:modified`. */
+export interface ProjectModified {
+	/** The user who made the update. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "project:modified"
+	/** The defaults of the current version of the project. */
+	readonly new: Project
+	/** The details of the old version of the project. */
+	readonly old: Project
+}
diff --git a/src/server/webhooks/events/repo/comment_added.ts b/src/server/webhooks/events/repo/comment_added.ts
new file mode 100644
index 0000000..c72ff45
--- /dev/null
+++ b/src/server/webhooks/events/repo/comment_added.ts
@@ -0,0 +1,66 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Comment {
+	readonly author: Actor
+	readonly comments: unknown[]
+	readonly createdDate: number
+	readonly id: number
+	readonly permittedOperations: PermittedOperations
+	readonly properties: Properties
+	readonly tasks: unknown[]
+	readonly text: string
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface PermittedOperations {
+	readonly deletable: boolean
+	readonly editable: boolean
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Properties {
+	readonly repositoryId: number
+}
+
+/** A user comments on a commit in a repository. This payload comes with an
+ * event key of `repo:comment:added`. */
+export interface RepoCommentAdded {
+	/** The user who comments on the commit. */
+	readonly actor: Actor
+	/** The comment created. */
+	readonly comment: Comment
+	/** The hash. */
+	readonly commit: string
+	readonly date: string
+	readonly eventKey: `repo:comment:added`
+	/** The repository with the commit. */
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/repo/comment_deleted.ts b/src/server/webhooks/events/repo/comment_deleted.ts
new file mode 100644
index 0000000..a04c76f
--- /dev/null
+++ b/src/server/webhooks/events/repo/comment_deleted.ts
@@ -0,0 +1,55 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Comment {
+	readonly author: Actor
+	readonly comments: unknown[]
+	readonly createdDate: number
+	readonly id: number
+	readonly tasks: unknown[]
+	readonly text: string
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+/** A user deletes a comment on a commit in a repository. This payload comes
+ * with an event key of `repo:comment:deleted`. */
+export interface RepoCommentDeleted {
+	/** The user who deletes the commit. */
+	readonly actor: Actor
+	/** The comment deleted. */
+	readonly comment: Comment
+	/** The hash of the commit. */
+	readonly commit: string
+	readonly date: string
+	readonly eventKey: "repo:comment:deleted"
+	/** The repository with the commit. */
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/repo/comment_edited.ts b/src/server/webhooks/events/repo/comment_edited.ts
new file mode 100644
index 0000000..8aef572
--- /dev/null
+++ b/src/server/webhooks/events/repo/comment_edited.ts
@@ -0,0 +1,68 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Comment {
+	readonly author: Actor
+	readonly comments: unknown[]
+	readonly createdDate: number
+	readonly id: number
+	readonly permittedOperations: PermittedOperations
+	readonly properties: Properties
+	readonly tasks: unknown[]
+	readonly text: string
+	readonly updatedDate: number
+	readonly version: number
+}
+
+export interface PermittedOperations {
+	readonly deletable: boolean
+	readonly editable: boolean
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Properties {
+	readonly repositoryId: number
+}
+
+/** A user edits a comment on a commit in a repository. This payload comes with
+ * an event key of `repo:comment:edited`. */
+export interface RepoCommentEdited {
+	/** The user who edits the commit. */
+	readonly actor: Actor
+	/** The comment edited. */
+	readonly comment: Comment
+	/** The hash of the commit. */
+	readonly commit: string
+	readonly date: string
+	readonly eventKey: "repo:comment:edited"
+	/** The text of the comment prior to editing. */
+	readonly previousComment: string
+	/** The repository with the commit. */
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/repo/event.ts b/src/server/webhooks/events/repo/event.ts
new file mode 100644
index 0000000..7880585
--- /dev/null
+++ b/src/server/webhooks/events/repo/event.ts
@@ -0,0 +1,28 @@
+import type { RepoCommentAdded } from "./comment_added.js"
+import type { RepoCommentDeleted } from "./comment_deleted.js"
+import type { RepoCommentEdited } from "./comment_edited.js"
+import type { RepoForked } from "./forked.js"
+import type { RepoModified } from "./modified.js"
+import type { RepoRefsChanged } from "./refs_changed.js"
+import type { RepoSecretDetected } from "./secret_detected.js"
+import type { MirrorRepoSynchronized } from "./synchronized.js"
+
+/** You can create webhooks for events that occur in a repository. */
+export type RepoEvent =
+	| MirrorRepoSynchronized
+	| RepoCommentAdded
+	| RepoCommentDeleted
+	| RepoCommentEdited
+	| RepoForked
+	| RepoModified
+	| RepoRefsChanged
+	| RepoSecretDetected
+export type RepoEventKey =
+	| MirrorRepoSynchronized["eventKey"]
+	| RepoCommentAdded["eventKey"]
+	| RepoCommentDeleted["eventKey"]
+	| RepoCommentEdited["eventKey"]
+	| RepoForked["eventKey"]
+	| RepoModified["eventKey"]
+	| RepoRefsChanged["eventKey"]
+	| RepoSecretDetected["eventKey"]
diff --git a/src/server/webhooks/events/repo/forked.ts b/src/server/webhooks/events/repo/forked.ts
new file mode 100644
index 0000000..2b56906
--- /dev/null
+++ b/src/server/webhooks/events/repo/forked.ts
@@ -0,0 +1,56 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Origin {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly owner?: Actor
+	readonly public?: boolean
+	readonly type: string
+}
+
+/** A user forks a repository. This payload comes with an event key of
+ * `repo:forked`. */
+export interface RepoForked {
+	/** The user who forks the repository. This user is also the owner of the
+	 * fork. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "repo:forked"
+	/** The new repository. */
+	readonly repository: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	/** The original repository that was forked. */
+	readonly origin: Origin
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/repo/index.ts b/src/server/webhooks/events/repo/index.ts
new file mode 100644
index 0000000..7d09ce9
--- /dev/null
+++ b/src/server/webhooks/events/repo/index.ts
@@ -0,0 +1,9 @@
+export * as commentAdded from "./comment_added.js"
+export * as commentDeleted from "./comment_deleted.js"
+export * as commentEdited from "./comment_edited.js"
+export * from "./event.js"
+export * as forked from "./forked.js"
+export * as modified from "./modified.js"
+export * as refsChanged from "./refs_changed.js"
+export * as secretDetected from "./secret_detected.js"
+export * as synchronized from "./synchronized.js"
diff --git a/src/server/webhooks/events/repo/modified.ts b/src/server/webhooks/events/repo/modified.ts
new file mode 100644
index 0000000..1a9f59a
--- /dev/null
+++ b/src/server/webhooks/events/repo/modified.ts
@@ -0,0 +1,42 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+/** A user updates the **Name** of a repository. This payload comes with an
+ * event key of `repo:modified`. */
+export interface RepoModified {
+	/** The user who made the update. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "repo:modified"
+	/** The defaults of the current version of the repository. */
+	readonly new: Repository
+	/** The details of the old version of the repository. */
+	readonly old: Repository
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
diff --git a/src/server/webhooks/events/repo/refs_changed.ts b/src/server/webhooks/events/repo/refs_changed.ts
new file mode 100644
index 0000000..7bf60bb
--- /dev/null
+++ b/src/server/webhooks/events/repo/refs_changed.ts
@@ -0,0 +1,100 @@
+export interface Actor {
+	readonly active: boolean
+	readonly displayName: string
+	readonly emailAddress: string
+	readonly id: number
+	readonly name: string
+	readonly slug: string
+	readonly type: string
+}
+
+export interface Author {
+	readonly emailAddress: string
+	readonly name: string
+}
+
+export interface Change {
+	readonly fromHash: string
+	readonly ref: Ref
+	readonly refId: string
+	readonly toHash: string
+	readonly type: string
+}
+
+export interface Commit {
+	readonly author: Author
+	readonly authorTimestamp: number
+	readonly committer: Author
+	readonly committerTimestamp: number
+	readonly displayId: string
+	readonly id: string
+	readonly message: string
+	readonly parents: Parent[]
+}
+
+export interface Parent {
+	readonly displayId: string
+	readonly id: string
+}
+
+export interface Project {
+	readonly description: string
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly type: string
+}
+
+/** A user pushes one or more commits to a repository. This payload comes with
+ * an event key of `repo:refs_changed`. */
+export interface RepoRefsChanged {
+	/** The user who pushed the commits. */
+	readonly actor: Actor
+	/** The details of the push. */
+	readonly changes: Change[]
+	/**
+	 * The details of the commit pushed.
+	 *
+	 * By default, the maximum number of commits included is 5. If the number of
+	 * commits pushed is greater than the limit set, the list will include only
+	 * the most recent commits.
+	 */
+	readonly commits: Commit[]
+	readonly date: string
+	readonly eventKey: "repo:refs_changed"
+	/** The repository with the commits. */
+	readonly repository: Repository
+	readonly toCommit: ToCommit
+}
+
+export interface Repository {
+	readonly archived: boolean
+	readonly forkable: boolean
+	readonly hierarchyId: string
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
+
+export interface ToCommit {
+	readonly author: Author
+	readonly authorTimestamp: number
+	readonly committer: Author
+	readonly committerTimestamp: number
+	readonly displayId: string
+	readonly id: string
+	readonly message: string
+	readonly parents: Commit[]
+}
diff --git a/src/server/webhooks/events/repo/secret_detected.ts b/src/server/webhooks/events/repo/secret_detected.ts
new file mode 100644
index 0000000..7b88d84
--- /dev/null
+++ b/src/server/webhooks/events/repo/secret_detected.ts
@@ -0,0 +1,56 @@
+export interface Actor {
+	readonly active: boolean
+	readonly backingCrowdUser: null
+	readonly crowdBacked: boolean
+	readonly deletedDate: null
+	readonly displayName: string
+	readonly emailAddress: null
+	readonly id: number
+	readonly locale: null
+	readonly name: string
+	readonly slug: string
+	readonly timeZone: null
+	readonly type: string
+	readonly username: string
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+/** A user pushes one or more commits that contain a secret to a repository.
+ * This payload comes with an event key of `repo:secret_detected`. */
+export interface RepoSecretDetected {
+	/** The user who pushed the commits. */
+	readonly actor: Actor
+	readonly date: string
+	readonly eventKey: "repo:secret_detected"
+	/** The details of the commits that contain a secret. */
+	readonly secretLocations: SecretLocation[]
+}
+
+export interface Repository {
+	readonly archived: boolean
+	readonly forkable: boolean
+	readonly hierarchyId: string
+	readonly id: number
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
+
+export interface SecretLocation {
+	readonly commitId: string
+	readonly line: number
+	readonly path: string
+	readonly repository: Repository
+	readonly ruleName: string
+}
diff --git a/src/server/webhooks/events/repo/synchronized.ts b/src/server/webhooks/events/repo/synchronized.ts
new file mode 100644
index 0000000..9ba885c
--- /dev/null
+++ b/src/server/webhooks/events/repo/synchronized.ts
@@ -0,0 +1,82 @@
+export interface Change {
+	readonly fromHash: string
+	readonly ref: Ref
+	readonly refId: string
+	readonly toHash: string
+	readonly type: string
+}
+
+export interface Clone {
+	readonly href: string
+	readonly name: string
+}
+
+export interface Links {
+	readonly clone: Clone[]
+	readonly self: Self[]
+}
+
+/** A mirror has finished synchronizing this repository. This payload comes with
+ * an event key of `mirror:repo_synchronized`. */
+export interface MirrorRepoSynchronized {
+	/** The ref changes for this push. */
+	readonly changes: Change[]
+	readonly date: string
+	readonly eventKey: "mirror:repo_synchronized"
+	/** The mirror which synchronized the changes. This JSON object contains both
+	 * the name and the `id` of the `mirrorServer` which synchronized the
+	 * changes. */
+	readonly mirrorServer: MirrorServer
+	/** If this value is `true`, the list of changes will be empty because it
+	 * exceeded the limit of refs that can be included. */
+	readonly refLimitExceeded: boolean
+	/** The repository. */
+	readonly repository: Repository
+	/**
+	 * The sync type the mirror used to synchronize the changes which are
+	 * announced by this webhook.
+	 *
+	 * This value can be `snapshot` or `incremental` for mirrors 6.7 and higher.
+	 * It defaults to `smartMirror` for mirrors before version 6.7.
+	 */
+	readonly syncType: string
+}
+
+export interface MirrorServer {
+	readonly id: string
+	readonly name: string
+}
+
+export interface Project {
+	readonly id: number
+	readonly key: string
+	readonly name: string
+	readonly public: boolean
+	readonly type: string
+}
+
+export interface Ref {
+	readonly displayId: string
+	readonly id: string
+	readonly type: string
+}
+
+export interface Repository {
+	readonly forkable: boolean
+	readonly id: number
+	/** This JSON object contains the HTTP and SSH clone URLs of the primary
+	 * server as well as the mirror that synchronized these changes. It also
+	 * contains a link to view this repository in Bitbucket. */
+	readonly links: Links
+	readonly name: string
+	readonly project: Project
+	readonly public: boolean
+	readonly scmId: string
+	readonly slug: string
+	readonly state: string
+	readonly statusMessage: string
+}
+
+export interface Self {
+	readonly href: string
+}
diff --git a/src/server/webhooks/headers.ts b/src/server/webhooks/headers.ts
new file mode 100644
index 0000000..dd1ff74
--- /dev/null
+++ b/src/server/webhooks/headers.ts
@@ -0,0 +1,60 @@
+import type { UUID } from "crypto"
+import type { EventKey } from "./events/event.js"
+
+/**
+ * All event payload requests may have these HTTP headers.
+ *
+ * @see https://confluence.atlassian.com/bitbucketserver/event-payload-938025882.html#Eventpayload-HTTPheaders
+ */
+export interface BitbucketServerWebhookHeaders {
+	/** A unique UUID for each webhook request */
+	"X-Request-Id": UUID
+
+	/**
+	 * The event that kicked off this webhook. For example, a repository push will
+	 * have `repo:refs_changed`.
+	 */
+
+	"X-Event-Key": EventKey
+	/**
+	 * ## Securing your webhook
+	 *
+	 * You can secure your webhook using a secret token or by using basic
+	 * authentication.
+	 *
+	 * **Secret token**: Use secret tokens to authenticate the payload and ensure
+	 * that contents are not tampered between Bitbucket and your endpoint.
+	 * Combined with HTTPS, it helps ensure the message transmitted is the one
+	 * that Bitbucket intended to send.
+	 *
+	 * When you define a secret for a webhook, each request is signed via a
+	 * Hash-based Message Authentication Code (HMAC). The default for this
+	 * algorithm is HMACSha256. The header X-Hub-Signature is defined and contains
+	 * the HMAC. For example, the header of the POST request would be plain text
+	 * encoded as follows:
+	 *
+	 * ```ini
+	 * x-hub-signature: sha256=c3383246d4fd871e66e962b50cc12222222222222222222222222222222222
+	 * ```
+	 *
+	 * To authenticate the validity of the message payload, the receiver can
+	 * perform the HMAC algorithm on the received body with the secret as the key
+	 * to the HMAC algorithm. If the results do not match, it may indicate there
+	 * was a problem with transmission that has caused the message payload to
+	 * change.
+	 *
+	 * **Basic authentication**: If your endpoint uses basic authentication (a
+	 * username and password), use this method to secure your webhook. When the
+	 * webhook data is sent, the authorisation header will be included  in the
+	 * HTTP request. The authentication credentials for the Authorization header
+	 * are base64 encoded.
+	 *
+	 * @see https://confluence.atlassian.com/bitbucketserver/manage-webhooks-938025878.html#Managewebhooks-webhooksecrets */
+	"X-Hub-Signature": string
+
+	/**
+	 * The Base64 encoded credentials that authenticate the webhook request.
+	 *
+	 * This header will only be present if the webhook has basic authentication configured. */
+	Authorization?: string
+}
diff --git a/src/server/webhooks/index.ts b/src/server/webhooks/index.ts
new file mode 100644
index 0000000..e17caf5
--- /dev/null
+++ b/src/server/webhooks/index.ts
@@ -0,0 +1,2 @@
+export * from "./events/index.js"
+export * from "./headers.js"