diff --git a/models/repo.go b/models/repo.go
index 7e38bbcdb7..3df850a3ba 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -322,11 +322,6 @@ func (repo *Repository) APIURL() string {
 	return setting.AppURL + path.Join("api/v1/repos", repo.FullName())
 }
 
-// APIFormat converts a Repository to api.Repository
-func (repo *Repository) APIFormat(mode AccessMode) *api.Repository {
-	return repo.innerAPIFormat(x, mode, false)
-}
-
 // GetCommitsCountCacheKey returns cache key used for commits count caching.
 func (repo *Repository) GetCommitsCountCacheKey(contextName string, isRef bool) string {
 	var prefix string
@@ -338,135 +333,6 @@ func (repo *Repository) GetCommitsCountCacheKey(contextName string, isRef bool)
 	return fmt.Sprintf("commits-count-%d-%s-%s", repo.ID, prefix, contextName)
 }
 
-func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) *api.Repository {
-	var parent *api.Repository
-
-	cloneLink := repo.cloneLink(false)
-	permission := &api.Permission{
-		Admin: mode >= AccessModeAdmin,
-		Push:  mode >= AccessModeWrite,
-		Pull:  mode >= AccessModeRead,
-	}
-	if !isParent {
-		err := repo.getBaseRepo(e)
-		if err != nil {
-			log.Error("APIFormat: %v", err)
-		}
-		if repo.BaseRepo != nil {
-			parent = repo.BaseRepo.innerAPIFormat(e, mode, true)
-		}
-	}
-
-	//check enabled/disabled units
-	hasIssues := false
-	var externalTracker *api.ExternalTracker
-	var internalTracker *api.InternalTracker
-	if unit, err := repo.getUnit(e, UnitTypeIssues); err == nil {
-		config := unit.IssuesConfig()
-		hasIssues = true
-		internalTracker = &api.InternalTracker{
-			EnableTimeTracker:                config.EnableTimetracker,
-			AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime,
-			EnableIssueDependencies:          config.EnableDependencies,
-		}
-	} else if unit, err := repo.getUnit(e, UnitTypeExternalTracker); err == nil {
-		config := unit.ExternalTrackerConfig()
-		hasIssues = true
-		externalTracker = &api.ExternalTracker{
-			ExternalTrackerURL:    config.ExternalTrackerURL,
-			ExternalTrackerFormat: config.ExternalTrackerFormat,
-			ExternalTrackerStyle:  config.ExternalTrackerStyle,
-		}
-	}
-	hasWiki := false
-	var externalWiki *api.ExternalWiki
-	if _, err := repo.getUnit(e, UnitTypeWiki); err == nil {
-		hasWiki = true
-	} else if unit, err := repo.getUnit(e, UnitTypeExternalWiki); err == nil {
-		hasWiki = true
-		config := unit.ExternalWikiConfig()
-		externalWiki = &api.ExternalWiki{
-			ExternalWikiURL: config.ExternalWikiURL,
-		}
-	}
-	hasPullRequests := false
-	ignoreWhitespaceConflicts := false
-	allowMerge := false
-	allowRebase := false
-	allowRebaseMerge := false
-	allowSquash := false
-	if unit, err := repo.getUnit(e, UnitTypePullRequests); err == nil {
-		config := unit.PullRequestsConfig()
-		hasPullRequests = true
-		ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts
-		allowMerge = config.AllowMerge
-		allowRebase = config.AllowRebase
-		allowRebaseMerge = config.AllowRebaseMerge
-		allowSquash = config.AllowSquash
-	}
-	hasProjects := false
-	if _, err := repo.getUnit(e, UnitTypeProjects); err == nil {
-		hasProjects = true
-	}
-
-	repo.mustOwner(e)
-
-	numReleases, _ := GetReleaseCountByRepoID(repo.ID, FindReleasesOptions{IncludeDrafts: false, IncludeTags: true})
-
-	return &api.Repository{
-		ID: repo.ID,
-		// TODO use convert.ToUser(repo.Owner)
-		Owner: &api.User{
-			ID:        repo.Owner.ID,
-			UserName:  repo.Owner.Name,
-			FullName:  repo.Owner.FullName,
-			Email:     repo.Owner.GetEmail(),
-			AvatarURL: repo.Owner.AvatarLink(),
-			LastLogin: repo.Owner.LastLoginUnix.AsTime(),
-			Created:   repo.Owner.CreatedUnix.AsTime(),
-		},
-		Name:                      repo.Name,
-		FullName:                  repo.FullName(),
-		Description:               repo.Description,
-		Private:                   repo.IsPrivate,
-		Template:                  repo.IsTemplate,
-		Empty:                     repo.IsEmpty,
-		Archived:                  repo.IsArchived,
-		Size:                      int(repo.Size / 1024),
-		Fork:                      repo.IsFork,
-		Parent:                    parent,
-		Mirror:                    repo.IsMirror,
-		HTMLURL:                   repo.HTMLURL(),
-		SSHURL:                    cloneLink.SSH,
-		CloneURL:                  cloneLink.HTTPS,
-		Website:                   repo.Website,
-		Stars:                     repo.NumStars,
-		Forks:                     repo.NumForks,
-		Watchers:                  repo.NumWatches,
-		OpenIssues:                repo.NumOpenIssues,
-		OpenPulls:                 repo.NumOpenPulls,
-		Releases:                  int(numReleases),
-		DefaultBranch:             repo.DefaultBranch,
-		Created:                   repo.CreatedUnix.AsTime(),
-		Updated:                   repo.UpdatedUnix.AsTime(),
-		Permissions:               permission,
-		HasIssues:                 hasIssues,
-		ExternalTracker:           externalTracker,
-		InternalTracker:           internalTracker,
-		HasWiki:                   hasWiki,
-		HasProjects:               hasProjects,
-		ExternalWiki:              externalWiki,
-		HasPullRequests:           hasPullRequests,
-		IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts,
-		AllowMerge:                allowMerge,
-		AllowRebase:               allowRebase,
-		AllowRebaseMerge:          allowRebaseMerge,
-		AllowSquash:               allowSquash,
-		AvatarURL:                 repo.avatarLink(e),
-		Internal:                  !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate,
-	}
-}
-
 func (repo *Repository) getUnits(e Engine) (err error) {
 	if repo.Units != nil {
 		return nil
diff --git a/modules/convert/notification.go b/modules/convert/notification.go
index 6934871844..fff891b15d 100644
--- a/modules/convert/notification.go
+++ b/modules/convert/notification.go
@@ -21,7 +21,7 @@ func ToNotificationThread(n *models.Notification) *api.NotificationThread {
 
 	//since user only get notifications when he has access to use minimal access mode
 	if n.Repository != nil {
-		result.Repository = n.Repository.APIFormat(models.AccessModeRead)
+		result.Repository = ToRepo(n.Repository, models.AccessModeRead)
 	}
 
 	//handle Subject
diff --git a/modules/convert/pull.go b/modules/convert/pull.go
index e522bee787..87eabcf53a 100644
--- a/modules/convert/pull.go
+++ b/modules/convert/pull.go
@@ -68,7 +68,7 @@ func ToAPIPullRequest(pr *models.PullRequest) *api.PullRequest {
 			Name:       pr.BaseBranch,
 			Ref:        pr.BaseBranch,
 			RepoID:     pr.BaseRepoID,
-			Repository: pr.BaseRepo.APIFormat(models.AccessModeNone),
+			Repository: ToRepo(pr.BaseRepo, models.AccessModeNone),
 		},
 		Head: &api.PRBranchInfo{
 			Name:   pr.HeadBranch,
@@ -97,7 +97,7 @@ func ToAPIPullRequest(pr *models.PullRequest) *api.PullRequest {
 
 	if pr.HeadRepo != nil {
 		apiPullRequest.Head.RepoID = pr.HeadRepo.ID
-		apiPullRequest.Head.Repository = pr.HeadRepo.APIFormat(models.AccessModeNone)
+		apiPullRequest.Head.Repository = ToRepo(pr.HeadRepo, models.AccessModeNone)
 
 		headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
 		if err != nil {
diff --git a/modules/convert/pull_test.go b/modules/convert/pull_test.go
index b78bbe87c9..adf42d8ca4 100644
--- a/modules/convert/pull_test.go
+++ b/modules/convert/pull_test.go
@@ -27,7 +27,7 @@ func TestPullRequest_APIFormat(t *testing.T) {
 		Ref:        "refs/pull/2/head",
 		Sha:        "4a357436d925b5c974181ff12a994538ddc5a269",
 		RepoID:     1,
-		Repository: headRepo.APIFormat(models.AccessModeNone),
+		Repository: ToRepo(headRepo, models.AccessModeNone),
 	}, apiPullRequest.Head)
 
 	//withOut HeadRepo
diff --git a/modules/convert/repository.go b/modules/convert/repository.go
new file mode 100644
index 0000000000..f2e10447f7
--- /dev/null
+++ b/modules/convert/repository.go
@@ -0,0 +1,137 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package convert
+
+import (
+	"code.gitea.io/gitea/models"
+	api "code.gitea.io/gitea/modules/structs"
+)
+
+// ToRepo converts a Repository to api.Repository
+func ToRepo(repo *models.Repository, mode models.AccessMode) *api.Repository {
+	return innerToRepo(repo, mode, false)
+}
+
+func innerToRepo(repo *models.Repository, mode models.AccessMode, isParent bool) *api.Repository {
+	var parent *api.Repository
+
+	cloneLink := repo.CloneLink()
+	permission := &api.Permission{
+		Admin: mode >= models.AccessModeAdmin,
+		Push:  mode >= models.AccessModeWrite,
+		Pull:  mode >= models.AccessModeRead,
+	}
+	if !isParent {
+		err := repo.GetBaseRepo()
+		if err != nil {
+			return nil
+		}
+		if repo.BaseRepo != nil {
+			parent = innerToRepo(repo.BaseRepo, mode, true)
+		}
+	}
+
+	//check enabled/disabled units
+	hasIssues := false
+	var externalTracker *api.ExternalTracker
+	var internalTracker *api.InternalTracker
+	if unit, err := repo.GetUnit(models.UnitTypeIssues); err == nil {
+		config := unit.IssuesConfig()
+		hasIssues = true
+		internalTracker = &api.InternalTracker{
+			EnableTimeTracker:                config.EnableTimetracker,
+			AllowOnlyContributorsToTrackTime: config.AllowOnlyContributorsToTrackTime,
+			EnableIssueDependencies:          config.EnableDependencies,
+		}
+	} else if unit, err := repo.GetUnit(models.UnitTypeExternalTracker); err == nil {
+		config := unit.ExternalTrackerConfig()
+		hasIssues = true
+		externalTracker = &api.ExternalTracker{
+			ExternalTrackerURL:    config.ExternalTrackerURL,
+			ExternalTrackerFormat: config.ExternalTrackerFormat,
+			ExternalTrackerStyle:  config.ExternalTrackerStyle,
+		}
+	}
+	hasWiki := false
+	var externalWiki *api.ExternalWiki
+	if _, err := repo.GetUnit(models.UnitTypeWiki); err == nil {
+		hasWiki = true
+	} else if unit, err := repo.GetUnit(models.UnitTypeExternalWiki); err == nil {
+		hasWiki = true
+		config := unit.ExternalWikiConfig()
+		externalWiki = &api.ExternalWiki{
+			ExternalWikiURL: config.ExternalWikiURL,
+		}
+	}
+	hasPullRequests := false
+	ignoreWhitespaceConflicts := false
+	allowMerge := false
+	allowRebase := false
+	allowRebaseMerge := false
+	allowSquash := false
+	if unit, err := repo.GetUnit(models.UnitTypePullRequests); err == nil {
+		config := unit.PullRequestsConfig()
+		hasPullRequests = true
+		ignoreWhitespaceConflicts = config.IgnoreWhitespaceConflicts
+		allowMerge = config.AllowMerge
+		allowRebase = config.AllowRebase
+		allowRebaseMerge = config.AllowRebaseMerge
+		allowSquash = config.AllowSquash
+	}
+	hasProjects := false
+	if _, err := repo.GetUnit(models.UnitTypeProjects); err == nil {
+		hasProjects = true
+	}
+
+	if err := repo.GetOwner(); err != nil {
+		return nil
+	}
+
+	numReleases, _ := models.GetReleaseCountByRepoID(repo.ID, models.FindReleasesOptions{IncludeDrafts: false, IncludeTags: true})
+
+	return &api.Repository{
+		ID:                        repo.ID,
+		Owner:                     ToUser(repo.Owner, mode != models.AccessModeNone, mode >= models.AccessModeAdmin),
+		Name:                      repo.Name,
+		FullName:                  repo.FullName(),
+		Description:               repo.Description,
+		Private:                   repo.IsPrivate,
+		Template:                  repo.IsTemplate,
+		Empty:                     repo.IsEmpty,
+		Archived:                  repo.IsArchived,
+		Size:                      int(repo.Size / 1024),
+		Fork:                      repo.IsFork,
+		Parent:                    parent,
+		Mirror:                    repo.IsMirror,
+		HTMLURL:                   repo.HTMLURL(),
+		SSHURL:                    cloneLink.SSH,
+		CloneURL:                  cloneLink.HTTPS,
+		Website:                   repo.Website,
+		Stars:                     repo.NumStars,
+		Forks:                     repo.NumForks,
+		Watchers:                  repo.NumWatches,
+		OpenIssues:                repo.NumOpenIssues,
+		OpenPulls:                 repo.NumOpenPulls,
+		Releases:                  int(numReleases),
+		DefaultBranch:             repo.DefaultBranch,
+		Created:                   repo.CreatedUnix.AsTime(),
+		Updated:                   repo.UpdatedUnix.AsTime(),
+		Permissions:               permission,
+		HasIssues:                 hasIssues,
+		ExternalTracker:           externalTracker,
+		InternalTracker:           internalTracker,
+		HasWiki:                   hasWiki,
+		HasProjects:               hasProjects,
+		ExternalWiki:              externalWiki,
+		HasPullRequests:           hasPullRequests,
+		IgnoreWhitespaceConflicts: ignoreWhitespaceConflicts,
+		AllowMerge:                allowMerge,
+		AllowRebase:               allowRebase,
+		AllowRebaseMerge:          allowRebaseMerge,
+		AllowSquash:               allowSquash,
+		AvatarURL:                 repo.AvatarLink(),
+		Internal:                  !repo.IsPrivate && repo.Owner.Visibility == api.VisibleTypePrivate,
+	}
+}
diff --git a/modules/notification/webhook/webhook.go b/modules/notification/webhook/webhook.go
index bc21fb6113..4c9c213f18 100644
--- a/modules/notification/webhook/webhook.go
+++ b/modules/notification/webhook/webhook.go
@@ -52,7 +52,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *model
 			Action:      api.HookIssueLabelCleared,
 			Index:       issue.Index,
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(mode),
+			Repository:  convert.ToRepo(issue.Repo, mode),
 			Sender:      convert.ToUser(doer, false, false),
 		})
 	} else {
@@ -60,7 +60,7 @@ func (m *webhookNotifier) NotifyIssueClearLabels(doer *models.User, issue *model
 			Action:     api.HookIssueLabelCleared,
 			Index:      issue.Index,
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 		})
 	}
@@ -75,8 +75,8 @@ func (m *webhookNotifier) NotifyForkRepository(doer *models.User, oldRepo, repo
 
 	// forked webhook
 	if err := webhook_module.PrepareWebhooks(oldRepo, models.HookEventFork, &api.ForkPayload{
-		Forkee: oldRepo.APIFormat(oldMode),
-		Repo:   repo.APIFormat(mode),
+		Forkee: convert.ToRepo(oldRepo, oldMode),
+		Repo:   convert.ToRepo(repo, mode),
 		Sender: convert.ToUser(doer, false, false),
 	}); err != nil {
 		log.Error("PrepareWebhooks [repo_id: %d]: %v", oldRepo.ID, err)
@@ -88,7 +88,7 @@ func (m *webhookNotifier) NotifyForkRepository(doer *models.User, oldRepo, repo
 	if u.IsOrganization() {
 		if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
 			Action:       api.HookRepoCreated,
-			Repository:   repo.APIFormat(models.AccessModeOwner),
+			Repository:   convert.ToRepo(repo, models.AccessModeOwner),
 			Organization: convert.ToUser(u, false, false),
 			Sender:       convert.ToUser(doer, false, false),
 		}); err != nil {
@@ -101,7 +101,7 @@ func (m *webhookNotifier) NotifyCreateRepository(doer *models.User, u *models.Us
 	// Add to hook queue for created repo after session commit.
 	if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
 		Action:       api.HookRepoCreated,
-		Repository:   repo.APIFormat(models.AccessModeOwner),
+		Repository:   convert.ToRepo(repo, models.AccessModeOwner),
 		Organization: convert.ToUser(u, false, false),
 		Sender:       convert.ToUser(doer, false, false),
 	}); err != nil {
@@ -114,7 +114,7 @@ func (m *webhookNotifier) NotifyDeleteRepository(doer *models.User, repo *models
 
 	if err := webhook_module.PrepareWebhooks(repo, models.HookEventRepository, &api.RepositoryPayload{
 		Action:       api.HookRepoDeleted,
-		Repository:   repo.APIFormat(models.AccessModeOwner),
+		Repository:   convert.ToRepo(repo, models.AccessModeOwner),
 		Organization: convert.ToUser(u, false, false),
 		Sender:       convert.ToUser(doer, false, false),
 	}); err != nil {
@@ -134,7 +134,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *mo
 		apiPullRequest := &api.PullRequestPayload{
 			Index:       issue.Index,
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(mode),
+			Repository:  convert.ToRepo(issue.Repo, mode),
 			Sender:      convert.ToUser(doer, false, false),
 		}
 		if removed {
@@ -152,7 +152,7 @@ func (m *webhookNotifier) NotifyIssueChangeAssignee(doer *models.User, issue *mo
 		apiIssue := &api.IssuePayload{
 			Index:      issue.Index,
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 		}
 		if removed {
@@ -186,7 +186,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *models.User, issue *model
 				},
 			},
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(mode),
+			Repository:  convert.ToRepo(issue.Repo, mode),
 			Sender:      convert.ToUser(doer, false, false),
 		})
 	} else {
@@ -199,7 +199,7 @@ func (m *webhookNotifier) NotifyIssueChangeTitle(doer *models.User, issue *model
 				},
 			},
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(issue.Poster, false, false),
 		})
 	}
@@ -221,7 +221,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *models.User, issue *mode
 		apiPullRequest := &api.PullRequestPayload{
 			Index:       issue.Index,
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(mode),
+			Repository:  convert.ToRepo(issue.Repo, mode),
 			Sender:      convert.ToUser(doer, false, false),
 		}
 		if isClosed {
@@ -234,7 +234,7 @@ func (m *webhookNotifier) NotifyIssueChangeStatus(doer *models.User, issue *mode
 		apiIssue := &api.IssuePayload{
 			Index:      issue.Index,
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 		}
 		if isClosed {
@@ -264,7 +264,7 @@ func (m *webhookNotifier) NotifyNewIssue(issue *models.Issue) {
 		Action:     api.HookIssueOpened,
 		Index:      issue.Index,
 		Issue:      convert.ToAPIIssue(issue),
-		Repository: issue.Repo.APIFormat(mode),
+		Repository: convert.ToRepo(issue.Repo, mode),
 		Sender:     convert.ToUser(issue.Poster, false, false),
 	}); err != nil {
 		log.Error("PrepareWebhooks: %v", err)
@@ -290,7 +290,7 @@ func (m *webhookNotifier) NotifyNewPullRequest(pull *models.PullRequest) {
 		Action:      api.HookIssueOpened,
 		Index:       pull.Issue.Index,
 		PullRequest: convert.ToAPIPullRequest(pull),
-		Repository:  pull.Issue.Repo.APIFormat(mode),
+		Repository:  convert.ToRepo(pull.Issue.Repo, mode),
 		Sender:      convert.ToUser(pull.Issue.Poster, false, false),
 	}); err != nil {
 		log.Error("PrepareWebhooks: %v", err)
@@ -311,7 +311,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *mod
 				},
 			},
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(mode),
+			Repository:  convert.ToRepo(issue.Repo, mode),
 			Sender:      convert.ToUser(doer, false, false),
 		})
 	} else {
@@ -324,7 +324,7 @@ func (m *webhookNotifier) NotifyIssueChangeContent(doer *models.User, issue *mod
 				},
 			},
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 		})
 	}
