diff --git a/models/webhook/hooktask.go b/models/webhook/hooktask.go
index 4415518cf..2adfcaa60 100644
--- a/models/webhook/hooktask.go
+++ b/models/webhook/hooktask.go
@@ -47,6 +47,7 @@ const (
 	HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected"
 	HookEventPullRequestReviewComment  HookEventType = "pull_request_review_comment"
 	HookEventPullRequestSync           HookEventType = "pull_request_sync"
+	HookEventWiki                      HookEventType = "wiki"
 	HookEventRepository                HookEventType = "repository"
 	HookEventRelease                   HookEventType = "release"
 	HookEventPackage                   HookEventType = "package"
@@ -76,6 +77,8 @@ func (h HookEventType) Event() string {
 		return "pull_request_rejected"
 	case HookEventPullRequestReviewComment:
 		return "pull_request_comment"
+	case HookEventWiki:
+		return "wiki"
 	case HookEventRepository:
 		return "repository"
 	case HookEventRelease:
diff --git a/models/webhook/webhook.go b/models/webhook/webhook.go
index 478a6a29f..ac0922063 100644
--- a/models/webhook/webhook.go
+++ b/models/webhook/webhook.go
@@ -132,6 +132,7 @@ type HookEvents struct {
 	PullRequestComment   bool `json:"pull_request_comment"`
 	PullRequestReview    bool `json:"pull_request_review"`
 	PullRequestSync      bool `json:"pull_request_sync"`
+	Wiki                 bool `json:"wiki"`
 	Repository           bool `json:"repository"`
 	Release              bool `json:"release"`
 	Package              bool `json:"package"`
@@ -328,6 +329,12 @@ func (w *Webhook) HasPullRequestSyncEvent() bool {
 		(w.ChooseEvents && w.HookEvents.PullRequestSync)
 }
 
+// HasWikiEvent returns true if hook enabled wiki event.
+func (w *Webhook) HasWikiEvent() bool {
+	return w.SendEverything ||
+		(w.ChooseEvents && w.HookEvent.Wiki)
+}
+
 // HasReleaseEvent returns if hook enabled release event.
 func (w *Webhook) HasReleaseEvent() bool {
 	return w.SendEverything ||
@@ -373,6 +380,7 @@ func (w *Webhook) EventCheckers() []struct {
 		{w.HasPullRequestRejectedEvent, HookEventPullRequestReviewRejected},
 		{w.HasPullRequestCommentEvent, HookEventPullRequestReviewComment},
 		{w.HasPullRequestSyncEvent, HookEventPullRequestSync},
+		{w.HasWikiEvent, HookEventWiki},
 		{w.HasRepositoryEvent, HookEventRepository},
 		{w.HasReleaseEvent, HookEventRelease},
 		{w.HasPackageEvent, HookEventPackage},
diff --git a/models/webhook/webhook_test.go b/models/webhook/webhook_test.go
index 1d77ee2a4..7ec7edc0b 100644
--- a/models/webhook/webhook_test.go
+++ b/models/webhook/webhook_test.go
@@ -71,7 +71,7 @@ func TestWebhook_EventsArray(t *testing.T) {
 		"issues", "issue_assign", "issue_label", "issue_milestone", "issue_comment",
 		"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
 		"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
-		"pull_request_review_comment", "pull_request_sync", "repository", "release",
+		"pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release",
 		"package",
 	},
 		(&Webhook{
diff --git a/modules/notification/base/notifier.go b/modules/notification/base/notifier.go
index 541731ddb..d6cec92e1 100644
--- a/modules/notification/base/notifier.go
+++ b/modules/notification/base/notifier.go
@@ -45,6 +45,9 @@ type Notifier interface {
 		issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User)
 	NotifyUpdateComment(*user_model.User, *issues_model.Comment, string)
 	NotifyDeleteComment(*user_model.User, *issues_model.Comment)
+	NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string)
+	NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string)
+	NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string)
 	NotifyNewRelease(rel *repo_model.Release)
 	NotifyUpdateRelease(doer *user_model.User, rel *repo_model.Release)
 	NotifyDeleteRelease(doer *user_model.User, rel *repo_model.Release)
diff --git a/modules/notification/base/null.go b/modules/notification/base/null.go
index 4f382b3d0..b113ae79e 100644
--- a/modules/notification/base/null.go
+++ b/modules/notification/base/null.go
@@ -78,6 +78,18 @@ func (*NullNotifier) NotifyUpdateComment(doer *user_model.User, c *issues_model.
 func (*NullNotifier) NotifyDeleteComment(doer *user_model.User, c *issues_model.Comment) {
 }
 
+// NotifyNewWikiPage places a place holder function
+func (*NullNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
+}
+
+// NotifyEditWikiPage places a place holder function
+func (*NullNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
+}
+
+// NotifyDeleteWikiPage places a place holder function
+func (*NullNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
+}
+
 // NotifyNewRelease places a place holder function
 func (*NullNotifier) NotifyNewRelease(rel *repo_model.Release) {
 }
diff --git a/modules/notification/notification.go b/modules/notification/notification.go
index 713cc72aa..693c7f5c2 100644
--- a/modules/notification/notification.go
+++ b/modules/notification/notification.go
@@ -40,6 +40,27 @@ func NewContext() {
 	RegisterNotifier(mirror.NewNotifier())
 }
 
+// NotifyNewWikiPage notifies creating new wiki pages to notifiers
+func NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
+	for _, notifier := range notifiers {
+		notifier.NotifyNewWikiPage(doer, repo, page, comment)
+	}
+}
+
+// NotifyEditWikiPage notifies editing or renaming wiki pages to notifiers
+func NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
+	for _, notifier := range notifiers {
+		notifier.NotifyEditWikiPage(doer, repo, page, comment)
+	}
+}
+
+// NotifyDeleteWikiPage notifies deleting wiki pages to notifiers
+func NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
+	for _, notifier := range notifiers {
+		notifier.NotifyDeleteWikiPage(doer, repo, page)
+	}
+}
+
 // NotifyCreateIssueComment notifies issue comment related message to notifiers
 func NotifyCreateIssueComment(doer *user_model.User, repo *repo_model.Repository,
 	issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go
index ed3b53e3e..0eb2099a2 100644
--- a/modules/notification/webhook/webhook.go
+++ b/modules/notification/webhook/webhook.go
@@ -501,6 +501,44 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *user_model.User, comment *is
 	}
 }
 
+func (m *webhookNotifier) NotifyNewWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
+	// Add to hook queue for created wiki page.
+	if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
+		Action:     api.HookWikiCreated,
+		Repository: convert.ToRepo(repo, perm.AccessModeOwner),
+		Sender:     convert.ToUser(doer, nil),
+		Page:       page,
+		Comment:    comment,
+	}); err != nil {
+		log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
+	}
+}
+
+func (m *webhookNotifier) NotifyEditWikiPage(doer *user_model.User, repo *repo_model.Repository, page, comment string) {
+	// Add to hook queue for edit wiki page.
+	if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
+		Action:     api.HookWikiEdited,
+		Repository: convert.ToRepo(repo, perm.AccessModeOwner),
+		Sender:     convert.ToUser(doer, nil),
+		Page:       page,
+		Comment:    comment,
+	}); err != nil {
+		log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
+	}
+}
+
+func (m *webhookNotifier) NotifyDeleteWikiPage(doer *user_model.User, repo *repo_model.Repository, page string) {
+	// Add to hook queue for edit wiki page.
+	if err := webhook_services.PrepareWebhooks(repo, webhook.HookEventWiki, &api.WikiPayload{
+		Action:     api.HookWikiDeleted,
+		Repository: convert.ToRepo(repo, perm.AccessModeOwner),
+		Sender:     convert.ToUser(doer, nil),
+		Page:       page,
+	}); err != nil {
+		log.Error("PrepareWebhooks [repo_id: %d]: %v", repo.ID, err)
+	}
+}
+
 func (m *webhookNotifier) NotifyIssueChangeLabels(doer *user_model.User, issue *issues_model.Issue,
 	addedLabels, removedLabels []*issues_model.Label,
 ) {
diff --git a/modules/structs/hook.go b/modules/structs/hook.go
index 07d51915d..132b24b85 100644
--- a/modules/structs/hook.go
+++ b/modules/structs/hook.go
@@ -397,6 +397,39 @@ type ReviewPayload struct {
 	Content string `json:"content"`
 }
 
+//  __      __.__ __   .__
+// /  \    /  \__|  | _|__|
+// \   \/\/   /  |  |/ /  |
+//  \        /|  |    <|  |
+//   \__/\  / |__|__|_ \__|
+//        \/          \/
+
+// HookWikiAction an action that happens to a wiki page
+type HookWikiAction string
+
+const (
+	// HookWikiCreated created
+	HookWikiCreated HookWikiAction = "created"
+	// HookWikiEdited edited
+	HookWikiEdited HookWikiAction = "edited"
+	// HookWikiDeleted deleted
+	HookWikiDeleted HookWikiAction = "deleted"
+)
+
+// WikiPayload payload for repository webhooks
+type WikiPayload struct {
+	Action     HookWikiAction `json:"action"`
+	Repository *Repository    `json:"repository"`
+	Sender     *User          `json:"sender"`
+	Page       string         `json:"page"`
+	Comment    string         `json:"comment"`
+}
+
+// JSONPayload JSON representation of the payload
+func (p *WikiPayload) JSONPayload() ([]byte, error) {
+	return json.MarshalIndent(p, "", " ")
+}
+
 //__________                           .__  __
 //\______   \ ____ ______   ____  _____|__|/  |_  ___________ ___.__.
 // |       _// __ \\____ \ /  _ \/  ___/  \   __\/  _ \_  __ <   |  |
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini
index ba647771e..6845680cc 100644
--- a/options/locale/locale_en-US.ini
+++ b/options/locale/locale_en-US.ini
@@ -1956,6 +1956,8 @@ settings.event_delete = Delete
 settings.event_delete_desc = Branch or tag deleted.
 settings.event_fork = Fork
 settings.event_fork_desc = Repository forked.
+settings.event_wiki = Wiki
+settings.event_wiki_desc = Wiki page created, renamed, edited or deleted.
 settings.event_release = Release
 settings.event_release_desc = Release published, updated or deleted in a repository.
 settings.event_push = Push
diff --git a/routers/api/v1/repo/wiki.go b/routers/api/v1/repo/wiki.go
index 82542d1ab..6d9564854 100644
--- a/routers/api/v1/repo/wiki.go
+++ b/routers/api/v1/repo/wiki.go
@@ -14,6 +14,7 @@ import (
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/convert"
 	"code.gitea.io/gitea/modules/git"
+	"code.gitea.io/gitea/modules/notification"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
@@ -85,6 +86,7 @@ func NewWikiPage(ctx *context.APIContext) {
 	wikiPage := getWikiPage(ctx, wikiName)
 
 	if !ctx.Written() {
+		notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message)
 		ctx.JSON(http.StatusCreated, wikiPage)
 	}
 }
@@ -152,6 +154,7 @@ func EditWikiPage(ctx *context.APIContext) {
 	wikiPage := getWikiPage(ctx, newWikiName)
 
 	if !ctx.Written() {
+		notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message)
 		ctx.JSON(http.StatusOK, wikiPage)
 	}
 }
