diff --git a/CHANGELOG b/CHANGELOG
index 894f4bc9af046792ae94605b89901b493444f0fc..9e193132ac2e7b5694492d987f4f787ba702940f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -19,6 +19,7 @@ v 8.13.0 (unreleased)
   - Replaced the check sign to arrow in the show build view. !6501
   - Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar)
   - Fix Error 500 when viewing old merge requests with bad diff data
+  - Create a new /templates namespace for the /licenses, /gitignores and /gitlab_ci_ymls API endpoints. !5717 (tbalthazar)
   - Speed-up group milestones show page
   - Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps)
   - Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs)
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 599331df3f508dc7fdf9815fde69b2c05583b782..56ec1489f896353d26f5827bca98cf020deee91d 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -6,11 +6,10 @@
     groupProjectsPath: "/api/:version/groups/:id/projects.json",
     projectsPath: "/api/:version/projects.json?simple=true",
     labelsPath: "/:namespace_path/:project_path/labels",
-    licensePath: "/api/:version/licenses/:key",
-    gitignorePath: "/api/:version/gitignores/:key",
-    gitlabCiYmlPath: "/api/:version/gitlab_ci_ymls/:key",
+    licensePath: "/api/:version/templates/licenses/:key",
+    gitignorePath: "/api/:version/templates/gitignores/:key",
+    gitlabCiYmlPath: "/api/:version/templates/gitlab_ci_ymls/:key",
     issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key",