@@ -361,7 +361,7 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comme
 					From: oldContent,
 				},
 			},
-			Repository: c.Issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(c.Issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 			IsPull:     true,
 		})
@@ -375,7 +375,7 @@ func (m *webhookNotifier) NotifyUpdateComment(doer *models.User, c *models.Comme
 					From: oldContent,
 				},
 			},
-			Repository: c.Issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(c.Issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 			IsPull:     false,
 		})
@@ -396,7 +396,7 @@ func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *mode
 			Action:     api.HookIssueCommentCreated,
 			Issue:      convert.ToAPIIssue(issue),
 			Comment:    convert.ToComment(comment),
-			Repository: repo.APIFormat(mode),
+			Repository: convert.ToRepo(repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 			IsPull:     true,
 		})
@@ -405,7 +405,7 @@ func (m *webhookNotifier) NotifyCreateIssueComment(doer *models.User, repo *mode
 			Action:     api.HookIssueCommentCreated,
 			Issue:      convert.ToAPIIssue(issue),
 			Comment:    convert.ToComment(comment),
-			Repository: repo.APIFormat(mode),
+			Repository: convert.ToRepo(repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 			IsPull:     false,
 		})
@@ -440,7 +440,7 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models
 			Action:     api.HookIssueCommentDeleted,
 			Issue:      convert.ToAPIIssue(comment.Issue),
 			Comment:    convert.ToComment(comment),