@@ -242,6 +245,8 @@ func DeleteWikiPage(ctx *context.APIContext) {
 		return
 	}
 
+	notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName)
+
 	ctx.Status(http.StatusNoContent)
 }
 
diff --git a/routers/api/v1/utils/hook.go b/routers/api/v1/utils/hook.go
index ba008f587..7e4dfca9a 100644
--- a/routers/api/v1/utils/hook.go
+++ b/routers/api/v1/utils/hook.go
@@ -126,6 +126,7 @@ func addHook(ctx *context.APIContext, form *api.CreateHookOption, orgID, repoID
 				PullRequestComment:   pullHook(form.Events, string(webhook.HookEventPullRequestComment)),
 				PullRequestReview:    pullHook(form.Events, "pull_request_review"),
 				PullRequestSync:      pullHook(form.Events, string(webhook.HookEventPullRequestSync)),
+				Wiki:                 util.IsStringInSlice(string(webhook.HookEventWiki), form.Events, true),
 				Repository:           util.IsStringInSlice(string(webhook.HookEventRepository), form.Events, true),
 				Release:              util.IsStringInSlice(string(webhook.HookEventRelease), form.Events, true),
 			},
@@ -249,6 +250,7 @@ func editHook(ctx *context.APIContext, form *api.EditHookOption, w *webhook.Webh
 	w.Delete = util.IsStringInSlice(string(webhook.HookEventDelete), form.Events, true)
 	w.Fork = util.IsStringInSlice(string(webhook.HookEventFork), form.Events, true)
 	w.Repository = util.IsStringInSlice(string(webhook.HookEventRepository), form.Events, true)
+	w.Wiki = util.IsStringInSlice(string(webhook.HookEventWiki), form.Events, true)
 	w.Release = util.IsStringInSlice(string(webhook.HookEventRelease), form.Events, true)
 	w.BranchFilter = form.BranchFilter
 
diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go
index 7e659de0d..a8939e72b 100644
--- a/routers/web/repo/webhook.go
+++ b/routers/web/repo/webhook.go
@@ -178,6 +178,7 @@ func ParseHookEvent(form forms.WebhookForm) *webhook.HookEvent {
 			PullRequestComment:   form.PullRequestComment,
 			PullRequestReview:    form.PullRequestReview,
 			PullRequestSync:      form.PullRequestSync,
+			Wiki:                 form.Wiki,
 			Repository:           form.Repository,
 			Package:              form.Package,
 		},
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 0c161568b..0f349547c 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -25,6 +25,7 @@ import (
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/markup"
 	"code.gitea.io/gitea/modules/markup/markdown"
+	"code.gitea.io/gitea/modules/notification"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/timeutil"
 	"code.gitea.io/gitea/modules/util"
@@ -705,6 +706,8 @@ func NewWikiPost(ctx *context.Context) {
 		return
 	}
 
+	notification.NotifyNewWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName, form.Message)
+
 	ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(wikiName))
 }
 