-
     group: function(group_id, callback) {
       var url = Api.buildUrl(Api.groupPath)
         .replace(':id', group_id);
diff --git a/doc/api/README.md b/doc/api/README.md
index 9e907689c804284f3e97787548d4648baad0818e..00cb003ed8a29fc3a700a71f4b095b97abe50b75 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -17,6 +17,8 @@ following locations:
 - [Commits](commits.md)
 - [Deployments](deployments.md)
 - [Deploy Keys](deploy_keys.md)
+- [Gitignores templates](templates/gitignores.md)
+- [GitLab CI Config templates](templates/gitlab_ci_ymls.md)
 - [Groups](groups.md)
 - [Group Access Requests](access_requests.md)
 - [Group Members](members.md)
@@ -25,7 +27,7 @@ following locations:
 - [Labels](labels.md)
 - [Merge Requests](merge_requests.md)
 - [Milestones](milestones.md)
-- [Open source license templates](licenses.md)
+- [Open source license templates](templates/licenses.md)
 - [Namespaces](namespaces.md)
 - [Notes](notes.md) (comments)
 - [Notification settings](notification_settings.md)
diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md
new file mode 100644
index 0000000000000000000000000000000000000000..8235be92b12df98db7c77b1d9a8dd30649f5a291
--- /dev/null
+++ b/doc/api/templates/gitignores.md
@@ -0,0 +1,579 @@
+# Gitignores
+
+## List gitignore templates
+
+Get all gitignore templates.
+
+```
+GET /templates/gitignores
+```
+
+```bash
+curl https://gitlab.example.com/api/v3/templates/gitignores
+```
+
+Example response:
+
+```json
+[
+  {
+    "name": "AppEngine"
+  },
+  {
+    "name": "Laravel"
+  },
+  {
+    "name": "Elisp"
+  },
+  {
+    "name": "SketchUp"
+  },
+  {
+    "name": "Ada"
+  },
+  {
+    "name": "Ruby"
+  },
+  {
+    "name": "Kohana"
+  },
+  {
+    "name": "Nanoc"
+  },
+  {
+    "name": "Erlang"
+  },
+  {
+    "name": "OCaml"
+  },
+  {
+    "name": "Lithium"
+  },
+  {
+    "name": "Fortran"
+  },
+  {
+    "name": "Scala"
+  },
+  {
+    "name": "Node"
+  },
+  {
+    "name": "Fancy"
+  },
+  {
+    "name": "Perl"
+  },
+  {
+    "name": "Zephir"
+  },
+  {
+    "name": "WordPress"
+  },
+  {
+    "name": "Symfony"
+  },
+  {
+    "name": "FuelPHP"
+  },
+  {
+    "name": "DM"
+  },
+  {
+    "name": "Sdcc"
+  },
+  {
+    "name": "Rust"
+  },
+  {
+    "name": "C"
+  },
+  {
+    "name": "Umbraco"
+  },
+  {
+    "name": "Actionscript"
+  },
+  {
+    "name": "Android"
+  },
+  {
+    "name": "Grails"
+  },
+  {
+    "name": "Composer"
+  },
+  {
+    "name": "ExpressionEngine"
+  },
+  {
+    "name": "Gcov"
+  },
+  {
+    "name": "Qt"
+  },
+  {
+    "name": "Phalcon"
+  },
+  {
+    "name": "ArchLinuxPackages"
+  },
+  {
+    "name": "TeX"
+  },
+  {
+    "name": "SCons"
+  },
+  {
+    "name": "Lilypond"
+  },
+  {
+    "name": "CommonLisp"
+  },
+  {
+    "name": "Rails"
+  },
+  {
+    "name": "Mercury"
+  },
+  {
+    "name": "Magento"
+  },
+  {
+    "name": "ChefCookbook"
+  },
+  {
+    "name": "GitBook"
+  },
+  {
+    "name": "C++"
+  },
+  {
+    "name": "Eagle"
+  },
+  {
+    "name": "Go"
+  },
+  {
+    "name": "OpenCart"
+  },
+  {
+    "name": "Scheme"
+  },
+  {
+    "name": "Typo3"
+  },
+  {
+    "name": "SeamGen"
+  },
+  {
+    "name": "Swift"
+  },
+  {
+    "name": "Elm"
+  },
+  {
+    "name": "Unity"
+  },
+  {
+    "name": "Agda"
+  },
+  {
+    "name": "CUDA"
+  },
+  {
+    "name": "VVVV"
+  },
+  {
+    "name": "Finale"
+  },
+  {
+    "name": "LemonStand"
+  },
+  {
+    "name": "Textpattern"
+  },
+  {
+    "name": "Julia"
+  },
+  {
+    "name": "Packer"
+  },
+  {
+    "name": "Scrivener"
+  },
+  {
+    "name": "Dart"
+  },
+  {
+    "name": "Plone"
+  },
+  {
+    "name": "Jekyll"
+  },
+  {
+    "name": "Xojo"
+  },
+  {
+    "name": "LabVIEW"
+  },
+  {
+    "name": "Autotools"
+  },
+  {
+    "name": "KiCad"
+  },
+  {
+    "name": "Prestashop"
+  },
+  {
+    "name": "ROS"
+  },
+  {
+    "name": "Smalltalk"
+  },
+  {
+    "name": "GWT"
+  },
+  {
+    "name": "OracleForms"
+  },
+  {
+    "name": "SugarCRM"
+  },
+  {
+    "name": "Nim"
+  },
+  {
+    "name": "SymphonyCMS"
+  },
+  {
+    "name": "Maven"
+  },
+  {
+    "name": "CFWheels"
+  },
+  {
+    "name": "Python"
+  },
+  {
+    "name": "ZendFramework"
+  },
+  {
+    "name": "CakePHP"
+  },
+  {
+    "name": "Concrete5"
+  },
+  {
+    "name": "PlayFramework"
+  },
+  {
+    "name": "Terraform"
+  },
+  {
+    "name": "Elixir"
+  },
+  {
+    "name": "CMake"
+  },
+  {
+    "name": "Joomla"
+  },
+  {
+    "name": "Coq"
+  },
+  {
+    "name": "Delphi"
+  },
+  {
+    "name": "Haskell"
+  },
+  {
+    "name": "Yii"
+  },
+  {
+    "name": "Java"
+  },
+  {
+    "name": "UnrealEngine"
+  },
+  {
+    "name": "AppceleratorTitanium"
+  },
+  {
+    "name": "CraftCMS"
+  },
+  {
+    "name": "ForceDotCom"
+  },
+  {
+    "name": "ExtJs"
+  },
+  {
+    "name": "MetaProgrammingSystem"
+  },
+  {
+    "name": "D"
+  },
+  {
+    "name": "Objective-C"
+  },
+  {
+    "name": "RhodesRhomobile"
+  },
+  {
+    "name": "R"
+  },
+  {
+    "name": "EPiServer"
+  },
+  {
+    "name": "Yeoman"
+  },
+  {
+    "name": "VisualStudio"
+  },
+  {
+    "name": "Processing"
+  },
+  {
+    "name": "Leiningen"
+  },
+  {
+    "name": "Stella"
+  },
+  {
+    "name": "Opa"
+  },
+  {
+    "name": "Drupal"
+  },
+  {
+    "name": "TurboGears2"
+  },
+  {
+    "name": "Idris"
+  },
+  {
+    "name": "Jboss"
+  },
+  {
+    "name": "CodeIgniter"
+  },
+  {
+    "name": "Qooxdoo"
+  },
+  {
+    "name": "Waf"
+  },
+  {
+    "name": "Sass"
+  },
+  {
+    "name": "Lua"
+  },
+  {
+    "name": "Clojure"
+  },
+  {
+    "name": "IGORPro"
+  },
+  {
+    "name": "Gradle"
+  },
+  {
+    "name": "Archives"
+  },
+  {
+    "name": "SynopsysVCS"
+  },
+  {
+    "name": "Ninja"
+  },
+  {
+    "name": "Tags"
+  },
+  {
+    "name": "OSX"
+  },
+  {
+    "name": "Dreamweaver"
+  },
+  {
+    "name": "CodeKit"
+  },
+  {
+    "name": "NotepadPP"
+  },
+  {
+    "name": "VisualStudioCode"
+  },
+  {
+    "name": "Mercurial"
+  },
+  {
+    "name": "BricxCC"
+  },
+  {
+    "name": "DartEditor"
+  },
+  {
+    "name": "Eclipse"
+  },
+  {
+    "name": "Cloud9"
+  },
+  {
+    "name": "TortoiseGit"
+  },
+  {
+    "name": "NetBeans"
+  },
+  {
+    "name": "GPG"
+  },
+  {
+    "name": "Espresso"
+  },
+  {
+    "name": "Redcar"
+  },
+  {
+    "name": "Xcode"
+  },
+  {
+    "name": "Matlab"
+  },
+  {
+    "name": "LyX"
+  },
+  {
+    "name": "SlickEdit"
+  },
+  {
+    "name": "Dropbox"
+  },
+  {
+    "name": "CVS"
+  },
+  {
+    "name": "Calabash"
+  },
+  {
+    "name": "JDeveloper"
+  },
+  {
+    "name": "Vagrant"
+  },
+  {
+    "name": "IPythonNotebook"
+  },
+  {
+    "name": "TextMate"
+  },
+  {
+    "name": "Ensime"
+  },
+  {
+    "name": "WebMethods"
+  },
+  {
+    "name": "VirtualEnv"
+  },
+  {
+    "name": "Emacs"
+  },
+  {
+    "name": "Momentics"
+  },
+  {
+    "name": "JetBrains"
+  },
+  {
+    "name": "SublimeText"
+  },
+  {
+    "name": "Kate"
+  },
+  {
+    "name": "ModelSim"
+  },
+  {
+    "name": "Redis"
+  },
+  {
+    "name": "KDevelop4"
+  },
+  {
+    "name": "Bazaar"
+  },
+  {
+    "name": "Linux"
+  },
+  {
+    "name": "Windows"
+  },
+  {
+    "name": "XilinxISE"
+  },
+  {
+    "name": "Lazarus"
+  },
+  {
+    "name": "EiffelStudio"
+  },
+  {
+    "name": "Anjuta"
+  },
+  {
+    "name": "Vim"
+  },
+  {
+    "name": "Otto"
+  },
+  {
+    "name": "MicrosoftOffice"
+  },
+  {
+    "name": "LibreOffice"
+  },
+  {
+    "name": "SBT"
+  },
+  {
+    "name": "MonoDevelop"
+  },
+  {
+    "name": "SVN"
+  },
+  {
+    "name": "FlexBuilder"
+  }
+]
+```
+
+## Single gitignore template
+
+Get a single gitignore template.
+
+```
+GET /templates/gitignores/:key
+```
+
+| Attribute  | Type   | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `key`      | string | yes      | The key of the gitignore template |
+
+```bash
+curl https://gitlab.example.com/api/v3/templates/gitignores/Ruby
+```
+
+Example response:
+
+```json
+{
+  "name": "Ruby",
+  "content": "*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n\n# Used by dotenv library to load environment variables.\n# .env\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\n# Gemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n"
+}
+```
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
new file mode 100644
index 0000000000000000000000000000000000000000..e120016fbe6b1b17fe66bbf4f29c52e50132f2d7
--- /dev/null
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -0,0 +1,120 @@
+# GitLab CI YMLs
+
+## List GitLab CI YML templates
+
+Get all GitLab CI YML templates.
+
+```
+GET /templates/gitlab_ci_ymls
+```
+
+```bash
+curl https://gitlab.example.com/api/v3/templates/gitlab_ci_ymls
+```
+
+Example response:
+
+```json
+[
+  {
+    "name": "C++"
+  },
+  {
+    "name": "Docker"
+  },
+  {
+    "name": "Elixir"
+  },
+  {
+    "name": "LaTeX"
+  },
+  {
+    "name": "Grails"
+  },
+  {
+    "name": "Rust"
+  },
+  {
+    "name": "Nodejs"
+  },
+  {
+    "name": "Ruby"
+  },
+  {
+    "name": "Scala"
+  },
+  {
+    "name": "Maven"
+  },
+  {
+    "name": "Harp"
+  },
+  {
+    "name": "Pelican"
+  },
+  {
+    "name": "Hyde"
+  },
+  {
+    "name": "Nanoc"
+  },
+  {
+    "name": "Octopress"
+  },
+  {
+    "name": "JBake"
+  },
+  {
+    "name": "HTML"
+  },
+  {
+    "name": "Hugo"
+  },
+  {
+    "name": "Metalsmith"
+  },
+  {
+    "name": "Hexo"
+  },
+  {
+    "name": "Lektor"
+  },
+  {
+    "name": "Doxygen"
+  },
+  {
+    "name": "Brunch"
+  },
+  {
+    "name": "Jekyll"
+  },
+  {
+    "name": "Middleman"
+  }
+]
+```
+
+## Single GitLab CI YML template
+
+Get a single GitLab CI YML template.
+
+```
+GET /templates/gitlab_ci_ymls/:key
+```
+
+| Attribute  | Type   | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `key`      | string | yes      | The key of the GitLab CI YML template |
+
+```bash
+curl https://gitlab.example.com/api/v3/templates/gitlab_ci_ymls/Ruby
+```
+
+Example response:
+
+```json
+{
+  "name": "Ruby",
+  "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.3\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service\nservices:\n  - mysql:latest\n  - redis:latest\n  - postgres:latest\n\nvariables:\n  POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n  paths:\n    - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n  - ruby -v                                   # Print out ruby version for debugging\n  # Uncomment next line if your rails app needs a JS runtime:\n  # - apt-get update -q && apt-get install nodejs -yqq\n  - gem install bundler  --no-ri --no-rdoc    # Bundler is not installed with the image\n  - bundle install -j $(nproc) --path vendor  # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n  script:\n  - rubocop\n\nrspec:\n  script:\n  - rspec spec\n\nrails:\n  variables:\n    DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n  script:\n  - bundle exec rake db:migrate\n  - bundle exec rake db:seed\n  - bundle exec rake test\n"
+}
+```
diff --git a/doc/api/licenses.md b/doc/api/templates/licenses.md
similarity index 95%
rename from doc/api/licenses.md
rename to doc/api/templates/licenses.md
index ed26d1fb7fbf777c843948148a57abc6fa732d37..ae7218cf1bdf5b906b5c0e8cb78ed8e3b97dc906 100644
--- a/doc/api/licenses.md
+++ b/doc/api/templates/licenses.md
@@ -5,7 +5,7 @@
 Get all license templates.
 
 ```
-GET /licenses
+GET /templates/licenses
 ```
 
 | Attribute | Type    | Required | Description           |
@@ -13,7 +13,7 @@ GET /licenses
 | `popular` | boolean | no       | If passed, returns only popular licenses |
 
 ```bash
-curl https://gitlab.example.com/api/v3/licenses?popular=1
+curl https://gitlab.example.com/api/v3/templates/licenses?popular=1
 ```
 
 Example response:
@@ -102,7 +102,7 @@ Get a single license template. You can pass parameters to replace the license
 placeholder.
 
 ```
-GET /licenses/:key
+GET /templates/licenses/:key
 ```
 
 | Attribute  | Type   | Required | Description |
@@ -116,7 +116,7 @@ If you omit the `fullname` parameter but authenticate your request, the name of
 the authenticated user will be used to replace the copyright holder placeholder.
 
 ```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/licenses/mit?project=My+Cool+Project
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/templates/licenses/mit?project=My+Cool+Project
 ```
 
 Example response:
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 99722a0a65cf5e6968bdea13d8279020b61cc872..c64d444842de37701d22d60b4707a7a8334337e9 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -46,7 +46,6 @@ module API
     mount ::API::Boards
     mount ::API::Keys
     mount ::API::Labels
-    mount ::API::LicenseTemplates
     mount ::API::Lint
     mount ::API::Members
     mount ::API::MergeRequests
diff --git a/lib/api/license_templates.rb b/lib/api/license_templates.rb
deleted file mode 100644
index d0552299ed0788d6b19ff97bbea54f7793efce18..0000000000000000000000000000000000000000
--- a/lib/api/license_templates.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-module API
-  # License Templates API
-  class LicenseTemplates < Grape::API
-    PROJECT_TEMPLATE_REGEX =
-      /[\<\{\[]
-        (project|description|
-        one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
-      [\>\}\]]/xi.freeze
-    YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze
-    FULLNAME_TEMPLATE_REGEX =
-      /[\<\{\[]
-        (fullname|name\sof\s(author|copyright\sowner))
-      [\>\}\]]/xi.freeze
-
-    # Get the list of the available license templates
-    #
-    # Parameters:
-    #   popular - Filter licenses to only the popular ones
-    #
-    # Example Request:
-    #   GET /licenses
-    #   GET /licenses?popular=1
-    get 'licenses' do
-      options = {
-        featured: params[:popular].present? ? true : nil
-      }
-      present Licensee::License.all(options), with: Entities::RepoLicense
-    end
-
-    # Get text for specific license
-    #
-    # Parameters:
-    #   key (required) - The key of a license
-    #   project        - Copyrighted project name
-    #   fullname       - Full name of copyright holder
-    #
-    # Example Request:
-    #   GET /licenses/mit
-    #
-    get 'licenses/:key', requirements: { key: /[\w\.-]+/ } do
-      required_attributes! [:key]
-
-      not_found!('License') unless Licensee::License.find(params[:key])
-
-      # We create a fresh Licensee::License object since we'll modify its
-      # content in place below.
-      license = Licensee::License.new(params[:key])
-
-      license.content.gsub!(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
-      license.content.gsub!(PROJECT_TEMPLATE_REGEX, params[:project]) if params[:project].present?
-
-      fullname = params[:fullname].presence || current_user.try(:name)
-      license.content.gsub!(FULLNAME_TEMPLATE_REGEX, fullname) if fullname
-
-      present license, with: Entities::RepoLicense
-    end
-  end
-end
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index b9e718147e10d1e9285c96e0ed582b0f1a023357..8a53d9c0095d5355224bb19e40ce174b734b49f4 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -1,39 +1,115 @@
 module API
   class Templates < Grape::API
     GLOBAL_TEMPLATE_TYPES = {
-      gitignores:     Gitlab::Template::GitignoreTemplate,
-      gitlab_ci_ymls: Gitlab::Template::GitlabCiYmlTemplate
+      gitignores: {
+        klass: Gitlab::Template::GitignoreTemplate,
+        gitlab_version: 8.8
+      },
+      gitlab_ci_ymls: {
+        klass: Gitlab::Template::GitlabCiYmlTemplate,
+        gitlab_version: 8.9
+      }
     }.freeze
+    PROJECT_TEMPLATE_REGEX =
+      /[\<\{\[]
+        (project|description|
+        one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
+      [\>\}\]]/xi.freeze
+    YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze
+    FULLNAME_TEMPLATE_REGEX =
+      /[\<\{\[]
+        (fullname|name\sof\s(author|copyright\sowner))
+      [\>\}\]]/xi.freeze
+    DEPRECATION_MESSAGE = ' This endpoint is deprecated and will be removed in GitLab 9.0.'.freeze
 
     helpers do
+      def parsed_license_template
+        # We create a fresh Licensee::License object since we'll modify its
+        # content in place below.
+        template = Licensee::License.new(params[:name])
+
+        template.content.gsub!(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
+        template.content.gsub!(PROJECT_TEMPLATE_REGEX, params[:project]) if params[:project].present?
+
+        fullname = params[:fullname].presence || current_user.try(:name)
+        template.content.gsub!(FULLNAME_TEMPLATE_REGEX, fullname) if fullname
+        template
+      end
+
       def render_response(template_type, template)
         not_found!(template_type.to_s.singularize) unless template
         present template, with: Entities::Template
       end
     end
 
-    GLOBAL_TEMPLATE_TYPES.each do |template_type, klass|
-      # Get the list of the available template
-      #
-      # Example Request:
-      #   GET /gitignores
-      #   GET /gitlab_ci_ymls
-      get template_type.to_s do
-        present klass.all, with: Entities::TemplatesList
-      end
-
-      # Get the text for a specific template present in local filesystem
-      #
-      # Parameters:
-      #   name (required) - The name of a template
-      #
-      # Example Request:
-      #   GET /gitignores/Elixir
-      #   GET /gitlab_ci_ymls/Ruby
-      get "#{template_type}/:name" do
-        required_attributes! [:name]
-        new_template = klass.find(params[:name])
-        render_response(template_type, new_template)
+    { "licenses" => :deprecated, "templates/licenses" => :ok }.each do |route, status|
+      desc 'Get the list of the available license template' do
+        detailed_desc = 'This feature was introduced in GitLab 8.7.'
+        detailed_desc << DEPRECATION_MESSAGE unless status == :ok
+        detail detailed_desc
+        success Entities::RepoLicense
+      end
+      params do
+        optional :popular, type: Boolean, desc: 'If passed, returns only popular licenses'
+      end 
+      get route do
+        options = {
+          featured: declared(params).popular.present? ? true : nil
+        }
+        present Licensee::License.all(options), with: Entities::RepoLicense
+      end
+    end
+
+    { "licenses/:name" => :deprecated, "templates/licenses/:name" => :ok }.each do |route, status|
+      desc 'Get the text for a specific license' do
+        detailed_desc = 'This feature was introduced in GitLab 8.7.'
+        detailed_desc << DEPRECATION_MESSAGE unless status == :ok
+        detail detailed_desc
+        success Entities::RepoLicense
+      end
+      params do
+        requires :name, type: String, desc: 'The name of the template'
+      end 
+      get route, requirements: { name: /[\w\.-]+/ } do
+        not_found!('License') unless Licensee::License.find(declared(params).name)
+
+        template = parsed_license_template
+
+        present template, with: Entities::RepoLicense
+      end
+    end
+      
+    GLOBAL_TEMPLATE_TYPES.each do |template_type, properties|
+      klass = properties[:klass]
+      gitlab_version = properties[:gitlab_version]
+
+      { template_type => :deprecated, "templates/#{template_type}" => :ok }.each do |route, status|
+        desc 'Get the list of the available template' do
+          detailed_desc = "This feature was introduced in GitLab #{gitlab_version}."
+          detailed_desc << DEPRECATION_MESSAGE unless status == :ok
+          detail detailed_desc
+          success Entities::TemplatesList
+        end
+        get route do
+          present klass.all, with: Entities::TemplatesList
+        end
+      end
+
+      { "#{template_type}/:name" => :deprecated, "templates/#{template_type}/:name" => :ok }.each do |route, status|
+        desc 'Get the text for a specific template present in local filesystem' do
+          detailed_desc = "This feature was introduced in GitLab #{gitlab_version}."
+          detailed_desc << DEPRECATION_MESSAGE unless status == :ok
+          detail detailed_desc
+          success Entities::Template
+        end
+        params do
+          requires :name, type: String, desc: 'The name of the template'
+        end 
+        get route do
+          new_template = klass.find(declared(params).name)
+
+          render_response(template_type, new_template)
+        end
       end
     end
   end
diff --git a/spec/requests/api/license_templates_spec.rb b/spec/requests/api/license_templates_spec.rb
deleted file mode 100644
index 9a1894d63a2d8d73397792bed02f8ef78d97de00..0000000000000000000000000000000000000000
--- a/spec/requests/api/license_templates_spec.rb
+++ /dev/null
@@ -1,136 +0,0 @@
-require 'spec_helper'
-
-describe API::API, api: true  do
-  include ApiHelpers
-
-  describe 'Entity' do
-    before { get api('/licenses/mit') }
-
-    it { expect(json_response['key']).to eq('mit') }
-    it { expect(json_response['name']).to eq('MIT License') }
-    it { expect(json_response['nickname']).to be_nil }
-    it { expect(json_response['popular']).to be true }
-    it { expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/') }
-    it { expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT') }
-    it { expect(json_response['description']).to include('A permissive license that is short and to the point.') }
-    it { expect(json_response['conditions']).to eq(%w[include-copyright]) }
-    it { expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use]) }
-    it { expect(json_response['limitations']).to eq(%w[no-liability]) }
-    it { expect(json_response['content']).to include('The MIT License (MIT)') }
-  end
-
-  describe 'GET /licenses' do
-    it 'returns a list of available license templates' do
-      get api('/licenses')
-
-      expect(response).to have_http_status(200)
-      expect(json_response).to be_an Array
-      expect(json_response.size).to eq(15)
-      expect(json_response.map { |l| l['key'] }).to include('agpl-3.0')
-    end
-
-    describe 'the popular parameter' do
-      context 'with popular=1' do
-        it 'returns a list of available popular license templates' do
-          get api('/licenses?popular=1')
-
-          expect(response).to have_http_status(200)
-          expect(json_response).to be_an Array
-          expect(json_response.size).to eq(3)
-          expect(json_response.map { |l| l['key'] }).to include('apache-2.0')
-        end
-      end
-    end
-  end
-
-  describe 'GET /licenses/:key' do
-    context 'with :project and :fullname given' do
-      before do
-        get api("/licenses/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}")
-      end
-
-      context 'for the mit license' do
-        let(:license_type) { 'mit' }
-
-        it 'returns the license text' do
-          expect(json_response['content']).to include('The MIT License (MIT)')
-        end
-
-        it 'replaces placeholder values' do
-          expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton")
-        end
-      end
-
-      context 'for the agpl-3.0 license' do
-        let(:license_type) { 'agpl-3.0' }
-
-        it 'returns the license text' do
-          expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE')
-        end
-
-        it 'replaces placeholder values' do
-          expect(json_response['content']).to include('My Awesome Project')
-          expect(json_response['content']).to include("Copyright (C) #{Time.now.year}  Anton")
-        end
-      end
-
-      context 'for the gpl-3.0 license' do
-        let(:license_type) { 'gpl-3.0' }
-
-        it 'returns the license text' do
-          expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
-        end
-
-        it 'replaces placeholder values' do
-          expect(json_response['content']).to include('My Awesome Project')
-          expect(json_response['content']).to include("Copyright (C) #{Time.now.year}  Anton")
-        end
-      end
-
-      context 'for the gpl-2.0 license' do
-        let(:license_type) { 'gpl-2.0' }
-
-        it 'returns the license text' do
-          expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
-        end
-
-        it 'replaces placeholder values' do
-          expect(json_response['content']).to include('My Awesome Project')
-          expect(json_response['content']).to include("Copyright (C) #{Time.now.year}  Anton")
-        end
-      end
-
-      context 'for the apache-2.0 license' do
-        let(:license_type) { 'apache-2.0' }
-
-        it 'returns the license text' do
-          expect(json_response['content']).to include('Apache License')
-        end
-
-        it 'replaces placeholder values' do
-          expect(json_response['content']).to include("Copyright #{Time.now.year} Anton")
-        end
-      end
-
-      context 'for an uknown license' do
-        let(:license_type) { 'muth-over9000' }
-
-        it 'returns a 404' do
-          expect(response).to have_http_status(404)
-        end
-      end
-    end
-
-    context 'with no :fullname given' do
-      context 'with an authenticated user' do
-        let(:user) { create(:user) }
-
-        it 'replaces the copyright owner placeholder with the name of the current user' do
-          get api('/licenses/mit', user)
-
-          expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}")
-        end
-      end
-    end
-  end
-end
diff --git a/spec/requests/api/templates_spec.rb b/spec/requests/api/templates_spec.rb
index 5bd5b861792da3b92f187bbcf4688547d4e17d95..d32ba60fc4ca75c71b44101fcf9bd20d5f8b8d57 100644
--- a/spec/requests/api/templates_spec.rb
+++ b/spec/requests/api/templates_spec.rb
@@ -3,53 +3,201 @@ require 'spec_helper'
 describe API::Templates, api: true  do
   include ApiHelpers
 
-  context 'global templates' do
-    describe 'the Template Entity' do
-      before { get api('/gitignores/Ruby') }
+  shared_examples_for 'the Template Entity' do |path|
+    before { get api(path) }
 
-      it { expect(json_response['name']).to eq('Ruby') }
-      it { expect(json_response['content']).to include('*.gem') }
+    it { expect(json_response['name']).to eq('Ruby') }
+    it { expect(json_response['content']).to include('*.gem') }
+  end
+  
+  shared_examples_for 'the TemplateList Entity' do |path|
+    before { get api(path) }
+
+    it { expect(json_response.first['name']).not_to be_nil }
+    it { expect(json_response.first['content']).to be_nil }
+  end
+
+  shared_examples_for 'requesting gitignores' do |path|
+    it 'returns a list of available gitignore templates' do
+      get api(path)
+
+      expect(response).to have_http_status(200)
+      expect(json_response).to be_an Array
+      expect(json_response.size).to be > 15
     end
+  end
 
-    describe 'the TemplateList Entity' do
-      before { get api('/gitignores') }
+  shared_examples_for 'requesting gitlab-ci-ymls' do |path|
+    it 'returns a list of available gitlab_ci_ymls' do
+      get api(path)
 
-      it { expect(json_response.first['name']).not_to be_nil }
-      it { expect(json_response.first['content']).to be_nil }
+      expect(response).to have_http_status(200)
+      expect(json_response).to be_an Array
+      expect(json_response.first['name']).not_to be_nil
     end
+  end
+
+  shared_examples_for 'requesting gitlab-ci-yml for Ruby' do |path|
+    it 'adds a disclaimer on the top' do
+      get api(path)
+
+      expect(response).to have_http_status(200)
+      expect(json_response['content']).to start_with("# This file is a template,")
+    end
+  end
+
+  shared_examples_for 'the License Template Entity' do |path|
+    before { get api(path) }
+
+    it 'returns a license template' do
+      expect(json_response['key']).to eq('mit')
+      expect(json_response['name']).to eq('MIT License')
+      expect(json_response['nickname']).to be_nil
+      expect(json_response['popular']).to be true
+      expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/')
+      expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT')
+      expect(json_response['description']).to include('A permissive license that is short and to the point.')
+      expect(json_response['conditions']).to eq(%w[include-copyright])
+      expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use])
+      expect(json_response['limitations']).to eq(%w[no-liability])
+      expect(json_response['content']).to include('The MIT License (MIT)')
+    end
+  end
 
-    context 'requesting gitignores' do
-      describe 'GET /gitignores' do
-        it 'returns a list of available gitignore templates' do
-          get api('/gitignores')
+  shared_examples_for 'GET licenses' do |path|
+    it 'returns a list of available license templates' do
+      get api(path)
 
-          expect(response.status).to eq(200)
+      expect(response).to have_http_status(200)
+      expect(json_response).to be_an Array
+      expect(json_response.size).to eq(15)
+      expect(json_response.map { |l| l['key'] }).to include('agpl-3.0')
+    end
+
+    describe 'the popular parameter' do
+      context 'with popular=1' do
+        it 'returns a list of available popular license templates' do
+          get api("#{path}?popular=1")
+
+          expect(response).to have_http_status(200)
           expect(json_response).to be_an Array
-          expect(json_response.size).to be > 15
+          expect(json_response.size).to eq(3)
+          expect(json_response.map { |l| l['key'] }).to include('apache-2.0')
         end
       end
     end
+  end
 
-    context 'requesting gitlab-ci-ymls' do
-      describe 'GET /gitlab_ci_ymls' do
-        it 'returns a list of available gitlab_ci_ymls' do
-          get api('/gitlab_ci_ymls')
+  shared_examples_for 'GET licenses/:name' do |path|
+    context 'with :project and :fullname given' do
+      before do
+        get api("#{path}/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}")
+      end
 
-          expect(response.status).to eq(200)
-          expect(json_response).to be_an Array
-          expect(json_response.first['name']).not_to be_nil
+      context 'for the mit license' do
+        let(:license_type) { 'mit' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('The MIT License (MIT)')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton")
+        end
+      end
+
+      context 'for the agpl-3.0 license' do
+        let(:license_type) { 'agpl-3.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('My Awesome Project')
+          expect(json_response['content']).to include("Copyright (C) #{Time.now.year}  Anton")
+        end
+      end
+
+      context 'for the gpl-3.0 license' do
+        let(:license_type) { 'gpl-3.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('My Awesome Project')
+          expect(json_response['content']).to include("Copyright (C) #{Time.now.year}  Anton")
+        end
+      end
+
+      context 'for the gpl-2.0 license' do
+        let(:license_type) { 'gpl-2.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include('My Awesome Project')
+          expect(json_response['content']).to include("Copyright (C) #{Time.now.year}  Anton")
+        end
+      end
+
+      context 'for the apache-2.0 license' do
+        let(:license_type) { 'apache-2.0' }
+
+        it 'returns the license text' do
+          expect(json_response['content']).to include('Apache License')
+        end
+
+        it 'replaces placeholder values' do
+          expect(json_response['content']).to include("Copyright #{Time.now.year} Anton")
+        end
+      end
+
+      context 'for an uknown license' do
+        let(:license_type) { 'muth-over9000' }
+
+        it 'returns a 404' do
+          expect(response).to have_http_status(404)
         end
       end
     end
 
-    describe 'GET /gitlab_ci_ymls/Ruby' do
-      it 'adds a disclaimer on the top' do
-        get api('/gitlab_ci_ymls/Ruby')
+    context 'with no :fullname given' do
+      context 'with an authenticated user' do
+        let(:user) { create(:user) }
+
+        it 'replaces the copyright owner placeholder with the name of the current user' do
+          get api('/templates/licenses/mit', user)
 
-        expect(response).to have_http_status(200)
-        expect(json_response['name']).not_to be_nil
-        expect(json_response['content']).to start_with("# This file is a template,")
+          expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}")
+        end
       end
     end
   end
+
+  describe 'with /templates namespace' do
+    it_behaves_like 'the Template Entity', '/templates/gitignores/Ruby'
+    it_behaves_like 'the TemplateList Entity', '/templates/gitignores'
+    it_behaves_like 'requesting gitignores', '/templates/gitignores'
+    it_behaves_like 'requesting gitlab-ci-ymls', '/templates/gitlab_ci_ymls'
+    it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/templates/gitlab_ci_ymls/Ruby'
+    it_behaves_like 'the License Template Entity', '/templates/licenses/mit'
+    it_behaves_like 'GET licenses', '/templates/licenses'
+    it_behaves_like 'GET licenses/:name', '/templates/licenses'
+  end
+
+  describe 'without /templates namespace' do
+    it_behaves_like 'the Template Entity', '/gitignores/Ruby'
+    it_behaves_like 'the TemplateList Entity', '/gitignores'
+    it_behaves_like 'requesting gitignores', '/gitignores'
+    it_behaves_like 'requesting gitlab-ci-ymls', '/gitlab_ci_ymls'
+    it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/gitlab_ci_ymls/Ruby'
+    it_behaves_like 'the License Template Entity', '/licenses/mit'
+    it_behaves_like 'GET licenses', '/licenses'
+    it_behaves_like 'GET licenses/:name', '/licenses'
+  end
 end