-			Repository: comment.Issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(comment.Issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 			IsPull:     true,
 		})
@@ -449,7 +449,7 @@ func (m *webhookNotifier) NotifyDeleteComment(doer *models.User, comment *models
 			Action:     api.HookIssueCommentDeleted,
 			Issue:      convert.ToAPIIssue(comment.Issue),
 			Comment:    convert.ToComment(comment),
-			Repository: comment.Issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(comment.Issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 			IsPull:     false,
 		})
@@ -489,7 +489,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *mode
 			Action:      api.HookIssueLabelUpdated,
 			Index:       issue.Index,
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(models.AccessModeNone),
+			Repository:  convert.ToRepo(issue.Repo, models.AccessModeNone),
 			Sender:      convert.ToUser(doer, false, false),
 		})
 	} else {
@@ -497,7 +497,7 @@ func (m *webhookNotifier) NotifyIssueChangeLabels(doer *models.User, issue *mode
 			Action:     api.HookIssueLabelUpdated,
 			Index:      issue.Index,
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 		})
 	}
@@ -531,7 +531,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *m
 			Action:      hookAction,
 			Index:       issue.Index,
 			PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-			Repository:  issue.Repo.APIFormat(mode),
+			Repository:  convert.ToRepo(issue.Repo, mode),
 			Sender:      convert.ToUser(doer, false, false),
 		})
 	} else {
@@ -539,7 +539,7 @@ func (m *webhookNotifier) NotifyIssueChangeMilestone(doer *models.User, issue *m
 			Action:     hookAction,
 			Index:      issue.Index,
 			Issue:      convert.ToAPIIssue(issue),
-			Repository: issue.Repo.APIFormat(mode),
+			Repository: convert.ToRepo(issue.Repo, mode),
 			Sender:     convert.ToUser(doer, false, false),
 		})
 	}