@@ -747,6 +750,8 @@ func EditWikiPost(ctx *context.Context) {
 		return
 	}
 
+	notification.NotifyEditWikiPage(ctx.Doer, ctx.Repo.Repository, newWikiName, form.Message)
+
 	ctx.Redirect(ctx.Repo.RepoLink + "/wiki/" + wiki_service.NameToSubURL(newWikiName))
 }
 
@@ -762,6 +767,8 @@ func DeleteWikiPagePost(ctx *context.Context) {
 		return
 	}
 
+	notification.NotifyDeleteWikiPage(ctx.Doer, ctx.Repo.Repository, wikiName)
+
 	ctx.JSON(http.StatusOK, map[string]interface{}{
 		"redirect": ctx.Repo.RepoLink + "/wiki/",
 	})
diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go
index 7a4a2123e..4eb20d297 100644
--- a/services/forms/repo_form.go
+++ b/services/forms/repo_form.go
@@ -215,12 +215,12 @@ func (f *ProtectBranchForm) Validate(req *http.Request, errs binding.Errors) bin
 	return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
 }
 
-//  __      __      ___.   .__    .__            __
-// /  \    /  \ ____\_ |__ |  |__ |  |__   ____ |  | __
-// \   \/\/   // __ \| __ \|  |  \|  |  \ /  _ \|  |/ /
-//  \        /\  ___/| \_\ \   Y  \   Y  (  <_> )    <
-//   \__/\  /  \___  >___  /___|  /___|  /\____/|__|_ \
-//        \/       \/    \/     \/     \/            \/
+//  __      __      ___.   .__                   __
+// /  \    /  \ ____\_ |__ |  |__   ____   ____ |  | __
+// \   \/\/   // __ \| __ \|  |  \ /  _ \ /  _ \|  |/ /
+//  \        /\  ___/| \_\ \   Y  (  <_> |  <_> )    <
+//   \__/\  /  \___  >___  /___|  /\____/ \____/|__|_ \
+//        \/       \/    \/     \/                   \/
 
 // WebhookForm form for changing web hook
 type WebhookForm struct {
@@ -242,6 +242,7 @@ type WebhookForm struct {
 	PullRequestComment   bool
 	PullRequestReview    bool
 	PullRequestSync      bool
+	Wiki                 bool
 	Repository           bool
 	Package              bool
 	Active               bool
diff --git a/services/webhook/dingtalk.go b/services/webhook/dingtalk.go
index 06b73c38d..5112bdb34 100644
--- a/services/webhook/dingtalk.go
+++ b/services/webhook/dingtalk.go
@@ -107,6 +107,14 @@ func (d *DingtalkPayload) Issue(p *api.IssuePayload) (api.Payloader, error) {
 	return createDingtalkPayload(issueTitle, text+"\r\n\r\n"+attachmentText, "view issue", p.Issue.HTMLURL), nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (d *DingtalkPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, _, _ := getWikiPayloadInfo(p, noneLinkFormatter, true)
+	url := p.Repository.HTMLURL + "/wiki/" + url.PathEscape(p.Page)
+
+	return createDingtalkPayload(text, text, "view wiki", url), nil
+}
+
 // IssueComment implements PayloadConvertor IssueComment method
 func (d *DingtalkPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader, error) {
 	text, issueTitle, _ := getIssueCommentPayloadInfo(p, noneLinkFormatter, true)
diff --git a/services/webhook/dingtalk_test.go b/services/webhook/dingtalk_test.go
index b66b5e43a..efc9601c1 100644
--- a/services/webhook/dingtalk_test.go
+++ b/services/webhook/dingtalk_test.go
@@ -189,6 +189,44 @@ func TestDingTalkPayload(t *testing.T) {
 		assert.Equal(t, "http://localhost:3000/test/repo", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(DingtalkPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &DingtalkPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Text)
+		assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Title)
+		assert.Equal(t, "view wiki", pl.(*DingtalkPayload).ActionCard.SingleTitle)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &DingtalkPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Text)
+		assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment) by user1", pl.(*DingtalkPayload).ActionCard.Title)
+		assert.Equal(t, "view wiki", pl.(*DingtalkPayload).ActionCard.SingleTitle)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &DingtalkPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] Wiki page 'index' deleted by user1", pl.(*DingtalkPayload).ActionCard.Text)
+		assert.Equal(t, "[test/repo] Wiki page 'index' deleted by user1", pl.(*DingtalkPayload).ActionCard.Title)
+		assert.Equal(t, "view wiki", pl.(*DingtalkPayload).ActionCard.SingleTitle)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", parseRealSingleURL(pl.(*DingtalkPayload).ActionCard.SingleURL))
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/discord.go b/services/webhook/discord.go
index ae5460b9a..7b6f0f0b1 100644
--- a/services/webhook/discord.go
+++ b/services/webhook/discord.go
@@ -7,6 +7,7 @@ package webhook
 import (
 	"errors"
 	"fmt"
+	"net/url"
 	"strconv"
 	"strings"
 
@@ -235,6 +236,19 @@ func (d *DiscordPayload) Repository(p *api.RepositoryPayload) (api.Payloader, er
 	return d.createPayload(p.Sender, title, "", url, color), nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (d *DiscordPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, color, _ := getWikiPayloadInfo(p, noneLinkFormatter, false)
+	htmlLink := p.Repository.HTMLURL + "/wiki/" + url.PathEscape(p.Page)
+
+	var description string
+	if p.Action != api.HookWikiDeleted {
+		description = p.Comment
+	}
+
+	return d.createPayload(p.Sender, text, description, htmlLink, color), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (d *DiscordPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	text, color := getReleasePayloadInfo(p, noneLinkFormatter, false)
diff --git a/services/webhook/discord_test.go b/services/webhook/discord_test.go
index 8fe20c010..8e4e60a7f 100644
--- a/services/webhook/discord_test.go
+++ b/services/webhook/discord_test.go
@@ -212,6 +212,53 @@ func TestDiscordPayload(t *testing.T) {
 		assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(DiscordPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &DiscordPayload{}, pl)
+
+		assert.Len(t, pl.(*DiscordPayload).Embeds, 1)
+		assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment)", pl.(*DiscordPayload).Embeds[0].Title)
+		assert.Equal(t, "Wiki change comment", pl.(*DiscordPayload).Embeds[0].Description)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", pl.(*DiscordPayload).Embeds[0].URL)
+		assert.Equal(t, p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.Name)
+		assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.URL)
+		assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &DiscordPayload{}, pl)
+
+		assert.Len(t, pl.(*DiscordPayload).Embeds, 1)
+		assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment)", pl.(*DiscordPayload).Embeds[0].Title)
+		assert.Equal(t, "Wiki change comment", pl.(*DiscordPayload).Embeds[0].Description)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", pl.(*DiscordPayload).Embeds[0].URL)
+		assert.Equal(t, p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.Name)
+		assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.URL)
+		assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &DiscordPayload{}, pl)
+
+		assert.Len(t, pl.(*DiscordPayload).Embeds, 1)
+		assert.Equal(t, "[test/repo] Wiki page 'index' deleted", pl.(*DiscordPayload).Embeds[0].Title)
+		assert.Empty(t, pl.(*DiscordPayload).Embeds[0].Description)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", pl.(*DiscordPayload).Embeds[0].URL)
+		assert.Equal(t, p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.Name)
+		assert.Equal(t, setting.AppURL+p.Sender.UserName, pl.(*DiscordPayload).Embeds[0].Author.URL)
+		assert.Equal(t, p.Sender.AvatarURL, pl.(*DiscordPayload).Embeds[0].Author.IconURL)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/feishu.go b/services/webhook/feishu.go
index 5b20c7dda..782684d0f 100644
--- a/services/webhook/feishu.go
+++ b/services/webhook/feishu.go
@@ -145,6 +145,13 @@ func (f *FeishuPayload) Repository(p *api.RepositoryPayload) (api.Payloader, err
 	return nil, nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (f *FeishuPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, _, _ := getWikiPayloadInfo(p, noneLinkFormatter, true)
+
+	return newFeishuTextPayload(text), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (f *FeishuPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true)
diff --git a/services/webhook/feishu_test.go b/services/webhook/feishu_test.go
index d862b015e..85cfb759f 100644
--- a/services/webhook/feishu_test.go
+++ b/services/webhook/feishu_test.go
@@ -145,6 +145,35 @@ func TestFeishuPayload(t *testing.T) {
 		assert.Equal(t, "[test/repo] Repository created", pl.(*FeishuPayload).Content.Text)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(FeishuPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &FeishuPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment) by user1", pl.(*FeishuPayload).Content.Text)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &FeishuPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment) by user1", pl.(*FeishuPayload).Content.Text)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &FeishuPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] Wiki page 'index' deleted by user1", pl.(*FeishuPayload).Content.Text)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/general.go b/services/webhook/general.go
index e8006faba..5be177d33 100644
--- a/services/webhook/general.go
+++ b/services/webhook/general.go
@@ -161,6 +161,35 @@ func getReleasePayloadInfo(p *api.ReleasePayload, linkFormatter linkFormatter, w
 	return text, color
 }
 
+func getWikiPayloadInfo(p *api.WikiPayload, linkFormatter linkFormatter, withSender bool) (string, int, string) {
+	repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
+	pageLink := linkFormatter(p.Repository.HTMLURL+"/wiki/"+url.PathEscape(p.Page), p.Page)
+
+	var text string
+	color := greenColor
+
+	switch p.Action {
+	case api.HookWikiCreated:
+		text = fmt.Sprintf("[%s] New wiki page '%s'", repoLink, pageLink)
+	case api.HookWikiEdited:
+		text = fmt.Sprintf("[%s] Wiki page '%s' edited", repoLink, pageLink)
+		color = yellowColor
+	case api.HookWikiDeleted:
+		text = fmt.Sprintf("[%s] Wiki page '%s' deleted", repoLink, pageLink)
+		color = redColor
+	}
+
+	if p.Action != api.HookWikiDeleted && p.Comment != "" {
+		text += fmt.Sprintf(" (%s)", p.Comment)
+	}
+
+	if withSender {
+		text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName))
+	}
+
+	return text, color, pageLink
+}
+
 func getIssueCommentPayloadInfo(p *api.IssueCommentPayload, linkFormatter linkFormatter, withSender bool) (string, string, int) {
 	repoLink := linkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
 	issueTitle := fmt.Sprintf("#%d %s", p.Issue.Index, p.Issue.Title)
diff --git a/services/webhook/general_test.go b/services/webhook/general_test.go
index 4d73afe06..4acf51ac7 100644
--- a/services/webhook/general_test.go
+++ b/services/webhook/general_test.go
@@ -195,6 +195,22 @@ func pullRequestCommentTestPayload() *api.IssueCommentPayload {
 	}
 }
 
