diff --git a/models/list_options.go b/models/list_options.go
index 62c0944cc8..0912355352 100644
--- a/models/list_options.go
+++ b/models/list_options.go
@@ -37,6 +37,14 @@ func (opts ListOptions) setEnginePagination(e Engine) Engine {
 	return e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
 }
 
+// GetStartEnd returns the start and end of the ListOptions
+func (opts ListOptions) GetStartEnd() (start, end int) {
+	opts.setDefaultValues()
+	start = (opts.Page - 1) * opts.PageSize
+	end = start + opts.Page
+	return
+}
+
 func (opts ListOptions) setDefaultValues() {
 	if opts.PageSize <= 0 {
 		opts.PageSize = setting.API.DefaultPagingNum
diff --git a/modules/structs/cron.go b/modules/structs/cron.go
new file mode 100644
index 0000000000..f52a5ed3c9
--- /dev/null
+++ b/modules/structs/cron.go
@@ -0,0 +1,16 @@
+// 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 structs
+
+import "time"
+
+// Cron represents a Cron task
+type Cron struct {
+	Name      string    `json:"name"`
+	Schedule  string    `json:"schedule"`
+	Next      time.Time `json:"next"`
+	Prev      time.Time `json:"prev"`
+	ExecTimes int64     `json:"exec_times"`
+}
diff --git a/routers/api/v1/admin/cron.go b/routers/api/v1/admin/cron.go
new file mode 100644
index 0000000000..2531346fcb
--- /dev/null
+++ b/routers/api/v1/admin/cron.go
@@ -0,0 +1,86 @@
+// 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 admin
+
+import (
+	"net/http"
+
+	"code.gitea.io/gitea/modules/context"
+	"code.gitea.io/gitea/modules/cron"
+	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/structs"
+	"code.gitea.io/gitea/routers/api/v1/utils"
+)
+
+// ListCronTasks api for getting cron tasks
+func ListCronTasks(ctx *context.APIContext) {
+	// swagger:operation GET /admin/cron admin adminCronList
+	// ---
+	// summary: List cron tasks
+	// produces:
+	// - application/json
+	// parameters:
+	// - name: page
+	//   in: query
+	//   description: page number of results to return (1-based)
+	//   type: integer
+	// - name: limit
+	//   in: query
+	//   description: page size of results
+	//   type: integer
+	// responses:
+	//   "200":
+	//     "$ref": "#/responses/CronList"
+	//   "403":
+	//     "$ref": "#/responses/forbidden"
+	tasks := cron.ListTasks()
+	listOpts := utils.GetListOptions(ctx)
+	start, end := listOpts.GetStartEnd()
+
+	if len(tasks) > listOpts.PageSize {
+		tasks = tasks[start:end]
+	}
+
+	res := make([]structs.Cron, len(tasks))
+	for i, task := range tasks {
+		res[i] = structs.Cron{
+			Name:      task.Name,
+			Schedule:  task.Spec,
+			Next:      task.Next,
+			Prev:      task.Prev,
+			ExecTimes: task.ExecTimes,
+		}
+	}
+	ctx.JSON(http.StatusOK, res)
+}
+
+// PostCronTask api for getting cron tasks
+func PostCronTask(ctx *context.APIContext) {
+	// swagger:operation POST /admin/cron/{task} admin adminCronRun
+	// ---
+	// summary: Run cron task
+	// produces:
+	// - application/json
+	// parameters:
+	// - name: task
+	//   in: path
+	//   description: task to run
+	//   type: string
+	//   required: true
+	// responses:
+	//   "204":
+	//     "$ref": "#/responses/empty"
+	//   "404":
+	//     "$ref": "#/responses/notFound"
+	task := cron.GetTask(ctx.Params(":task"))
+	if task == nil {
+		ctx.NotFound()
+		return
+	}
+	task.Run()
+	log.Trace("Cron Task %s started by admin(%s)", task.Name, ctx.User.Name)
+
+	ctx.Status(http.StatusNoContent)
+}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 506e6a3ec0..ab7ef6d6f7 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -934,6 +934,10 @@ func RegisterRoutes(m *macaron.Macaron) {
 		})
 
 		m.Group("/admin", func() {
+			m.Group("/cron", func() {
+				m.Get("", admin.ListCronTasks)
+				m.Post("/:task", admin.PostCronTask)
+			})
 			m.Get("/orgs", admin.GetAllOrgs)
 			m.Group("/users", func() {
 				m.Get("", admin.GetAllUsers)
diff --git a/routers/api/v1/swagger/cron.go b/routers/api/v1/swagger/cron.go
new file mode 100644
index 0000000000..85f2ed0e35
--- /dev/null
+++ b/routers/api/v1/swagger/cron.go
@@ -0,0 +1,16 @@
+// 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 swagger
+
+import (
+	api "code.gitea.io/gitea/modules/structs"
+)
+
+// CronList
+// swagger:response CronList
+type swaggerResponseCronList struct {
+	// in:body
+	Body []api.Cron `json:"body"`
+}
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index ec4570b488..d9c8aeb87d 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -23,6 +23,69 @@
   },
   "basePath": "{{AppSubUrl}}/api/v1",
   "paths": {
+    "/admin/cron": {
+      "get": {
+        "produces": [
+          "application/json"
+        ],
+        "tags": [
+          "admin"
+        ],
+        "summary": "List cron tasks",
+        "operationId": "adminCronList",
+        "parameters": [
+          {
+            "type": "integer",
+            "description": "page number of results to return (1-based)",
+            "name": "page",
+            "in": "query"
+          },
+          {
+            "type": "integer",
+            "description": "page size of results",
+            "name": "limit",
+            "in": "query"
+          }
+        ],
+        "responses": {
+          "200": {
+            "$ref": "#/responses/CronList"
+          },
+          "403": {
+            "$ref": "#/responses/forbidden"
+          }
+        }
+      }
+    },
+    "/admin/cron/{task}": {
+      "post": {
+        "produces": [
+          "application/json"
+        ],
+        "tags": [
+          "admin"
+        ],
+        "summary": "Run cron task",
+        "operationId": "adminCronRun",
+        "parameters": [
+          {
+            "type": "string",
+            "description": "task to run",
+            "name": "task",
+            "in": "path",
+            "required": true
+          }
+        ],
+        "responses": {
+          "204": {
+            "$ref": "#/responses/empty"
+          },
+          "404": {
+            "$ref": "#/responses/notFound"
+          }
+        }
+      }
+    },
     "/admin/orgs": {
       "get": {
         "produces": [
@@ -11931,6 +11994,36 @@
       },
       "x-go-package": "code.gitea.io/gitea/modules/structs"
     },
+    "Cron": {
+      "description": "Cron represents a Cron task",
+      "type": "object",
+      "properties": {
+        "exec_times": {
+          "type": "integer",
+          "format": "int64",
+          "x-go-name": "ExecTimes"
+        },
+        "name": {
+          "type": "string",
+          "x-go-name": "Name"
+        },
+        "next": {
+          "type": "string",
+          "format": "date-time",
+          "x-go-name": "Next"
+        },
+        "prev": {
+          "type": "string",
+          "format": "date-time",
+          "x-go-name": "Prev"
+        },
+        "schedule": {
+          "type": "string",
+          "x-go-name": "Schedule"
+        }
+      },
+      "x-go-package": "code.gitea.io/gitea/modules/structs"
+    },
     "DeleteEmailOption": {
       "description": "DeleteEmailOption options when deleting email addresses",
       "type": "object",
@@ -15027,6 +15120,15 @@
         "$ref": "#/definitions/ContentsResponse"
       }
     },
+    "CronList": {
+      "description": "CronList",
+      "schema": {
+        "type": "array",
+        "items": {
+          "$ref": "#/definitions/Cron"
+        }
+      }
+    },
     "DeployKey": {
       "description": "DeployKey",
       "schema": {