@@ -562,7 +562,7 @@ func (m *webhookNotifier) NotifyPushCommits(pusher *models.User, repo *models.Re
 		After:      opts.NewCommitID,
 		CompareURL: setting.AppURL + commits.CompareURL,
 		Commits:    apiCommits,
-		Repo:       repo.APIFormat(models.AccessModeOwner),
+		Repo:       convert.ToRepo(repo, models.AccessModeOwner),
 		Pusher:     apiPusher,
 		Sender:     apiPusher,
 	}); err != nil {
@@ -597,7 +597,7 @@ func (*webhookNotifier) NotifyMergePullRequest(pr *models.PullRequest, doer *mod
 	apiPullRequest := &api.PullRequestPayload{
 		Index:       pr.Issue.Index,
 		PullRequest: convert.ToAPIPullRequest(pr),
-		Repository:  pr.Issue.Repo.APIFormat(mode),
+		Repository:  convert.ToRepo(pr.Issue.Repo, mode),
 		Sender:      convert.ToUser(doer, false, false),
 		Action:      api.HookIssueClosed,
 	}
@@ -630,7 +630,7 @@ func (m *webhookNotifier) NotifyPullRequestChangeTargetBranch(doer *models.User,
 			},
 		},
 		PullRequest: convert.ToAPIPullRequest(issue.PullRequest),
-		Repository:  issue.Repo.APIFormat(mode),
+		Repository:  convert.ToRepo(issue.Repo, mode),
 		Sender:      convert.ToUser(doer, false, false),
 	})
 