+func wikiTestPayload() *api.WikiPayload {
+	return &api.WikiPayload{
+		Repository: &api.Repository{
+			HTMLURL:  "http://localhost:3000/test/repo",
+			Name:     "repo",
+			FullName: "test/repo",
+		},
+		Sender: &api.User{
+			UserName:  "user1",
+			AvatarURL: "http://localhost:3000/user1/avatar",
+		},
+		Page:    "index",
+		Comment: "Wiki change comment",
+	}
+}
+
 func pullReleaseTestPayload() *api.ReleasePayload {
 	return &api.ReleasePayload{
 		Action: api.HookReleasePublished,
@@ -469,6 +485,44 @@ func TestGetPullRequestPayloadInfo(t *testing.T) {
 	}
 }
 
+func TestGetWikiPayloadInfo(t *testing.T) {
+	p := wikiTestPayload()
+
+	cases := []struct {
+		action api.HookWikiAction
+		text   string
+		color  int
+		link   string
+	}{
+		{
+			api.HookWikiCreated,
+			"[test/repo] New wiki page 'index' (Wiki change comment) by user1",
+			greenColor,
+			"index",
+		},
+		{
+			api.HookWikiEdited,
+			"[test/repo] Wiki page 'index' edited (Wiki change comment) by user1",
+			yellowColor,
+			"index",
+		},
+		{
+			api.HookWikiDeleted,
+			"[test/repo] Wiki page 'index' deleted by user1",
+			redColor,
+			"index",
+		},
+	}
+
+	for i, c := range cases {
+		p.Action = c.action
+		text, color, link := getWikiPayloadInfo(p, noneLinkFormatter, true)
+		assert.Equal(t, c.text, text, "case %d", i)
+		assert.Equal(t, c.color, color, "case %d", i)
+		assert.Equal(t, c.link, link, "case %d", i)
+	}
+}
+
 func TestGetReleasePayloadInfo(t *testing.T) {
 	p := pullReleaseTestPayload()
 
diff --git a/services/webhook/matrix.go b/services/webhook/matrix.go
index a42ab2a93..f4c4cf0e9 100644
--- a/services/webhook/matrix.go
+++ b/services/webhook/matrix.go
@@ -143,6 +143,13 @@ func (m *MatrixPayloadUnsafe) IssueComment(p *api.IssueCommentPayload) (api.Payl
 	return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (m *MatrixPayloadUnsafe) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, _, _ := getWikiPayloadInfo(p, MatrixLinkFormatter, true)
+
+	return getMatrixPayloadUnsafe(text, nil, m.AccessToken, m.MsgType), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (m *MatrixPayloadUnsafe) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	text, _ := getReleasePayloadInfo(p, MatrixLinkFormatter, true)
diff --git a/services/webhook/matrix_test.go b/services/webhook/matrix_test.go
index 34196aedf..4cab84533 100644
--- a/services/webhook/matrix_test.go
+++ b/services/webhook/matrix_test.go
@@ -156,6 +156,38 @@ func TestMatrixPayload(t *testing.T) {
 		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Repository created by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*MatrixPayloadUnsafe).FormattedBody)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(MatrixPayloadUnsafe)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &MatrixPayloadUnsafe{}, pl)
+
+		assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] New wiki page '[index](http://localhost:3000/test/repo/wiki/index)' (Wiki change comment) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body)
+		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] New wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*MatrixPayloadUnsafe).FormattedBody)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &MatrixPayloadUnsafe{}, pl)
+
+		assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' edited (Wiki change comment) by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body)
+		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' edited (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*MatrixPayloadUnsafe).FormattedBody)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &MatrixPayloadUnsafe{}, pl)
+
+		assert.Equal(t, "[[test/repo](http://localhost:3000/test/repo)] Wiki page '[index](http://localhost:3000/test/repo/wiki/index)' deleted by [user1](https://try.gitea.io/user1)", pl.(*MatrixPayloadUnsafe).Body)
+		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' deleted by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*MatrixPayloadUnsafe).FormattedBody)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/msteams.go b/services/webhook/msteams.go
index 59e2e9349..140600478 100644
--- a/services/webhook/msteams.go
+++ b/services/webhook/msteams.go
@@ -6,6 +6,7 @@ package webhook
 
 import (
 	"fmt"
+	"net/url"
 	"strings"
 
 	webhook_model "code.gitea.io/gitea/models/webhook"
@@ -266,6 +267,21 @@ func (m *MSTeamsPayload) Repository(p *api.RepositoryPayload) (api.Payloader, er
 	), nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (m *MSTeamsPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	title, color, _ := getWikiPayloadInfo(p, noneLinkFormatter, false)
+
+	return createMSTeamsPayload(
+		p.Repository,
+		p.Sender,
+		title,
+		"",
+		p.Repository.HTMLURL+"/wiki/"+url.PathEscape(p.Page),
+		color,
+		&MSTeamsFact{"Repository:", p.Repository.FullName},
+	), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (m *MSTeamsPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	title, color := getReleasePayloadInfo(p, noneLinkFormatter, false)
diff --git a/services/webhook/msteams_test.go b/services/webhook/msteams_test.go
index 3fdf47c1a..8292beed7 100644
--- a/services/webhook/msteams_test.go
+++ b/services/webhook/msteams_test.go
@@ -330,6 +330,80 @@ func TestMSTeamsPayload(t *testing.T) {
 		assert.Equal(t, "http://localhost:3000/test/repo", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(MSTeamsPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &MSTeamsPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment)", pl.(*MSTeamsPayload).Title)
+		assert.Equal(t, "[test/repo] New wiki page 'index' (Wiki change comment)", pl.(*MSTeamsPayload).Summary)
+		assert.Len(t, pl.(*MSTeamsPayload).Sections, 1)
+		assert.Equal(t, "user1", pl.(*MSTeamsPayload).Sections[0].ActivitySubtitle)
+		assert.Equal(t, "", pl.(*MSTeamsPayload).Sections[0].Text)
+		assert.Len(t, pl.(*MSTeamsPayload).Sections[0].Facts, 2)
+		for _, fact := range pl.(*MSTeamsPayload).Sections[0].Facts {
+			if fact.Name == "Repository:" {
+				assert.Equal(t, p.Repository.FullName, fact.Value)
+			} else {
+				t.Fail()
+			}
+		}
+		assert.Len(t, pl.(*MSTeamsPayload).PotentialAction, 1)
+		assert.Len(t, pl.(*MSTeamsPayload).PotentialAction[0].Targets, 1)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &MSTeamsPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment)", pl.(*MSTeamsPayload).Title)
+		assert.Equal(t, "[test/repo] Wiki page 'index' edited (Wiki change comment)", pl.(*MSTeamsPayload).Summary)
+		assert.Len(t, pl.(*MSTeamsPayload).Sections, 1)
+		assert.Equal(t, "user1", pl.(*MSTeamsPayload).Sections[0].ActivitySubtitle)
+		assert.Equal(t, "", pl.(*MSTeamsPayload).Sections[0].Text)
+		assert.Len(t, pl.(*MSTeamsPayload).Sections[0].Facts, 2)
+		for _, fact := range pl.(*MSTeamsPayload).Sections[0].Facts {
+			if fact.Name == "Repository:" {
+				assert.Equal(t, p.Repository.FullName, fact.Value)
+			} else {
+				t.Fail()
+			}
+		}
+		assert.Len(t, pl.(*MSTeamsPayload).PotentialAction, 1)
+		assert.Len(t, pl.(*MSTeamsPayload).PotentialAction[0].Targets, 1)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &MSTeamsPayload{}, pl)
+
+		assert.Equal(t, "[test/repo] Wiki page 'index' deleted", pl.(*MSTeamsPayload).Title)
+		assert.Equal(t, "[test/repo] Wiki page 'index' deleted", pl.(*MSTeamsPayload).Summary)
+		assert.Len(t, pl.(*MSTeamsPayload).Sections, 1)
+		assert.Equal(t, "user1", pl.(*MSTeamsPayload).Sections[0].ActivitySubtitle)
+		assert.Empty(t, pl.(*MSTeamsPayload).Sections[0].Text)
+		assert.Len(t, pl.(*MSTeamsPayload).Sections[0].Facts, 2)
+		for _, fact := range pl.(*MSTeamsPayload).Sections[0].Facts {
+			if fact.Name == "Repository:" {
+				assert.Equal(t, p.Repository.FullName, fact.Value)
+			} else {
+				t.Fail()
+			}
+		}
+		assert.Len(t, pl.(*MSTeamsPayload).PotentialAction, 1)
+		assert.Len(t, pl.(*MSTeamsPayload).PotentialAction[0].Targets, 1)
+		assert.Equal(t, "http://localhost:3000/test/repo/wiki/index", pl.(*MSTeamsPayload).PotentialAction[0].Targets[0].URI)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/packagist.go b/services/webhook/packagist.go
index ace93b13f..5badc7462 100644
--- a/services/webhook/packagist.go
+++ b/services/webhook/packagist.go
@@ -94,6 +94,11 @@ func (f *PackagistPayload) Repository(p *api.RepositoryPayload) (api.Payloader,
 	return nil, nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (f *PackagistPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	return nil, nil
+}
+
 // Release implements PayloadConvertor Release method
 func (f *PackagistPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	return nil, nil
diff --git a/services/webhook/packagist_test.go b/services/webhook/packagist_test.go
index 08912924d..4a24b7652 100644
--- a/services/webhook/packagist_test.go
+++ b/services/webhook/packagist_test.go
@@ -116,6 +116,26 @@ func TestPackagistPayload(t *testing.T) {
 		require.Nil(t, pl)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(PackagistPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.Nil(t, pl)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.Nil(t, pl)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.Nil(t, pl)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/payloader.go b/services/webhook/payloader.go
index 0e09dd1b1..a9d01c989 100644
--- a/services/webhook/payloader.go
+++ b/services/webhook/payloader.go
@@ -22,6 +22,7 @@ type PayloadConvertor interface {
 	Review(*api.PullRequestPayload, webhook_model.HookEventType) (api.Payloader, error)
 	Repository(*api.RepositoryPayload) (api.Payloader, error)
 	Release(*api.ReleasePayload) (api.Payloader, error)
+	Wiki(*api.WikiPayload) (api.Payloader, error)
 }
 
 func convertPayloader(s PayloadConvertor, p api.Payloader, event webhook_model.HookEventType) (api.Payloader, error) {
@@ -51,6 +52,8 @@ func convertPayloader(s PayloadConvertor, p api.Payloader, event webhook_model.H
 		return s.Repository(p.(*api.RepositoryPayload))
 	case webhook_model.HookEventRelease:
 		return s.Release(p.(*api.ReleasePayload))
+	case webhook_model.HookEventWiki:
+		return s.Wiki(p.(*api.WikiPayload))
 	}
 	return s, nil
 }
diff --git a/services/webhook/slack.go b/services/webhook/slack.go
index e3d0d406d..63cc6f8ca 100644
--- a/services/webhook/slack.go
+++ b/services/webhook/slack.go
@@ -157,6 +157,13 @@ func (s *SlackPayload) IssueComment(p *api.IssueCommentPayload) (api.Payloader,
 	}}), nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (s *SlackPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, _, _ := getWikiPayloadInfo(p, SlackLinkFormatter, true)
+
+	return s.createPayload(text, nil), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (s *SlackPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	text, _ := getReleasePayloadInfo(p, SlackLinkFormatter, true)
diff --git a/services/webhook/slack_test.go b/services/webhook/slack_test.go
index 0f08785d2..3af38b515 100644
--- a/services/webhook/slack_test.go
+++ b/services/webhook/slack_test.go
@@ -145,6 +145,35 @@ func TestSlackPayload(t *testing.T) {
 		assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] Repository created by <https://try.gitea.io/user1|user1>", pl.(*SlackPayload).Text)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(SlackPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &SlackPayload{}, pl)
+
+		assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] New wiki page '<http://localhost:3000/test/repo/wiki/index|index>' (Wiki change comment) by <https://try.gitea.io/user1|user1>", pl.(*SlackPayload).Text)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &SlackPayload{}, pl)
+
+		assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] Wiki page '<http://localhost:3000/test/repo/wiki/index|index>' edited (Wiki change comment) by <https://try.gitea.io/user1|user1>", pl.(*SlackPayload).Text)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &SlackPayload{}, pl)
+
+		assert.Equal(t, "[<http://localhost:3000/test/repo|test/repo>] Wiki page '<http://localhost:3000/test/repo/wiki/index|index>' deleted by <https://try.gitea.io/user1|user1>", pl.(*SlackPayload).Text)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/telegram.go b/services/webhook/telegram.go
index 64211493e..13471d864 100644
--- a/services/webhook/telegram.go
+++ b/services/webhook/telegram.go
@@ -171,6 +171,13 @@ func (t *TelegramPayload) Repository(p *api.RepositoryPayload) (api.Payloader, e
 	return nil, nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (t *TelegramPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, _, _ := getWikiPayloadInfo(p, htmlLinkFormatter, true)
+
+	return createTelegramPayload(text), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (t *TelegramPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	text, _ := getReleasePayloadInfo(p, htmlLinkFormatter, true)
diff --git a/services/webhook/telegram_test.go b/services/webhook/telegram_test.go
index 2f8309016..5ca78d050 100644
--- a/services/webhook/telegram_test.go
+++ b/services/webhook/telegram_test.go
@@ -145,6 +145,35 @@ func TestTelegramPayload(t *testing.T) {
 		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Repository created`, pl.(*TelegramPayload).Message)
 	})
 
+	t.Run("Wiki", func(t *testing.T) {
+		p := wikiTestPayload()
+
+		d := new(TelegramPayload)
+		p.Action = api.HookWikiCreated
+		pl, err := d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &TelegramPayload{}, pl)
+
+		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] New wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*TelegramPayload).Message)
+
+		p.Action = api.HookWikiEdited
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &TelegramPayload{}, pl)
+
+		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' edited (Wiki change comment) by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*TelegramPayload).Message)
+
+		p.Action = api.HookWikiDeleted
+		pl, err = d.Wiki(p)
+		require.NoError(t, err)
+		require.NotNil(t, pl)
+		require.IsType(t, &TelegramPayload{}, pl)
+
+		assert.Equal(t, `[<a href="http://localhost:3000/test/repo">test/repo</a>] Wiki page '<a href="http://localhost:3000/test/repo/wiki/index">index</a>' deleted by <a href="https://try.gitea.io/user1">user1</a>`, pl.(*TelegramPayload).Message)
+	})
+
 	t.Run("Release", func(t *testing.T) {
 		p := pullReleaseTestPayload()
 
diff --git a/services/webhook/wechatwork.go b/services/webhook/wechatwork.go
index de8b77706..bd4c3e085 100644
--- a/services/webhook/wechatwork.go
+++ b/services/webhook/wechatwork.go
@@ -166,6 +166,13 @@ func (f *WechatworkPayload) Repository(p *api.RepositoryPayload) (api.Payloader,
 	return nil, nil
 }
 
+// Wiki implements PayloadConvertor Wiki method
+func (f *WechatworkPayload) Wiki(p *api.WikiPayload) (api.Payloader, error) {
+	text, _, _ := getWikiPayloadInfo(p, noneLinkFormatter, true)
+
+	return newWechatworkMarkdownPayload(text), nil
+}
+
 // Release implements PayloadConvertor Release method
 func (f *WechatworkPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
 	text, _ := getReleasePayloadInfo(p, noneLinkFormatter, true)
diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go
index ac5283bbe..b341b048c 100644
--- a/services/wiki/wiki.go
+++ b/services/wiki/wiki.go
@@ -118,7 +118,7 @@ func prepareWikiFileName(gitRepo *git.Repository, wikiName string) (bool, string
 	return foundEscaped, escaped, nil
 }
 
-// updateWikiPage adds a new page to the repository wiki.
+// updateWikiPage adds a new page or edits an existing page in repository wiki.
 func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, oldWikiName, newWikiName, content, message string, isNew bool) (err error) {
 	if err = nameAllowed(newWikiName); err != nil {
 		return err
diff --git a/templates/repo/settings/webhook/settings.tmpl b/templates/repo/settings/webhook/settings.tmpl
index 98a916dc1..57cf8a2f3 100644
--- a/templates/repo/settings/webhook/settings.tmpl
+++ b/templates/repo/settings/webhook/settings.tmpl
@@ -98,6 +98,17 @@
 			</div>
 		</div>
 
+		<!-- Wiki -->
+		<div class="seven wide column">
+			<div class="field">
+				<div class="ui checkbox">
+					<input class="hidden" name="wiki" type="checkbox" tabindex="0" {{if .Webhook.Wiki}}checked{{end}}>
+					<label>{{.i18n.Tr "repo.settings.event_wiki"}}</label>
+					<span class="help">{{.i18n.Tr "repo.settings.event_wiki_desc"}}</span>
+				</div>
+			</div>
+		</div>
+
 		<!-- Issue Events -->
 		<div class="fourteen wide column">
 			<label>{{.locale.Tr "repo.settings.event_header_issue"}}</label>
diff --git a/templates/repo/wiki/new.tmpl b/templates/repo/wiki/new.tmpl
index d3085a106..26c19c0a4 100644
--- a/templates/repo/wiki/new.tmpl
+++ b/templates/repo/wiki/new.tmpl
@@ -11,7 +11,7 @@
 				</div>
 			{{end}}
 		</div>
-		<form class="ui form" action="{{.Link}}" method="post">
+		<form class="ui form" action="{{.Link}}?action={{if .PageIsWikiEdit}}_edit{{else}}_new{{end}}" method="post">
 			{{.CsrfTokenHtml}}
 			<div class="field {{if .Err_Title}}error{{end}}">
 				<input name="title" value="{{.title}}" autofocus required>