diff --git a/integrations/api_issue_test.go b/integrations/api_issue_test.go
new file mode 100644
index 000000000..63dd9459b
--- /dev/null
+++ b/integrations/api_issue_test.go
@@ -0,0 +1,65 @@
+// Copyright 2017 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 integrations
+
+import (
+	"net/http"
+	"testing"
+
+	"code.gitea.io/gitea/models"
+	api "code.gitea.io/sdk/gitea"
+
+	"fmt"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestAPIListIssues(t *testing.T) {
+	prepareTestEnv(t)
+
+	repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
+	owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
+
+	session := loginUser(t, owner.Name)
+	req := NewRequestf(t, "GET", "/api/v1/repos/%s/%s/issues?state=all",
+		owner.Name, repo.Name)
+	resp := session.MakeRequest(t, req)
+	assert.EqualValues(t, http.StatusOK, resp.HeaderCode)
+	var apiIssues []*api.Issue
+	DecodeJSON(t, resp, &apiIssues)
+	assert.Len(t, apiIssues, models.GetCount(t, &models.Issue{RepoID: repo.ID}))
+	for _, apiIssue := range apiIssues {
+		models.AssertExistsAndLoadBean(t, &models.Issue{ID: apiIssue.ID, RepoID: repo.ID})
+	}
+}
+
+func TestAPICreateIssue(t *testing.T) {
+	prepareTestEnv(t)
+	const body, title = "apiTestBody", "apiTestTitle"
+
+	repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository)
+	owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
+
+	session := loginUser(t, owner.Name)
+
+	urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues?state=all", owner.Name, repo.Name)
+	req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateIssueOption{
+		Body:     body,
+		Title:    title,
+		Assignee: owner.Name,
+	})
+	resp := session.MakeRequest(t, req)
+	assert.EqualValues(t, http.StatusCreated, resp.HeaderCode)
+	var apiIssue api.Issue
+	DecodeJSON(t, resp, &apiIssue)
+	assert.Equal(t, apiIssue.Body, body)
+	assert.Equal(t, apiIssue.Title, title)
+
+	models.AssertExistsAndLoadBean(t, &models.Issue{
+		RepoID:     repo.ID,
+		AssigneeID: owner.ID,
+		Content:    body,
+		Title:      title,
+	})
+}
diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go
index 9afde1f5e..253bdb43d 100644
--- a/routers/api/v1/repo/issue.go
+++ b/routers/api/v1/repo/issue.go
@@ -18,27 +18,25 @@ import (
 
 // ListIssues list the issues of a repository
 func ListIssues(ctx *context.APIContext) {
-	isClosed := ctx.Query("state") == "closed"
-	issueOpts := models.IssuesOptions{
-		RepoID:   ctx.Repo.Repository.ID,
-		Page:     ctx.QueryInt("page"),
-		IsClosed: util.OptionalBoolOf(isClosed),
+	var isClosed util.OptionalBool
+	switch ctx.Query("state") {
+	case "closed":
+		isClosed = util.OptionalBoolTrue
+	case "all":
+		isClosed = util.OptionalBoolNone
+	default:
+		isClosed = util.OptionalBoolFalse
 	}
 
-	issues, err := models.Issues(&issueOpts)
+	issues, err := models.Issues(&models.IssuesOptions{
+		RepoID:   ctx.Repo.Repository.ID,
+		Page:     ctx.QueryInt("page"),
+		IsClosed: isClosed,
+	})
 	if err != nil {
 		ctx.Error(500, "Issues", err)
 		return
 	}
-	if ctx.Query("state") == "all" {
-		issueOpts.IsClosed = util.OptionalBoolOf(!isClosed)
-		tempIssues, err := models.Issues(&issueOpts)
-		if err != nil {
-			ctx.Error(500, "Issues", err)
-			return
-		}
-		issues = append(issues, tempIssues...)
-	}
 
 	err = models.IssueList(issues).LoadAttributes()
 	if err != nil {