@@ -669,7 +669,7 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *models.PullRequest, review
 		Action:      api.HookIssueReviewed,
 		Index:       review.Issue.Index,
 		PullRequest: convert.ToAPIPullRequest(pr),
-		Repository:  review.Issue.Repo.APIFormat(mode),
+		Repository:  convert.ToRepo(review.Issue.Repo, mode),
 		Sender:      convert.ToUser(review.Reviewer, false, false),
 		Review: &api.ReviewPayload{
 			Type:    string(reviewHookType),
@@ -682,7 +682,7 @@ func (m *webhookNotifier) NotifyPullRequestReview(pr *models.PullRequest, review
 
 func (m *webhookNotifier) NotifyCreateRef(pusher *models.User, repo *models.Repository, refType, refFullName string) {
 	apiPusher := convert.ToUser(pusher, false, false)
-	apiRepo := repo.APIFormat(models.AccessModeNone)
+	apiRepo := convert.ToRepo(repo, models.AccessModeNone)
 	refName := git.RefEndName(refFullName)
 
 	gitRepo, err := git.OpenRepository(repo.RepoPath())
@@ -724,7 +724,7 @@ func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *models.User, pr *m
 		Action:      api.HookIssueSynchronized,
 		Index:       pr.Issue.Index,
 		PullRequest: convert.ToAPIPullRequest(pr),
-		Repository:  pr.Issue.Repo.APIFormat(models.AccessModeNone),
+		Repository:  convert.ToRepo(pr.Issue.Repo, models.AccessModeNone),
 		Sender:      convert.ToUser(doer, false, false),
 	}); err != nil {
 		log.Error("PrepareWebhooks [pull_id: %v]: %v", pr.ID, err)
@@ -733,7 +733,7 @@ func (m *webhookNotifier) NotifyPullRequestSynchronized(doer *models.User, pr *m
 
 func (m *webhookNotifier) NotifyDeleteRef(pusher *models.User, repo *models.Repository, refType, refFullName string) {
 	apiPusher := convert.ToUser(pusher, false, false)
-	apiRepo := repo.APIFormat(models.AccessModeNone)
+	apiRepo := convert.ToRepo(repo, models.AccessModeNone)
 	refName := git.RefEndName(refFullName)
 
 	if err := webhook_module.PrepareWebhooks(repo, models.HookEventDelete, &api.DeletePayload{
@@ -757,7 +757,7 @@ func sendReleaseHook(doer *models.User, rel *models.Release, action api.HookRele
 	if err := webhook_module.PrepareWebhooks(rel.Repo, models.HookEventRelease, &api.ReleasePayload{
 		Action:     action,
 		Release:    convert.ToRelease(rel),
-		Repository: rel.Repo.APIFormat(mode),
+		Repository: convert.ToRepo(rel.Repo, mode),
 		Sender:     convert.ToUser(rel.Publisher, false, false),
 	}); err != nil {
 		log.Error("PrepareWebhooks: %v", err)
@@ -790,7 +790,7 @@ func (m *webhookNotifier) NotifySyncPushCommits(pusher *models.User, repo *model
 		After:      opts.NewCommitID,
 		CompareURL: setting.AppURL + commits.CompareURL,
 		Commits:    apiCommits,
-		Repo:       repo.APIFormat(models.AccessModeOwner),
+		Repo:       convert.ToRepo(repo, models.AccessModeOwner),
 		Pusher:     apiPusher,
 		Sender:     apiPusher,
 	}); err != nil {
diff --git a/routers/api/v1/org/team.go b/routers/api/v1/org/team.go
index 443784fb8b..72387dcbf7 100644
--- a/routers/api/v1/org/team.go
+++ b/routers/api/v1/org/team.go
@@ -492,7 +492,7 @@ func GetTeamRepos(ctx *context.APIContext) {
 			ctx.Error(http.StatusInternalServerError, "GetTeamRepos", err)
 			return
 		}
-		repos[i] = repo.APIFormat(access)
+		repos[i] = convert.ToRepo(repo, access)
 	}
 	ctx.JSON(http.StatusOK, repos)
 }
diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go
index e6f5f5e630..24700f7a7f 100644
--- a/routers/api/v1/repo/fork.go
+++ b/routers/api/v1/repo/fork.go
@@ -11,6 +11,7 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/routers/api/v1/utils"
 	repo_service "code.gitea.io/gitea/services/repository"
@@ -58,7 +59,7 @@ func ListForks(ctx *context.APIContext) {
 			ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 			return
 		}
-		apiForks[i] = fork.APIFormat(access)
+		apiForks[i] = convert.ToRepo(fork, access)
 	}
 	ctx.JSON(http.StatusOK, apiForks)
 }
@@ -125,5 +126,5 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) {
 	}
 
 	//TODO change back to 201
-	ctx.JSON(http.StatusAccepted, fork.APIFormat(models.AccessModeOwner))
+	ctx.JSON(http.StatusAccepted, convert.ToRepo(fork, models.AccessModeOwner))
 }
diff --git a/routers/api/v1/repo/hook.go b/routers/api/v1/repo/hook.go
index 1a38fc3018..fc8b33a7ca 100644
--- a/routers/api/v1/repo/hook.go
+++ b/routers/api/v1/repo/hook.go
@@ -146,7 +146,7 @@ func TestHook(ctx *context.APIContext) {
 		Commits: []*api.PayloadCommit{
 			convert.ToPayloadCommit(ctx.Repo.Repository, ctx.Repo.Commit),
 		},
-		Repo:   ctx.Repo.Repository.APIFormat(models.AccessModeNone),
+		Repo:   convert.ToRepo(ctx.Repo.Repository, models.AccessModeNone),
 		Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false),
 		Sender: convert.ToUser(ctx.User, ctx.IsSigned, false),
 	}); err != nil {
diff --git a/routers/api/v1/repo/key.go b/routers/api/v1/repo/key.go
index 3d16ae6d40..3e6174f621 100644
--- a/routers/api/v1/repo/key.go
+++ b/routers/api/v1/repo/key.go
@@ -21,13 +21,13 @@ import (
 func appendPrivateInformation(apiKey *api.DeployKey, key *models.DeployKey, repository *models.Repository) (*api.DeployKey, error) {
 	apiKey.ReadOnly = key.Mode == models.AccessModeRead
 	if repository.ID == key.RepoID {
-		apiKey.Repository = repository.APIFormat(key.Mode)
+		apiKey.Repository = convert.ToRepo(repository, key.Mode)
 	} else {
 		repo, err := models.GetRepositoryByID(key.RepoID)
 		if err != nil {
 			return apiKey, err
 		}
-		apiKey.Repository = repo.APIFormat(key.Mode)
+		apiKey.Repository = convert.ToRepo(repo, key.Mode)
 	}
 	return apiKey, nil
 }
diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go
index 68ab7e4897..511e91f94e 100644
--- a/routers/api/v1/repo/migrate.go
+++ b/routers/api/v1/repo/migrate.go
@@ -191,7 +191,7 @@ func Migrate(ctx *context.APIContext, form api.MigrateRepoOptions) {
 	}
 
 	log.Trace("Repository migrated: %s/%s", repoOwner.Name, form.RepoName)
-	ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeAdmin))
+	ctx.JSON(http.StatusCreated, convert.ToRepo(repo, models.AccessModeAdmin))
 }
 
 func handleMigrateError(ctx *context.APIContext, repoOwner *models.User, remoteAddr string, err error) {
diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go
index 116e413125..048f7d6b1f 100644
--- a/routers/api/v1/repo/repo.go
+++ b/routers/api/v1/repo/repo.go
@@ -12,6 +12,7 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/convert"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
@@ -217,7 +218,7 @@ func Search(ctx *context.APIContext) {
 				Error: err.Error(),
 			})
 		}
