diff --git a/lib/api/api.rb b/lib/api/api.rb
index 9571d49d9d56be84c632437ee92d3e90c632c15c..5d97d50cb82cfa0ab6f01232bef881f07817ffea 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -36,5 +36,8 @@ module API
     mount Internal
     mount SystemHooks
     mount UserTeams
+    mount ProjectSnippets
+    mount DeployKeys
+    mount ProjectHooks
   end
 end
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
new file mode 100644
index 0000000000000000000000000000000000000000..55c947eb176a31c4dde5486f4ad3c8fa50bc5da7
--- /dev/null
+++ b/lib/api/deploy_keys.rb
@@ -0,0 +1,84 @@
+module API
+  # Projects API
+  class DeployKeys < Grape::API
+    before { authenticate! }
+
+    resource :projects do
+      helpers do
+        def handle_project_member_errors(errors)
+          if errors[:project_access].any?
+            error!(errors[:project_access], 422)
+          end
+          not_found!
+        end
+      end
+
+
+      # Get a specific project's keys
+      #
+      # Example Request:
+      #   GET /projects/:id/keys
+      get ":id/keys" do
+        present user_project.deploy_keys, with: Entities::SSHKey
+      end
+
+      # Get single key owned by currently authenticated user
+      #
+      # Example Request:
+      #   GET /projects/:id/keys/:id
+      get ":id/keys/:key_id" do
+        key = user_project.deploy_keys.find params[:key_id]
+        present key, with: Entities::SSHKey
+      end
+
+      # Add new ssh key to currently authenticated user
+      # If deploy key already exists - it will be joined to project
+      # but only if original one was is accessible by same user
+      #
+      # Parameters:
+      #   key (required) - New SSH Key
+      #   title (required) - New SSH Key's title
+      # Example Request:
+      #   POST /projects/:id/keys
+      post ":id/keys" do
+        attrs = attributes_for_keys [:title, :key]
+
+        if attrs[:key].present?
+          attrs[:key].strip!
+
+          # check if key already exist in project
+          key = user_project.deploy_keys.find_by_key(attrs[:key])
+          if key
+            present key, with: Entities::SSHKey
+            return
+          end
+
+          # Check for available deploy keys in other projects
+          key = current_user.accessible_deploy_keys.find_by_key(attrs[:key])
+          if key
+            user_project.deploy_keys << key
+            present key, with: Entities::SSHKey
+            return
+          end
+        end
+
+        key = DeployKey.new attrs
+
+        if key.valid? && user_project.deploy_keys << key
+          present key, with: Entities::SSHKey
+        else
+          not_found!
+        end
+      end
+
+      # Delete existed ssh key of currently authenticated user
+      #
+      # Example Request:
+      #   DELETE /projects/:id/keys/:id
+      delete ":id/keys/:key_id" do
+        key = user_project.deploy_keys.find params[:key_id]
+        key.destroy
+      end
+    end
+  end
+end
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
new file mode 100644
index 0000000000000000000000000000000000000000..2850125679554471c5347bc3c519198122d8cfdc
--- /dev/null
+++ b/lib/api/project_hooks.rb
@@ -0,0 +1,108 @@
+module API
+  # Projects API
+  class ProjectHooks < Grape::API
+    before { authenticate! }
+
+    resource :projects do
+      helpers do
+        def handle_project_member_errors(errors)
+          if errors[:project_access].any?
+            error!(errors[:project_access], 422)
+          end
+          not_found!
+        end
+      end
+
+      # Get project hooks
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      # Example Request:
+      #   GET /projects/:id/hooks
+      get ":id/hooks" do
+        authorize! :admin_project, user_project
+        @hooks = paginate user_project.hooks
+        present @hooks, with: Entities::Hook
+      end
+
+      # Get a project hook
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   hook_id (required) - The ID of a project hook
+      # Example Request:
+      #   GET /projects/:id/hooks/:hook_id
+      get ":id/hooks/:hook_id" do
+        authorize! :admin_project, user_project
+        @hook = user_project.hooks.find(params[:hook_id])
+        present @hook, with: Entities::Hook
+      end
+
+
+      # Add hook to project
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   url (required) - The hook URL
+      # Example Request:
+      #   POST /projects/:id/hooks
+      post ":id/hooks" do
+        authorize! :admin_project, user_project
+        required_attributes! [:url]
+
+        @hook = user_project.hooks.new({"url" => params[:url]})
+        if @hook.save
+          present @hook, with: Entities::Hook
+        else
+          if @hook.errors[:url].present?
+            error!("Invalid url given", 422)
+          end
+          not_found!
+        end
+      end
+
+      # Update an existing project hook
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   hook_id (required) - The ID of a project hook
+      #   url (required) - The hook URL
+      # Example Request:
+      #   PUT /projects/:id/hooks/:hook_id
+      put ":id/hooks/:hook_id" do
+        @hook = user_project.hooks.find(params[:hook_id])
+        authorize! :admin_project, user_project
+        required_attributes! [:url]
+
+        attrs = attributes_for_keys [:url]
+        if @hook.update_attributes attrs
+          present @hook, with: Entities::Hook
+        else
+          if @hook.errors[:url].present?
+            error!("Invalid url given", 422)
+          end
+          not_found!
+        end
+      end
+
+      # Deletes project hook. This is an idempotent function.
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   hook_id (required) - The ID of hook to delete
+      # Example Request:
+      #   DELETE /projects/:id/hooks/:hook_id
+      delete ":id/hooks/:hook_id" do
+        authorize! :admin_project, user_project
+        required_attributes! [:hook_id]
+
+        begin
+          @hook = ProjectHook.find(params[:hook_id])
+          @hook.destroy
+        rescue
+          # ProjectHook can raise Error if hook_id not found
+        end
+      end
+    end
+  end
+end
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
new file mode 100644
index 0000000000000000000000000000000000000000..46f70f2dc6b9d9493e833e51088dc466700d71d4
--- /dev/null
+++ b/lib/api/project_snippets.rb
@@ -0,0 +1,121 @@
+module API
+  # Projects API
+  class ProjectSnippets < Grape::API
+    before { authenticate! }
+
+    resource :projects do
+      helpers do
+        def handle_project_member_errors(errors)
+          if errors[:project_access].any?
+            error!(errors[:project_access], 422)
+          end
+          not_found!
+        end
+      end
+
+      # Get a project snippets
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      # Example Request:
+      #   GET /projects/:id/snippets
+      get ":id/snippets" do
+        present paginate(user_project.snippets), with: Entities::ProjectSnippet
+      end
+
+      # Get a project snippet
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   snippet_id (required) - The ID of a project snippet
+      # Example Request:
+      #   GET /projects/:id/snippets/:snippet_id
+      get ":id/snippets/:snippet_id" do
+        @snippet = user_project.snippets.find(params[:snippet_id])
+        present @snippet, with: Entities::ProjectSnippet
+      end
+
+      # Create a new project snippet
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   title (required) - The title of a snippet
+      #   file_name (required) - The name of a snippet file
+      #   lifetime (optional) - The expiration date of a snippet
+      #   code (required) - The content of a snippet
+      # Example Request:
+      #   POST /projects/:id/snippets
+      post ":id/snippets" do
+        authorize! :write_project_snippet, user_project
+        required_attributes! [:title, :file_name, :code]
+
+        attrs = attributes_for_keys [:title, :file_name]
+        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
+        attrs[:content] = params[:code] if params[:code].present?
+        @snippet = user_project.snippets.new attrs
+        @snippet.author = current_user
+
+        if @snippet.save
+          present @snippet, with: Entities::ProjectSnippet
+        else
+          not_found!
+        end
+      end
+
+      # Update an existing project snippet
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   snippet_id (required) - The ID of a project snippet
+      #   title (optional) - The title of a snippet
+      #   file_name (optional) - The name of a snippet file
+      #   lifetime (optional) - The expiration date of a snippet
+      #   code (optional) - The content of a snippet
+      # Example Request:
+      #   PUT /projects/:id/snippets/:snippet_id
+      put ":id/snippets/:snippet_id" do
+        @snippet = user_project.snippets.find(params[:snippet_id])
+        authorize! :modify_project_snippet, @snippet
+
+        attrs = attributes_for_keys [:title, :file_name]
+        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
+        attrs[:content] = params[:code] if params[:code].present?
+
+        if @snippet.update_attributes attrs
+          present @snippet, with: Entities::ProjectSnippet
+        else
+          not_found!
+        end
+      end
+
+      # Delete a project snippet
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   snippet_id (required) - The ID of a project snippet
+      # Example Request:
+      #   DELETE /projects/:id/snippets/:snippet_id
+      delete ":id/snippets/:snippet_id" do
+        begin
+          @snippet = user_project.snippets.find(params[:snippet_id])
+          authorize! :modify_project_snippet, @snippet
+          @snippet.destroy
+        rescue
+        end
+      end
+
+      # Get a raw project snippet
+      #
+      # Parameters:
+      #   id (required) - The ID of a project
+      #   snippet_id (required) - The ID of a project snippet
+      # Example Request:
+      #   GET /projects/:id/snippets/:snippet_id/raw
+      get ":id/snippets/:snippet_id/raw" do
+        @snippet = user_project.snippets.find(params[:snippet_id])
+        content_type 'text/plain'
+        present @snippet.content
+      end
+    end
+  end
+end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index f0648c326d5055d548b39c733c20462441a1028b..7fcde3794f45e8fdcea5e4b55c220790d5a9b39a 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -203,267 +203,6 @@ module API
           {message: "Access revoked", id: params[:user_id].to_i}
         end
       end
