diff --git a/CHANGELOG b/CHANGELOG
index b70d81cdd552a3e11287e126f3d43d7d112be989..137257add3bc62d4ae1b95c7b1404cd23495b48b 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -9,6 +9,7 @@ v 8.13.0 (unreleased)
   - Avoid database queries on Banzai::ReferenceParser::BaseParser for nodes without references
   - Fix permission for setting an issue's due date
   - Expose expires_at field when sharing project on API
+  - Allow the Koding integration to be configured through the API
   - Fix robots.txt disallowing access to groups starting with "s" (Matt Harrison)
   - Use a ConnectionPool for Rails.cache on Sidekiq servers
   - Only update issuable labels if they have been changed
diff --git a/doc/api/settings.md b/doc/api/settings.md
index aaa2c99642bc79e0f85fffac5041c384467dc15c..f7ad3b4cc8edb110953d7d732e5f8678a6283984 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -41,7 +41,9 @@ Example response:
    "gravatar_enabled" : true,
    "sign_in_text" : null,
    "container_registry_token_expire_delay": 5,
-   "repository_storage": "default"
+   "repository_storage": "default",
+   "koding_enabled": false,
+   "koding_url": null
 }
 ```
 
@@ -72,7 +74,9 @@ PUT /application/settings
 | `after_sign_out_path` | string | no | Where to redirect users after logout |
 | `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes |
 | `repository_storage` | string | no | Storage path for new projects. The value should be the name of one of the repository storage paths defined in your gitlab.yml |
-| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols.
+| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. |
+| `koding_enabled` | boolean | no | Enable Koding integration. Default is `false`. |
+| `koding_url` | string | yes (if `koding_enabled` is `true`) |  The Koding instance URL for integration. |
 
 ```bash
 curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/application/settings?signup_enabled=false&default_project_visibility=1
@@ -103,6 +107,8 @@ Example response:
   "user_oauth_applications": true,
   "after_sign_out_path": "",
   "container_registry_token_expire_delay": 5,
-  "repository_storage": "default"
+  "repository_storage": "default",
+  "koding_enabled": false,
+  "koding_url": null
 }
 ```
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index c5dc8b22f6084f84b80a540f41958430e3d6c98c..04437322ec1568eb487ac4ba6711133da7158729 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -494,6 +494,8 @@ module API
       expose :after_sign_out_path
       expose :container_registry_token_expire_delay
       expose :repository_storage
+      expose :koding_enabled
+      expose :koding_url
     end
 
     class Release < Grape::Entity
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 54d096e8b7ffd9d66dc2d8a4301c421af8647882..f4903d8e0beeb0a3c8cde79c59985285d119536c 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -14,22 +14,38 @@ describe API::API, 'Settings', api: true  do
       expect(json_response['default_projects_limit']).to eq(42)
       expect(json_response['signin_enabled']).to be_truthy
       expect(json_response['repository_storage']).to eq('default')
+      expect(json_response['koding_enabled']).to be_falsey
+      expect(json_response['koding_url']).to be_nil
     end
   end
 
   describe "PUT /application/settings" do
-    before do
-      storages = { 'custom' => 'tmp/tests/custom_repositories' }
-      allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
+    context "custom repository storage type set in the config" do
+      before do
+        storages = { 'custom' => 'tmp/tests/custom_repositories' }
+        allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
+      end
+
+      it "updates application settings" do
+        put api("/application/settings", admin),
+          default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com'
+        expect(response).to have_http_status(200)
+        expect(json_response['default_projects_limit']).to eq(3)
+        expect(json_response['signin_enabled']).to be_falsey
+        expect(json_response['repository_storage']).to eq('custom')
+        expect(json_response['koding_enabled']).to be_truthy
+        expect(json_response['koding_url']).to eq('http://koding.example.com')
+      end
     end
 
-    it "updates application settings" do
-      put api("/application/settings", admin),
-        default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom'
-      expect(response).to have_http_status(200)
-      expect(json_response['default_projects_limit']).to eq(3)
-      expect(json_response['signin_enabled']).to be_falsey
-      expect(json_response['repository_storage']).to eq('custom')
+    context "missing koding_url value when koding_enabled is true" do
+      it "returns a blank parameter error message" do
+        put api("/application/settings", admin), koding_enabled: true
+
+        expect(response).to have_http_status(400)
+        expect(json_response['message']).to have_key('koding_url')
+        expect(json_response['message']['koding_url']).to include "can't be blank"
+      end
     end
   end
 end