-		results[i] = repo.APIFormat(accessMode)
+		results[i] = convert.ToRepo(repo, accessMode)
 	}
 
 	ctx.SetLinkHeader(int(count), opts.PageSize)
@@ -265,7 +266,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR
 		ctx.Error(http.StatusInternalServerError, "GetRepositoryByID", err)
 	}
 
-	ctx.JSON(http.StatusCreated, repo.APIFormat(models.AccessModeOwner))
+	ctx.JSON(http.StatusCreated, convert.ToRepo(repo, models.AccessModeOwner))
 }
 
 // Create one repository of mine
@@ -406,7 +407,7 @@ func Get(ctx *context.APIContext) {
 	//   "200":
 	//     "$ref": "#/responses/Repository"
 
-	ctx.JSON(http.StatusOK, ctx.Repo.Repository.APIFormat(ctx.Repo.AccessMode))
+	ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode))
 }
 
 // GetByID returns a single Repository
@@ -445,7 +446,7 @@ func GetByID(ctx *context.APIContext) {
 		ctx.NotFound()
 		return
 	}
-	ctx.JSON(http.StatusOK, repo.APIFormat(perm.AccessMode))
+	ctx.JSON(http.StatusOK, convert.ToRepo(repo, perm.AccessMode))
 }
 
 // Edit edit repository properties
