diff --git a/CHANGELOG b/CHANGELOG
index 65be4bdf16c1e33f11731f4cf61450c450e39c0d..4874f88f12fc5983daa2253a732af2557887c9e7 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -35,6 +35,7 @@ v 7.13.0 (unreleased)
   - Faster automerge check and merge itself when source and target branches are in same repository 
   - Correctly show anonymous authorized applications under Profile > Applications.
   - Query Optimization in MySQL.
+  - Allow users to be blocked and unblocked via the API
 
 v 7.12.1
   - Fix error when deleting a user who has projects (Stan Hu)
diff --git a/doc/api/users.md b/doc/api/users.md
index 8b04282f16019149a15b6c8ac20bb3429fcbb951..5dca77b5c7befe050039f64996129209a5a123a0 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -396,3 +396,31 @@ Parameters:
 - `id` (required)  - SSH key ID
 
 Will return `200 OK` on success, or `404 Not found` if either user or key cannot be found.
+
+## Block user
+
+Blocks the specified user.  Available only for admin.
+
+```
+PUT /users/:uid/block
+```
+
+Parameters:
+
+- `uid` (required) - id of specified user
+
+Will return `200 OK` on success, or `404 User Not Found` is user cannot be found.
+
+## Unblock user
+
+Unblocks the specified user.  Available only for admin.
+
+```
+PUT /users/:uid/unblock
+```
+
+Parameters:
+
+- `uid` (required) - id of specified user
+
+Will return `200 OK` on success, or `404 User Not Found` is user cannot be found.
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 9b268cfe8bc918c9b08847648af8f738de99e39c..c468371d3d44f0f0264b80e7628cd001e4c81f7e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -199,6 +199,36 @@ module API
           not_found!('User')
         end
       end
+
+      # Block user. Available only for admin
+      #
+      # Example Request:
+      #   PUT /users/:id/block
+      put ':id/block' do
+        authenticated_as_admin!
+        user = User.find_by(id: params[:id])
+
+        if user
+          user.block
+        else
+          not_found!('User')
+        end
+      end
+
+      # Unblock user. Available only for admin
+      #
+      # Example Request:
+      #   PUT /users/:id/unblock
+      put ':id/unblock' do
+        authenticated_as_admin!
+        user = User.find_by(id: params[:id])
+
+        if user
+          user.activate
+        else
+          not_found!('User')
+        end
+      end
     end
 
     resource :user do
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index 1a29058f3f194cbea20ae1c15e00027213661689..c4dd1f76cf2aee870702a4b4d9e5f98593c45f51 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -527,4 +527,55 @@ describe API::API, api: true  do
       expect(response.status).to eq(401)
     end
   end
+
+  describe 'PUT /user/:id/block' do
+    before { admin }
+    it 'should block existing user' do
+      put api("/users/#{user.id}/block", admin)
+      expect(response.status).to eq(200)
+      expect(user.reload.state).to eq('blocked')
+    end
+
+    it 'should not be available for non admin users' do
+      put api("/users/#{user.id}/block", user)
+      expect(response.status).to eq(403)
+      expect(user.reload.state).to eq('active')
+    end
+
+    it 'should return a 404 error if user id not found' do
+      put api('/users/9999/block', admin)
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 User Not Found')
+    end
+  end
+
+  describe 'PUT /user/:id/unblock' do
+    before { admin }
+    it 'should unblock existing user' do
+      put api("/users/#{user.id}/unblock", admin)
+      expect(response.status).to eq(200)
+      expect(user.reload.state).to eq('active')
+    end
+
+    it 'should unblock a blocked user' do
+      put api("/users/#{user.id}/block", admin)
+      expect(response.status).to eq(200)
+      expect(user.reload.state).to eq('blocked')
+      put api("/users/#{user.id}/unblock", admin)
+      expect(response.status).to eq(200)
+      expect(user.reload.state).to eq('active')
+    end
+
+    it 'should not be available for non admin users' do
+      put api("/users/#{user.id}/unblock", user)
+      expect(response.status).to eq(403)
+      expect(user.reload.state).to eq('active')
+    end
+
+    it 'should return a 404 error if user id not found' do
+      put api('/users/9999/block', admin)
+      expect(response.status).to eq(404)
+      expect(json_response['message']).to eq('404 User Not Found')
+    end
+  end
 end