diff --git a/models/issue.go b/models/issue.go
index 485be4baef..3986aeee15 100644
--- a/models/issue.go
+++ b/models/issue.go
@@ -381,6 +381,7 @@ func (issue *Issue) apiFormat(e Engine) *api.Issue {
 	apiIssue := &api.Issue{
 		ID:       issue.ID,
 		URL:      issue.APIURL(),
+		HTMLURL:  issue.HTMLURL(),
 		Index:    issue.Index,
 		Poster:   issue.Poster.APIFormat(),
 		Title:    issue.Title,
diff --git a/modules/structs/issue.go b/modules/structs/issue.go
index cc640edab0..49a7dc6d6f 100644
--- a/modules/structs/issue.go
+++ b/modules/structs/issue.go
@@ -38,6 +38,7 @@ type RepositoryMeta struct {
 type Issue struct {
 	ID               int64      `json:"id"`
 	URL              string     `json:"url"`
+	HTMLURL          string     `json:"html_url"`
 	Index            int64      `json:"number"`
 	Poster           *User      `json:"user"`
 	OriginalAuthor   string     `json:"original_author"`
diff --git a/modules/webhook/dingtalk.go b/modules/webhook/dingtalk.go
index 0d569f4120..fc99202a70 100644
--- a/modules/webhook/dingtalk.go
+++ b/modules/webhook/dingtalk.go
@@ -142,7 +142,7 @@ func getDingtalkIssuesPayload(p *api.IssuePayload) (*DingtalkPayload, error) {
 			Title:       issueTitle,
 			HideAvatar:  "0",
 			SingleTitle: "view issue",
-			SingleURL:   p.Issue.URL,
+			SingleURL:   p.Issue.HTMLURL,
 		},
 	}, nil
 }
diff --git a/modules/webhook/discord.go b/modules/webhook/discord.go
index c1e8421228..732821c183 100644
--- a/modules/webhook/discord.go
+++ b/modules/webhook/discord.go
@@ -236,7 +236,7 @@ func getDiscordIssuesPayload(p *api.IssuePayload, meta *DiscordMeta) (*DiscordPa
 			{
 				Title:       text,
 				Description: attachmentText,
-				URL:         p.Issue.URL,
+				URL:         p.Issue.HTMLURL,
 				Color:       color,
 				Author: DiscordEmbedAuthor{
 					Name:    p.Sender.UserName,
diff --git a/modules/webhook/msteams.go b/modules/webhook/msteams.go
index b47725209d..b9ceb5ee0b 100644
--- a/modules/webhook/msteams.go
+++ b/modules/webhook/msteams.go
@@ -299,7 +299,7 @@ func getMSTeamsIssuesPayload(p *api.IssuePayload) (*MSTeamsPayload, error) {
 				Targets: []MSTeamsActionTarget{
 					{
 						Os:  "default",
-						URI: p.Issue.URL,
+						URI: p.Issue.HTMLURL,
 					},
 				},
 			},
diff --git a/modules/webhook/slack.go b/modules/webhook/slack.go
index 11ad4c1b8b..74361509d8 100644
--- a/modules/webhook/slack.go
+++ b/modules/webhook/slack.go
@@ -158,7 +158,7 @@ func getSlackIssuesPayload(p *api.IssuePayload, slack *SlackMeta) (*SlackPayload
 		pl.Attachments = []SlackAttachment{{
 			Color:     fmt.Sprintf("%x", color),
 			Title:     issueTitle,
-			TitleLink: p.Issue.URL,
+			TitleLink: p.Issue.HTMLURL,
 			Text:      attachmentText,
 		}}
 	}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index d3e2ac6113..4e37f65d19 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -10305,6 +10305,10 @@
           "format": "date-time",
           "x-go-name": "Deadline"
         },
+        "html_url": {
+          "type": "string",
+          "x-go-name": "HTMLURL"
+        },
         "id": {
           "type": "integer",
           "format": "int64",