@@ -494,7 +495,7 @@ func Edit(ctx *context.APIContext, opts api.EditRepoOption) {
 		}
 	}
 
-	ctx.JSON(http.StatusOK, ctx.Repo.Repository.APIFormat(ctx.Repo.AccessMode))
+	ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode))
 }
 
 // updateBasicProperties updates the basic properties of a repo: Name, Description, Website and Visibility
diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go
index e7318edaa5..3b6d9b04c1 100644
--- a/routers/api/v1/repo/status.go
+++ b/routers/api/v1/repo/status.go
@@ -300,7 +300,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
 	retStatus := &combinedCommitStatus{
 		SHA:        sha,
 		TotalCount: len(statuses),
-		Repo:       repo.APIFormat(ctx.Repo.AccessMode),
+		Repo:       convert.ToRepo(repo, ctx.Repo.AccessMode),
 		URL:        "",
 	}
 
diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go
index b1271b7721..a0999a6ce2 100644
--- a/routers/api/v1/repo/transfer.go
+++ b/routers/api/v1/repo/transfer.go
@@ -105,5 +105,5 @@ func Transfer(ctx *context.APIContext, opts api.TransferRepoOption) {
 	}
 
 	log.Trace("Repository transferred: %s -> %s", ctx.Repo.Repository.FullName(), newOwner.Name)
