diff --git a/changelogs/unreleased/26847-api-pipelines-use-basic.yml b/changelogs/unreleased/26847-api-pipelines-use-basic.yml
new file mode 100644
index 0000000000000000000000000000000000000000..2034a4ba08074584387b684615b70f2a5ff09525
--- /dev/null
+++ b/changelogs/unreleased/26847-api-pipelines-use-basic.yml
@@ -0,0 +1,4 @@
+---
+title: Expose pipelines as PipelineBasic `api/v3/projects/:id/pipelines`
+merge_request: 8875
+author:
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 9d6f3ea41d970e491eb3842306c41c8c76d25354..d809ec032f8c035c50258d684874a35594815d79 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -24,49 +24,13 @@ Example of response
     "id": 47,
     "status": "pending",
     "ref": "new-pipeline",
-    "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
-    "before_sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
-    "tag": false,
-    "yaml_errors": null,
-    "user": {
-      "name": "Administrator",
-      "username": "root",
-      "id": 1,
-      "state": "active",
-      "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
-      "web_url": "http://localhost:3000/root"
-    },
-    "created_at": "2016-08-16T10:23:19.007Z",
-    "updated_at": "2016-08-16T10:23:19.216Z",
-    "started_at": null,
-    "finished_at": null,
-    "committed_at": null,
-    "duration": null,
-    "coverage": "30.0"
+    "sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a"
   },
   {
     "id": 48,
     "status": "pending",
     "ref": "new-pipeline",
-    "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
-    "before_sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
-    "tag": false,
-    "yaml_errors": null,
-    "user": {
-      "name": "Administrator",
-      "username": "root",
-      "id": 1,
-      "state": "active",
-      "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
-      "web_url": "http://localhost:3000/root"
-    },
-    "created_at": "2016-08-16T10:23:21.184Z",
-    "updated_at": "2016-08-16T10:23:21.314Z",
-    "started_at": null,
-    "finished_at": null,
-    "committed_at": null,
-    "duration": null,
-    "coverage": null
+    "sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a"
   }
 ]
 ```
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index cca588944769f5c0ac9bf7f237818cce09032e78..ba5b7e09102ee10de5efbd767c9d3d6d7ddf93bd 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -53,3 +53,4 @@ changes are in V4:
 - Remove `GET /groups/owned`. Use `GET /groups?owned=true` instead [!9505](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9505)
 - Return 202 with JSON body on async removals on V4 API (DELETE `/projects/:id/repository/merged_branches` and DELETE `/projects/:id`) [!9449](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9449)
 - `projects/:id/milestones?iid[]=x&iid[]=y` array filter has been renamed to `iids` [!9096](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9096)
+- Return basic info about pipeline in `GET /projects/:id/pipelines` [!8875](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8875)
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 3e53ab693ab570ebb2007292db54014ae778ea9a..89449ce8813d9eb45f9e10f237b95f8485cca683 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -20,6 +20,7 @@ module API
       mount ::API::V3::MergeRequestDiffs
       mount ::API::V3::MergeRequests
       mount ::API::V3::Notes
+      mount ::API::V3::Pipelines
       mount ::API::V3::ProjectHooks
       mount ::API::V3::Milestones
       mount ::API::V3::Projects
diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb
index 3afc1e385fe5afa16f3a363e96076e4339119514..0721b975ba4d640753c5ba048f20bab933028f63 100644
--- a/lib/api/pipelines.rb
+++ b/lib/api/pipelines.rb
@@ -10,7 +10,7 @@ module API
     resource :projects do
       desc 'Get all Pipelines of the project' do
         detail 'This feature was introduced in GitLab 8.11.'
-        success Entities::Pipeline
+        success Entities::PipelineBasic
       end
       params do
         use :pagination
@@ -21,7 +21,7 @@ module API
         authorize! :read_pipeline, user_project
 
         pipelines = PipelinesFinder.new(user_project).execute(scope: params[:scope])
-        present paginate(pipelines), with: Entities::Pipeline
+        present paginate(pipelines), with: Entities::PipelineBasic
       end
 
       desc 'Create a new pipeline' do
diff --git a/lib/api/v3/pipelines.rb b/lib/api/v3/pipelines.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2c26a5f7d350a9d9066658d96c659a70944b96cd
--- /dev/null
+++ b/lib/api/v3/pipelines.rb
@@ -0,0 +1,36 @@
+module API
+  module V3
+    class Pipelines < Grape::API
+      include PaginationParams
+
+      before { authenticate! }
+
+      params do
+        requires :id, type: String, desc: 'The project ID'
+      end
+      resource :projects do
+        desc 'Get all Pipelines of the project' do
+          detail 'This feature was introduced in GitLab 8.11.'
+          success ::API::Entities::Pipeline
+        end
+        params do
+          use :pagination
+          optional :scope,    type: String, values: %w(running branches tags),
+                              desc: 'Either running, branches, or tags'
+        end
+        get ':id/pipelines' do
+          authorize! :read_pipeline, user_project
+
+          pipelines = PipelinesFinder.new(user_project).execute(scope: params[:scope])
+          present paginate(pipelines), with: ::API::Entities::Pipeline
+        end
+      end
+
+      helpers do
+        def pipeline
+          @pipeline ||= user_project.pipelines.find(params[:pipeline_id])
+        end
+      end
+    end
+  end
+end
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index 98d004b572e2dc2afd104d57ef1935d182d35076..51af999b45545bca084719a1d1f4a6b6e931d58f 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -24,6 +24,7 @@ describe API::Pipelines, api: true do
         expect(json_response).to be_an Array
         expect(json_response.first['sha']).to match /\A\h{40}\z/
         expect(json_response.first['id']).to eq pipeline.id
+        expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status])
       end
     end
 
diff --git a/spec/requests/api/v3/pipelines_spec.rb b/spec/requests/api/v3/pipelines_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..3786eb0693247aef33c783be6cc4e672def2056a
--- /dev/null
+++ b/spec/requests/api/v3/pipelines_spec.rb
@@ -0,0 +1,203 @@
+require 'spec_helper'
+
+describe API::V3::Pipelines, api: true do
+  include ApiHelpers
+
+  let(:user)        { create(:user) }
+  let(:non_member)  { create(:user) }
+  let(:project)     { create(:project, :repository, creator: user) }
+
+  let!(:pipeline) do
+    create(:ci_empty_pipeline, project: project, sha: project.commit.id,
+                               ref: project.default_branch)
+  end
+
+  before { project.team << [user, :master] }
+
+  shared_examples 'a paginated resources' do
+    before do
+      # Fires the request
+      request
+    end
+
+    it 'has pagination headers' do
+      expect(response).to include_pagination_headers
+    end
+  end
+
+  describe 'GET /projects/:id/pipelines ' do
+    it_behaves_like 'a paginated resources' do
+      let(:request) { get v3_api("/projects/#{project.id}/pipelines", user) }
+    end
+
+    context 'authorized user' do
+      it 'returns project pipelines' do
+        get v3_api("/projects/#{project.id}/pipelines", user)
+
+        expect(response).to have_http_status(200)
+        expect(json_response).to be_an Array
+        expect(json_response.first['sha']).to match(/\A\h{40}\z/)
+        expect(json_response.first['id']).to eq pipeline.id
+        expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status before_sha tag yaml_errors user created_at updated_at started_at finished_at committed_at duration coverage])
+      end
+    end
+
+    context 'unauthorized user' do
+      it 'does not return project pipelines' do
+        get v3_api("/projects/#{project.id}/pipelines", non_member)
+
+        expect(response).to have_http_status(404)
+        expect(json_response['message']).to eq '404 Project Not Found'
+        expect(json_response).not_to be_an Array
+      end
+    end
+  end
+
+  describe 'POST /projects/:id/pipeline ' do
+    context 'authorized user' do
+      context 'with gitlab-ci.yml' do
+        before { stub_ci_pipeline_to_return_yaml_file }
+
+        it 'creates and returns a new pipeline' do
+          expect do
+            post v3_api("/projects/#{project.id}/pipeline", user), ref: project.default_branch
+          end.to change { Ci::Pipeline.count }.by(1)
+
+          expect(response).to have_http_status(201)
+          expect(json_response).to be_a Hash
+          expect(json_response['sha']).to eq project.commit.id
+        end
+
+        it 'fails when using an invalid ref' do
+          post v3_api("/projects/#{project.id}/pipeline", user), ref: 'invalid_ref'
+
+          expect(response).to have_http_status(400)
+          expect(json_response['message']['base'].first).to eq 'Reference not found'
+          expect(json_response).not_to be_an Array
+        end
+      end
+
+      context 'without gitlab-ci.yml' do
+        it 'fails to create pipeline' do
+          post v3_api("/projects/#{project.id}/pipeline", user), ref: project.default_branch
+
+          expect(response).to have_http_status(400)
+          expect(json_response['message']['base'].first).to eq 'Missing .gitlab-ci.yml file'
+          expect(json_response).not_to be_an Array
+        end
+      end
+    end
+
+    context 'unauthorized user' do
+      it 'does not create pipeline' do
+        post v3_api("/projects/#{project.id}/pipeline", non_member), ref: project.default_branch
+
+        expect(response).to have_http_status(404)
+        expect(json_response['message']).to eq '404 Project Not Found'
+        expect(json_response).not_to be_an Array
+      end
+    end
+  end
+
+  describe 'GET /projects/:id/pipelines/:pipeline_id' do
+    context 'authorized user' do
+      it 'returns project pipelines' do
+        get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
+
+        expect(response).to have_http_status(200)
+        expect(json_response['sha']).to match /\A\h{40}\z/
+      end
+
+      it 'returns 404 when it does not exist' do
+        get v3_api("/projects/#{project.id}/pipelines/123456", user)
+
+        expect(response).to have_http_status(404)
+        expect(json_response['message']).to eq '404 Not found'
+        expect(json_response['id']).to be nil
+      end
+
+      context 'with coverage' do
+        before do
+          create(:ci_build, coverage: 30, pipeline: pipeline)
+        end
+
+        it 'exposes the coverage' do
+          get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
+
+          expect(json_response["coverage"].to_i).to eq(30)
+        end
+      end
+    end
+
+    context 'unauthorized user' do
+      it 'should not return a project pipeline' do
+        get v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member)
+
+        expect(response).to have_http_status(404)
+        expect(json_response['message']).to eq '404 Project Not Found'
+        expect(json_response['id']).to be nil
+      end
+    end
+  end
+
+  describe 'POST /projects/:id/pipelines/:pipeline_id/retry' do
+    context 'authorized user' do
+      let!(:pipeline) do
+        create(:ci_pipeline, project: project, sha: project.commit.id,
+                             ref: project.default_branch)
+      end
+
+      let!(:build) { create(:ci_build, :failed, pipeline: pipeline) }
+
+      it 'retries failed builds' do
+        expect do
+          post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", user)
+        end.to change { pipeline.builds.count }.from(1).to(2)
+
+        expect(response).to have_http_status(201)
+        expect(build.reload.retried?).to be true
+      end
+    end
+
+    context 'unauthorized user' do
+      it 'should not return a project pipeline' do
+        post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/retry", non_member)
+
+        expect(response).to have_http_status(404)
+        expect(json_response['message']).to eq '404 Project Not Found'
+        expect(json_response['id']).to be nil
+      end
+    end
+  end
+
+  describe 'POST /projects/:id/pipelines/:pipeline_id/cancel' do
+    let!(:pipeline) do
+      create(:ci_empty_pipeline, project: project, sha: project.commit.id,
+                                 ref: project.default_branch)
+    end
+
+    let!(:build) { create(:ci_build, :running, pipeline: pipeline) }
+
+    context 'authorized user' do
+      it 'retries failed builds' do
+        post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", user)
+
+        expect(response).to have_http_status(200)
+        expect(json_response['status']).to eq('canceled')
+      end
+    end
+
+    context 'user without proper access rights' do
+      let!(:reporter) { create(:user) }
+
+      before { project.team << [reporter, :reporter] }
+
+      it 'rejects the action' do
+        post v3_api("/projects/#{project.id}/pipelines/#{pipeline.id}/cancel", reporter)
+
+        expect(response).to have_http_status(403)
+        expect(pipeline.reload.status).to eq('pending')
+      end
+    end
+  end
+end