-
-      # Get project hooks
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      # Example Request:
-      #   GET /projects/:id/hooks
-      get ":id/hooks" do
-        authorize! :admin_project, user_project
-        @hooks = paginate user_project.hooks
-        present @hooks, with: Entities::Hook
-      end
-
-      # Get a project hook
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   hook_id (required) - The ID of a project hook
-      # Example Request:
-      #   GET /projects/:id/hooks/:hook_id
-      get ":id/hooks/:hook_id" do
-        authorize! :admin_project, user_project
-        @hook = user_project.hooks.find(params[:hook_id])
-        present @hook, with: Entities::Hook
-      end
-
-
-      # Add hook to project
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   url (required) - The hook URL
-      # Example Request:
-      #   POST /projects/:id/hooks
-      post ":id/hooks" do
-        authorize! :admin_project, user_project
-        required_attributes! [:url]
-
-        @hook = user_project.hooks.new({"url" => params[:url]})
-        if @hook.save
-          present @hook, with: Entities::Hook
-        else
-          if @hook.errors[:url].present?
-            error!("Invalid url given", 422)
-          end
-          not_found!
-        end
-      end
-
-      # Update an existing project hook
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   hook_id (required) - The ID of a project hook
-      #   url (required) - The hook URL
-      # Example Request:
-      #   PUT /projects/:id/hooks/:hook_id
-      put ":id/hooks/:hook_id" do
-        @hook = user_project.hooks.find(params[:hook_id])
-        authorize! :admin_project, user_project
-        required_attributes! [:url]
-
-        attrs = attributes_for_keys [:url]
-        if @hook.update_attributes attrs
-          present @hook, with: Entities::Hook
-        else
-          if @hook.errors[:url].present?
-            error!("Invalid url given", 422)
-          end
-          not_found!
-        end
-      end
-
-      # Deletes project hook. This is an idempotent function.
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   hook_id (required) - The ID of hook to delete
-      # Example Request:
-      #   DELETE /projects/:id/hooks/:hook_id
-      delete ":id/hooks/:hook_id" do
-        authorize! :admin_project, user_project
-        required_attributes! [:hook_id]
-
-        begin
-          @hook = ProjectHook.find(params[:hook_id])
-          @hook.destroy
-        rescue
-          # ProjectHook can raise Error if hook_id not found
-        end
-      end
-
-      # Get a project snippets
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      # Example Request:
-      #   GET /projects/:id/snippets
-      get ":id/snippets" do
-        present paginate(user_project.snippets), with: Entities::ProjectSnippet
-      end
-
-      # Get a project snippet
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   snippet_id (required) - The ID of a project snippet
-      # Example Request:
-      #   GET /projects/:id/snippets/:snippet_id
-      get ":id/snippets/:snippet_id" do
-        @snippet = user_project.snippets.find(params[:snippet_id])
-        present @snippet, with: Entities::ProjectSnippet
-      end
-
-      # Create a new project snippet
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   title (required) - The title of a snippet
-      #   file_name (required) - The name of a snippet file
-      #   lifetime (optional) - The expiration date of a snippet
-      #   code (required) - The content of a snippet
-      # Example Request:
-      #   POST /projects/:id/snippets
-      post ":id/snippets" do
-        authorize! :write_project_snippet, user_project
-        required_attributes! [:title, :file_name, :code]
-
-        attrs = attributes_for_keys [:title, :file_name]
-        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
-        attrs[:content] = params[:code] if params[:code].present?
-        @snippet = user_project.snippets.new attrs
-        @snippet.author = current_user
-
-        if @snippet.save
-          present @snippet, with: Entities::ProjectSnippet
-        else
-          not_found!
-        end
-      end
-
-      # Update an existing project snippet
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   snippet_id (required) - The ID of a project snippet
-      #   title (optional) - The title of a snippet
-      #   file_name (optional) - The name of a snippet file
-      #   lifetime (optional) - The expiration date of a snippet
-      #   code (optional) - The content of a snippet
-      # Example Request:
-      #   PUT /projects/:id/snippets/:snippet_id
-      put ":id/snippets/:snippet_id" do
-        @snippet = user_project.snippets.find(params[:snippet_id])
-        authorize! :modify_project_snippet, @snippet
-
-        attrs = attributes_for_keys [:title, :file_name]
-        attrs[:expires_at] = params[:lifetime] if params[:lifetime].present?
-        attrs[:content] = params[:code] if params[:code].present?
-
-        if @snippet.update_attributes attrs
-          present @snippet, with: Entities::ProjectSnippet
-        else
-          not_found!
-        end
-      end
-
-      # Delete a project snippet
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   snippet_id (required) - The ID of a project snippet
-      # Example Request:
-      #   DELETE /projects/:id/snippets/:snippet_id
-      delete ":id/snippets/:snippet_id" do
-        begin
-          @snippet = user_project.snippets.find(params[:snippet_id])
-          authorize! :modify_project_snippet, @snippet
-          @snippet.destroy
-        rescue
-        end
-      end
-
-      # Get a raw project snippet
-      #
-      # Parameters:
-      #   id (required) - The ID of a project
-      #   snippet_id (required) - The ID of a project snippet
-      # Example Request:
-      #   GET /projects/:id/snippets/:snippet_id/raw
-      get ":id/snippets/:snippet_id/raw" do
-        @snippet = user_project.snippets.find(params[:snippet_id])
-        content_type 'text/plain'
-        present @snippet.content
-      end
-
-      # Get a specific project's keys
-      #
-      # Example Request:
-      #   GET /projects/:id/keys
-      get ":id/keys" do
-        present user_project.deploy_keys, with: Entities::SSHKey
-      end
-
-      # Get single key owned by currently authenticated user
-      #
-      # Example Request:
-      #   GET /projects/:id/keys/:id
-      get ":id/keys/:key_id" do
-        key = user_project.deploy_keys.find params[:key_id]
-        present key, with: Entities::SSHKey
-      end
-
-      # Add new ssh key to currently authenticated user
-      # If deploy key already exists - it will be joined to project
-      # but only if original one was owned by same user
-      #
-      # Parameters:
-      #   key (required) - New SSH Key
-      #   title (required) - New SSH Key's title
-      # Example Request:
-      #   POST /projects/:id/keys
-      post ":id/keys" do
-        attrs = attributes_for_keys [:title, :key]
-
-        if attrs[:key].present?
-          attrs[:key].strip!
-
-          # check if key already exist in project
-          key = user_project.deploy_keys.find_by_key(attrs[:key])
-          if key
-            present key, with: Entities::SSHKey
-            return
-          end
-
-          # Check for available deploy keys in other projects
-          key = current_user.accessible_deploy_keys.find_by_key(attrs[:key])
-          if key
-            user_project.deploy_keys << key
-            present key, with: Entities::SSHKey
-            return
-          end
-        end
-
-        key = DeployKey.new attrs
-
-        if key.valid? && user_project.deploy_keys << key
-          present key, with: Entities::SSHKey
-        else
-          not_found!
-        end
-      end
-
-      # Delete existed ssh key of currently authenticated user
-      #
-      # Example Request:
-      #   DELETE /projects/:id/keys/:id
-      delete ":id/keys/:key_id" do
-        key = user_project.deploy_keys.find params[:key_id]
-        key.destroy
-      end
     end
   end
 end