-	ctx.JSON(http.StatusAccepted, newRepo.APIFormat(models.AccessModeAdmin))
+	ctx.JSON(http.StatusAccepted, convert.ToRepo(newRepo, models.AccessModeAdmin))
 }
diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go
index ae5e319c27..b17841e67a 100644
--- a/routers/api/v1/user/repo.go
+++ b/routers/api/v1/user/repo.go
@@ -10,6 +10,7 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/routers/api/v1/utils"
 )
@@ -37,7 +38,7 @@ func listUserRepos(ctx *context.APIContext, u *models.User, private bool) {
 			return
 		}
 		if ctx.IsSigned && ctx.User.IsAdmin || access >= models.AccessModeRead {
-			apiRepos = append(apiRepos, repos[i].APIFormat(access))
+			apiRepos = append(apiRepos, convert.ToRepo(repos[i], access))
 		}
 	}
 
@@ -125,7 +126,7 @@ func ListMyRepos(ctx *context.APIContext) {
 		if err != nil {
 			ctx.Error(http.StatusInternalServerError, "AccessLevel", err)
 		}
-		results[i] = repo.APIFormat(accessMode)
+		results[i] = convert.ToRepo(repo, accessMode)
 	}
 
 	ctx.SetLinkHeader(int(count), opts.ListOptions.PageSize)
diff --git a/routers/api/v1/user/star.go b/routers/api/v1/user/star.go
index 1fc1005810..937dcb477f 100644
--- a/routers/api/v1/user/star.go
+++ b/routers/api/v1/user/star.go
@@ -10,6 +10,7 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/routers/api/v1/utils"
 )
@@ -28,7 +29,7 @@ func getStarredRepos(user *models.User, private bool, listOptions models.ListOpt
 		if err != nil {
 			return nil, err
 		}
-		repos[i] = starred.APIFormat(access)
+		repos[i] = convert.ToRepo(starred, access)
 	}
 	return repos, nil
 }
diff --git a/routers/api/v1/user/watch.go b/routers/api/v1/user/watch.go
index 9ad8682f5f..ab656f3229 100644
--- a/routers/api/v1/user/watch.go
+++ b/routers/api/v1/user/watch.go
@@ -9,6 +9,7 @@ import (
 
 	"code.gitea.io/gitea/models"
 	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/convert"
 	api "code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/routers/api/v1/utils"
 )
@@ -27,7 +28,7 @@ func getWatchedRepos(user *models.User, private bool, listOptions models.ListOpt
 		if err != nil {
 			return nil, err
 		}
-		repos[i] = watched.APIFormat(access)
+		repos[i] = convert.ToRepo(watched, access)
 	}
 	return repos, nil
 }
diff --git a/routers/repo/webhook.go b/routers/repo/webhook.go
index 13b95c8076..f9f9e94a2b 100644
--- a/routers/repo/webhook.go
+++ b/routers/repo/webhook.go
@@ -1073,7 +1073,7 @@ func TestWebhook(ctx *context.Context) {
 				},
 			},
 		},
-		Repo:   ctx.Repo.Repository.APIFormat(models.AccessModeNone),
+		Repo:   convert.ToRepo(ctx.Repo.Repository, models.AccessModeNone),
 		Pusher: apiUser,
 		Sender: apiUser,
 	}