diff --git a/.gitignore b/.gitignore
index 28e148770b5..e4b7fe4684c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,21 @@
-*.bak
+# Python
 *.pyc
 *.pyo
-*~
+
+# Apple
 .DS_Store
-.ropeproject
+
+.*project
+local.properties
+*.bak
+*~
 /*.log
 /.Tribler
 /.coverage
 /.dir-locals.el
 /.gdb_history
-/.idea/
+**.idea/
 /.noseids
-/.project
-/.pydevproject
-/Tribler/.project
-/Tribler/.pydevproject
 /TAGS
 /bootstraptribler.txt
 /core
@@ -33,10 +34,28 @@ memorydump.out
 test_file
 test_file.torrent
 
-# pycharm
-**.idea/
-
 # Ignore nosetest coverage output
 cover/
 htmlcov/
 .coverage
+
+# Android
+*.apk
+
+/android/TriblerService/service/typescript
+/android/TriblerService/service/ffmpeg
+/android/TriblerService/dist
+
+/android/TriblerApp/app/src/main/jniLibs
+/android/TriblerApp/app/src/main/jni/include/python2.7
+/android/TriblerApp/app/src/main/jni/lib
+/android/TriblerApp/app/src/main/assets/private.mp3
+
+# Android Studio
+/android/TriblerApp/app/*.iml
+/android/TriblerApp/*.iml
+/android/TriblerApp/app/build
+/android/TriblerApp/build
+/android/TriblerApp/.gradle
+/android/TriblerApp/captures
+
diff --git a/Tribler/Core/Modules/channel/channel.py b/Tribler/Core/Modules/channel/channel.py
index ecdabd7615e..4d8a837a849 100644
--- a/Tribler/Core/Modules/channel/channel.py
+++ b/Tribler/Core/Modules/channel/channel.py
@@ -36,6 +36,14 @@ def channel_id(self):
     def name(self):
         return self._channel_community.get_channel_name()
 
+    @property
+    def description(self):
+        return self._channel_community.get_channel_description()
+
+    @property
+    def mode(self):
+        return self._channel_community.get_channel_mode()
+
     def get_rss_feed_url_list(self):
         return [url for url in self._rss_feed_dict.iterkeys()]
 
diff --git a/Tribler/Core/Modules/channel/channel_manager.py b/Tribler/Core/Modules/channel/channel_manager.py
index 2b4f046c915..d8738edb88f 100644
--- a/Tribler/Core/Modules/channel/channel_manager.py
+++ b/Tribler/Core/Modules/channel/channel_manager.py
@@ -5,6 +5,7 @@
 from Tribler.dispersy.util import blocking_call_on_reactor_thread, call_on_reactor_thread
 from Tribler.community.channel.community import ChannelCommunity
 
+from Tribler.Core.exceptions import DuplicateChannelNameError
 from Tribler.Core.Modules.channel.channel import ChannelObject
 
 
@@ -61,6 +62,8 @@ def create_channel(self, name, description, mode, rss_url=None):
         :param description: Description of the Channel.
         :param mode: Mode of the Channel ('open', 'semi-open', or 'closed').
         :param rss_url: RSS URL for the Channel.
+        :return: Channel ID
+        :raises DuplicateChannelNameError if name already exists
         """
         assert isinstance(name, basestring), u"name is not a basestring: %s" % type(name)
         assert isinstance(description, basestring), u"description is not a basestring: %s" % type(description)
@@ -70,8 +73,7 @@ def create_channel(self, name, description, mode, rss_url=None):
         # if two channels have the same name, this will not work
         for channel_object in self._channel_list:
             if name == channel_object.name:
-                self._logger.error(u"Channel name already exists: %s", name)
-                return
+                raise DuplicateChannelNameError(u"Channel name already exists: %s" % name)
 
         channel_mode = self._channel_mode_map[mode]
         community = ChannelCommunity.create_community(self.dispersy, self.session.dispersy_member,
@@ -90,6 +92,7 @@ def create_channel(self, name, description, mode, rss_url=None):
             channel_obj.create_rss_feed(rss_url)
 
         self._logger.debug(u"creating channel '%s', %s", channel_obj.name, hexlify(community.cid))
+        return channel_obj.channel_id
 
     def get_my_channel(self, channel_id):
         """
diff --git a/Tribler/Core/Modules/restapi/my_channel_endpoint.py b/Tribler/Core/Modules/restapi/my_channel_endpoint.py
index c2b1b6f9131..3012f341b36 100644
--- a/Tribler/Core/Modules/restapi/my_channel_endpoint.py
+++ b/Tribler/Core/Modules/restapi/my_channel_endpoint.py
@@ -3,6 +3,7 @@
 from Tribler.Core.CacheDB.sqlitecachedb import str2bin
 
 from Tribler.Core.simpledefs import NTFY_CHANNELCAST
+from Tribler.Core.exceptions import DuplicateChannelNameError
 
 
 class MyChannelBaseEndpoint(resource.Resource):
@@ -36,31 +37,30 @@ class MyChannelEndpoint(MyChannelBaseEndpoint):
     This endpoint is responsible for handing all requests regarding your channel such as getting and updating
     torrents, playlists and rss-feeds.
     """
+
     def __init__(self, session):
         MyChannelBaseEndpoint.__init__(self, session)
-        child_handler_dict = {"overview": MyChannelOverviewEndpoint, "torrents": MyChannelTorrentsEndpoint,
-                              "rssfeeds": MyChannelRssFeedsEndpoint, "playlists": MyChannelPlaylistsEndpoint,
+        child_handler_dict = {"torrents": MyChannelTorrentsEndpoint,
+                              "rssfeeds": MyChannelRssFeedsEndpoint,
+                              "playlists": MyChannelPlaylistsEndpoint,
                               "recheckfeeds": MyChannelRecheckFeedsEndpoint}
         for path, child_cls in child_handler_dict.iteritems():
             self.putChild(path, child_cls(self.session))
 
-
-class MyChannelOverviewEndpoint(MyChannelBaseEndpoint):
-    """
-    Return the name, description and identifier of your channel.
-    This endpoint returns a 404 HTTP response if you have not created a channel (yet).
-
-    Example response:
-    {
-        "overview": {
-            "name": "My Tribler channel",
-            "description": "A great collection of open-source movies",
-            "identifier": "4a9cfc7ca9d15617765f4151dd9fae94c8f3ba11"
-        }
-    }
-    """
-
     def render_GET(self, request):
+        """
+            Return the name, description and identifier of your channel.
+            This endpoint returns a 404 HTTP response if you have not created a channel (yet).
+
+            Example response:
+            {
+                "overview": {
+                    "name": "My Tribler channel",
+                    "description": "A great collection of open-source movies",
+                    "identifier": "4a9cfc7ca9d15617765f4151dd9fae94c8f3ba11"
+                }
+            }
+            """
         my_channel_id = self.channel_db_handler.getMyChannelId()
         if my_channel_id is None:
             return MyChannelBaseEndpoint.return_404(request)
@@ -70,6 +70,48 @@ def render_GET(self, request):
         return json.dumps({'overview': {'identifier': my_channel[1].encode('hex'), 'name': my_channel[2],
                                         'description': my_channel[3]}})
 
+    def render_PUT(self, request):
+        """
+        Create your own new channel.
+
+        Example request:
+        {
+            "name": "John Smit's channel",
+            "description": "Video's of my cat",
+            "mode": "open" or "semi-open" or "closed" (default)
+        }
+        """
+        parameters = http.parse_qs(request.content.read(), 1)
+
+        if 'name' not in parameters or len(parameters['name']) == 0:
+            request.setResponseCode(http.BAD_REQUEST)
+            return json.dumps({"error": "name parameter missing"})
+
+        if 'description' not in parameters or len(parameters['description']) == 0:
+            request.setResponseCode(http.BAD_REQUEST)
+            return json.dumps({"error": "description parameter missing"})
+
+        if 'mode' not in parameters or len(parameters['mode']) == 0:
+            mode = u'closed'
+        else:
+            mode = parameters['mode'][0]
+
+        try:
+            channel_id = self.session.create_channel(parameters['name'][0], parameters['description'][0], mode)
+        except DuplicateChannelNameError as ex:
+            request.setResponseCode(http.INTERNAL_SERVER_ERROR)
+            request.setHeader('Content-Type', 'text/json')
+            return json.dumps({
+                u"error": {
+                    u"handled": True,
+                    u"code": ex.__class__.__name__,
+                    u"message": ex.message
+                }
+            })
+
+        request.setHeader('Content-Type', 'text/json')
+        return json.dumps({"added": channel_id})
+
 
 class MyChannelTorrentsEndpoint(MyChannelBaseEndpoint):
     """
diff --git a/Tribler/Core/Modules/restapi/rest_manager.py b/Tribler/Core/Modules/restapi/rest_manager.py
index 938bc424579..c5056086d9e 100644
--- a/Tribler/Core/Modules/restapi/rest_manager.py
+++ b/Tribler/Core/Modules/restapi/rest_manager.py
@@ -1,8 +1,11 @@
+import json
 import logging
+from traceback import format_tb
 
 from twisted.internet import reactor
 from twisted.internet.defer import maybeDeferred
-from twisted.web import server
+from twisted.python.compat import intToBytes
+from twisted.web import server, http
 
 from Tribler.Core.Modules.restapi.root_endpoint import RootEndpoint
 from Tribler.dispersy.taskmanager import TaskManager
@@ -24,10 +27,42 @@ def start(self):
         Starts the HTTP API with the listen port as specified in the session configuration.
         """
         self.site = reactor.listenTCP(self.session.get_http_api_port(),
-                                      server.Site(RootEndpoint(self.session)))
+                                      server.Site(resource=RootEndpoint(self.session),
+                                                  requestFactory=RESTRequest))
 
     def stop(self):
         """
         Stop the HTTP API and return a deferred that fires when the server has shut down.
         """
         return maybeDeferred(self.site.stopListening)
+
+
+class RESTRequest(server.Request):
+    """
+    This class gracefully takes care of unhandled exceptions raised during the processing of any request.
+    """
+    defaultContentType = b"text/json"
+
+    def __init__(self, *args, **kw):
+        server.Request.__init__(self, *args, **kw)
+        self._logger = logging.getLogger(self.__class__.__name__)
+
+    def processingFailed(self, reason):
+        self._logger.error(reason)
+        response = {
+            u"error": {
+                u"handled": False,
+                u"code": reason.value.__class__.__name__,
+                u"message": reason.value.message
+            }
+        }
+        if self.site.displayTracebacks:
+            response[u"error"][u"trace"] = format_tb(reason.getTracebackObject())
+
+        body = json.dumps(response)
+        self.setResponseCode(http.INTERNAL_SERVER_ERROR)
+        self.setHeader(b'content-type', self.defaultContentType)
+        self.setHeader(b'content-length', intToBytes(len(body)))
+        self.write(body)
+        self.finish()
+        return reason
diff --git a/Tribler/Core/Session.py b/Tribler/Core/Session.py
index 835f878f13e..a7fbb8ec8ff 100644
--- a/Tribler/Core/Session.py
+++ b/Tribler/Core/Session.py
@@ -637,16 +637,16 @@ def search_remote_channels(self, keywords):
             raise OperationNotEnabledByConfigurationException("channel_search is not enabled")
         self.lm.search_manager.search_for_channels(keywords)
 
-    def create_channel(self, name, description, mode=u'open'):
+    def create_channel(self, name, description, mode=u'closed'):
         """
         Creates a new Channel.
         :param name: Name of the Channel.
         :param description: Description of the Channel.
         :param mode: Mode of the Channel ('open', 'semi-open', or 'closed').
+        :return: Channel ID
+        :raises DuplicateChannelNameError if name already exists
         """
-        if not self.get_enable_channel_search():
-            raise OperationNotEnabledByConfigurationException("channel_search is not enabled")
-        self.lm.channel_manager.create_channel(name, description, mode)
+        return self.lm.channel_manager.create_channel(name, description, mode)
 
     def check_torrent_health(self, infohash):
         """
diff --git a/Tribler/Core/exceptions.py b/Tribler/Core/exceptions.py
index d0694bf62b8..0972c126da0 100644
--- a/Tribler/Core/exceptions.py
+++ b/Tribler/Core/exceptions.py
@@ -48,6 +48,14 @@ def __init__(self, msg=None):
         TriblerException.__init__(self, msg)
 
 
+class DuplicateChannelNameError(TriblerException):
+
+    """ The Channel name already exists in the ChannelManager channel list,
+    i.e., one of your own Channels with the same name already exists. """
+
+    pass
+
+
 class DuplicateDownloadException(TriblerException):
 
     """ The Download already exists in the Session, i.e., a Download for
@@ -65,6 +73,7 @@ class TorrentDefNotFinalizedException(TriblerException):
     def __init__(self, msg=None):
         TriblerException.__init__(self, msg)
 
+
 class TorrentFileException(TriblerException):
 
     """ The torrent file that is used is corrupt or cannot be read. """
diff --git a/Tribler/Test/Core/Modules/RestApi/base_api_test.py b/Tribler/Test/Core/Modules/RestApi/base_api_test.py
index 4d4a5abef12..d0163e87e58 100644
--- a/Tribler/Test/Core/Modules/RestApi/base_api_test.py
+++ b/Tribler/Test/Core/Modules/RestApi/base_api_test.py
@@ -50,7 +50,7 @@ def parse_body(self, body):
 
     def parse_response(self, response):
         self.assertEqual(response.code, self.expected_response_code)
-        if response.code == 200 or response.code == 400:
+        if response.code in (200, 400, 500):
             return readBody(response)
         return succeed(None)
 
diff --git a/Tribler/Test/Core/Modules/RestApi/test_my_channel_endpoints.py b/Tribler/Test/Core/Modules/RestApi/test_my_channel_endpoints.py
index f97c229a2cf..22b788976ea 100644
--- a/Tribler/Test/Core/Modules/RestApi/test_my_channel_endpoints.py
+++ b/Tribler/Test/Core/Modules/RestApi/test_my_channel_endpoints.py
@@ -4,21 +4,30 @@
 from Tribler.Core.Modules.channel.channel_manager import ChannelManager
 from Tribler.Core.Utilities.twisted_thread import deferred
 from Tribler.Core.simpledefs import NTFY_CHANNELCAST
+from Tribler.Core.exceptions import DuplicateChannelNameError
 from Tribler.Test.Core.Modules.RestApi.base_api_test import AbstractApiTest
 
 
 class ChannelCommunityMock(object):
 
-    def __init__(self, channel_id):
-        self.name = "Channel name"
+    def __init__(self, channel_id, name, description, mode):
         self.cid = 'a' * 20
-        self.channel_id = channel_id
+        self._channel_id = channel_id
+        self._channel_name = name
+        self._channel_description = description
+        self._channel_mode = mode
+
+    def get_channel_id(self):
+        return self._channel_id
 
     def get_channel_name(self):
-        return self.name
+        return self._channel_name
 
-    def get_channel_id(self):
-        return self.channel_id
+    def get_channel_description(self):
+        return self._channel_description
+
+    def get_channel_mode(self):
+        return self._channel_mode
 
 
 class AbstractTestMyChannelEndpoints(AbstractApiTest):
@@ -35,15 +44,18 @@ def create_my_channel(self, name, description):
         self.channel_db_handler.on_channel_from_dispersy('fakedispersyid', None, name, description)
         return self.channel_db_handler.getMyChannelId()
 
-    def create_fake_channel(self, channel_name, channel_description):
+    def create_fake_channel(self, name, description, mode=u'closed'):
         # Use a fake ChannelCommunity object (we don't actually want to create a Dispersy community)
-        my_channel_id = self.create_my_channel(channel_name, channel_description)
+        my_channel_id = self.create_my_channel(name, description)
         self.session.lm.channel_manager = ChannelManager(self.session)
 
-        channel_obj = ChannelObject(self.session, ChannelCommunityMock(my_channel_id))
+        channel_obj = ChannelObject(self.session, ChannelCommunityMock(my_channel_id, name, description, mode))
         self.session.lm.channel_manager._channel_list.append(channel_obj)
         return my_channel_id
 
+    def create_fake_channel_with_existing_name(self, name, description, mode=u'closed'):
+        raise DuplicateChannelNameError(u"Channel name already exists: %s" % name)
+
     def insert_torrents_into_my_channel(self, torrent_list):
         self.channel_db_handler.on_torrents_from_dispersy(torrent_list)
 
@@ -58,12 +70,110 @@ def test_my_channel_unknown_endpoint(self):
         self.should_check_equality = False
         return self.do_request('mychannel/thisendpointdoesnotexist123', expected_code=404)
 
+    @deferred(timeout=10)
+    def test_my_channel_endpoint_create(self):
+        """
+        Testing whether the API returns the right JSON data if a channel is created
+        """
+
+        def verify_channel_created(body):
+            channel_obj = self.session.lm.channel_manager._channel_list[0]
+            self.assertEqual(channel_obj.name, post_data["name"])
+            self.assertEqual(channel_obj.description, post_data["description"])
+            self.assertEqual(channel_obj.mode, post_data["mode"])
+            self.assertDictEqual(json.loads(body), {"added": channel_obj.channel_id})
+
+        post_data = {
+            "name": "John Smit's channel",
+            "description": "Video's of my cat",
+            "mode": "semi-open"
+        }
+        self.session.create_channel = self.create_fake_channel
+        self.should_check_equality = False
+        return self.do_request('mychannel', expected_code=200, expected_json=None,
+                               request_type='PUT', post_data=post_data).addCallback(verify_channel_created)
+
+    @deferred(timeout=10)
+    def test_my_channel_endpoint_create_default_mode(self):
+        """
+        Testing whether the API returns the right JSON data if a channel is created
+         """
+
+        def verify_channel_created(body):
+            channel_obj = self.session.lm.channel_manager._channel_list[0]
+            self.assertEqual(channel_obj.name, post_data["name"])
+            self.assertEqual(channel_obj.description, post_data["description"])
+            self.assertEqual(channel_obj.mode, u'closed')
+            self.assertDictEqual(json.loads(body), {"added": channel_obj.channel_id})
+
+        post_data = {
+            "name": "John Smit's channel",
+            "description": "Video's of my cat"
+        }
+        self.session.create_channel = self.create_fake_channel
+        self.should_check_equality = False
+        return self.do_request('mychannel', expected_code=200, expected_json=None,
+                               request_type='PUT', post_data=post_data).addCallback(verify_channel_created)
+
+    @deferred(timeout=10)
+    def test_my_channel_endpoint_create_duplicate_name_error(self):
+        """
+        Testing whether the API returns a formatted 500 error if DuplicateChannelNameError is raised
+        """
+
+        def verify_error_message(body):
+            error_response = json.loads(body)
+            expected_response = {
+                u"error": {
+                    u"handled": True,
+                    u"code": u"DuplicateChannelNameError",
+                    u"message": u"Channel name already exists: %s" % post_data["name"]
+                }
+            }
+            self.assertDictContainsSubset(expected_response[u"error"], error_response[u"error"])
+
+        post_data = {
+            "name": "John Smit's channel",
+            "description": "Video's of my cat",
+            "mode": "semi-open"
+        }
+        self.session.create_channel = self.create_fake_channel_with_existing_name
+        self.should_check_equality = False
+        return self.do_request('mychannel', expected_code=500, expected_json=None, request_type='PUT',
+                               post_data=post_data).addCallback(verify_error_message)
+
+    @deferred(timeout=10)
+    def test_my_channel_endpoint_create_no_name_param(self):
+        """
+        Testing whether the API returns a 400 and error if the name parameter is not passed
+        """
+        post_data = {
+            "description": "Video's of my cat",
+            "mode": "semi-open"
+        }
+        expected_json = {"error": "name parameter missing"}
+        return self.do_request('mychannel', expected_code=400, expected_json=expected_json, request_type='PUT',
+                               post_data=post_data)
+
+    @deferred(timeout=10)
+    def test_my_channel_endpoint_create_no_description_param(self):
+        """
+        Testing whether the API returns a 400 and error if the name parameter is not passed
+        """
+        post_data = {
+            "name": "John Smit's channel",
+            "mode": "semi-open"
+        }
+        expected_json = {"error": "description parameter missing"}
+        return self.do_request('mychannel', expected_code=400, expected_json=expected_json, request_type='PUT',
+                               post_data=post_data)
+
     @deferred(timeout=10)
     def test_my_channel_overview_endpoint_no_my_channel(self):
         """
         Testing whether the API returns response code 404 if no channel has been created
         """
-        return self.do_request('mychannel/overview', expected_code=404)
+        return self.do_request('mychannel', expected_code=404)
 
     @deferred(timeout=10)
     def test_my_channel_overview_endpoint_with_channel(self):
@@ -74,7 +184,7 @@ def test_my_channel_overview_endpoint_with_channel(self):
                                       u'identifier': 'fakedispersyid'.encode('hex')}}
         self.create_my_channel(channel_json[u'overview'][u'name'], channel_json[u'overview'][u'description'])
 
-        return self.do_request('mychannel/overview', expected_code=200, expected_json=channel_json)
+        return self.do_request('mychannel', expected_code=200, expected_json=channel_json)
 
     @deferred(timeout=10)
     def test_my_channel_torrents_endpoint_no_my_channel(self):
@@ -83,22 +193,23 @@ def test_my_channel_torrents_endpoint_no_my_channel(self):
         """
         return self.do_request('mychannel/torrents', expected_code=404)
 
-    def verify_torrents_json(self, body):
-        torrents_dict = json.loads(body)
-        self.assertTrue(torrents_dict["torrents"])
-        self.assertEqual(len(torrents_dict["torrents"]), 1)
-
     @deferred(timeout=10)
     def test_torrents_endpoint_with_channel(self):
         """
         Testing whether the API returns the right JSON data if a torrents from a channel are fetched
         """
+
+        def verify_torrents_json(body):
+            torrents_dict = json.loads(body)
+            self.assertTrue(torrents_dict["torrents"])
+            self.assertEqual(len(torrents_dict["torrents"]), 1)
+
         self.should_check_equality = False
         my_channel_id = self.create_my_channel("my channel", "this is a short description")
         torrent_list = [[my_channel_id, 1, 1, ('a' * 40).decode('hex'), 1460000000, "ubuntu-torrent.iso", [], []]]
         self.insert_torrents_into_my_channel(torrent_list)
 
-        return self.do_request('mychannel/torrents', expected_code=200).addCallback(self.verify_torrents_json)
+        return self.do_request('mychannel/torrents', expected_code=200).addCallback(verify_torrents_json)
 
     @deferred(timeout=10)
     def test_rss_feeds_endpoint_no_my_channel(self):
@@ -117,8 +228,9 @@ def test_rss_feeds_endpoint_with_channel(self):
         Testing whether the API returns the right JSON data if a rss feeds from a channel are fetched
         """
         expected_json = {u'rssfeeds': [{u'url': u'http://test1.com/feed.xml'}, {u'url': u'http://test2.com/feed.xml'}]}
-        self.create_fake_channel("my channel", "this is a short description")
-        channel_obj = self.session.lm.channel_manager.get_channel("Channel name")
+        channel_name = "my channel"
+        self.create_fake_channel(channel_name, "this is a short description")
+        channel_obj = self.session.lm.channel_manager.get_channel(channel_name)
         for rss_item in expected_json[u'rssfeeds']:
             channel_obj.create_rss_feed(rss_item[u'url'])
 
@@ -151,6 +263,7 @@ def test_add_rss_feed_with_channel(self):
         """
         Testing whether the API returns a 200 if a channel has been created and when adding a rss feed
         """
+
         def verify_rss_added(_):
             channel_obj = self.session.lm.channel_manager.get_my_channel(my_channel_id)
             self.assertEqual(channel_obj.get_rss_feed_url_list(), ["http://rssfeed.com/rss.xml"])
diff --git a/Tribler/Test/Core/Modules/RestApi/test_rest_manager.py b/Tribler/Test/Core/Modules/RestApi/test_rest_manager.py
new file mode 100644
index 00000000000..0647ba8e13d
--- /dev/null
+++ b/Tribler/Test/Core/Modules/RestApi/test_rest_manager.py
@@ -0,0 +1,37 @@
+import json
+
+from Tribler.Core.exceptions import TriblerException
+
+from base_api_test import AbstractApiTest
+
+
+class RestRequestTest(AbstractApiTest):
+
+    def throw_unhandled_exception(self, name, description, mode=u'closed'):
+        raise TriblerException(u"Oops! Something went wrong. Please restart Tribler")
+
+    def test_unhandled_exception(self):
+        """
+        Testing whether the API returns a formatted 500 error if an unhandled Exception is raised
+        """
+
+        def verify_error_message(body):
+            error_response = json.loads(body)
+            expected_response = {
+                u"error": {
+                    u"handled": False,
+                    u"code": u"TriblerException",
+                    u"message": u"Oops! Something went wrong. Please restart Tribler"
+                }
+            }
+            self.assertDictContainsSubset(expected_response[u"error"], error_response[u"error"])
+
+        post_data = {
+            "name": "John Smit's channel",
+            "description": "Video's of my cat",
+            "mode": "semi-open"
+        }
+        self.session.create_channel = self.throw_unhandled_exception
+        self.should_check_equality = False
+        return self.do_request('mychannel', expected_code=500, expected_json=None, request_type='PUT',
+                               post_data=post_data).addCallback(verify_error_message)
diff --git a/Tribler/Test/Core/Modules/channel/__init__.py b/Tribler/Test/Core/Modules/channel/__init__.py
new file mode 100644
index 00000000000..7cd1ded3af7
--- /dev/null
+++ b/Tribler/Test/Core/Modules/channel/__init__.py
@@ -0,0 +1,3 @@
+"""
+This testing package contains tests for the channel module.
+"""
diff --git a/Tribler/Test/Core/Modules/channel/test_channel_manager.py b/Tribler/Test/Core/Modules/channel/test_channel_manager.py
new file mode 100644
index 00000000000..db247711c7b
--- /dev/null
+++ b/Tribler/Test/Core/Modules/channel/test_channel_manager.py
@@ -0,0 +1,33 @@
+from Tribler.Test.Core.base_test import TriblerCoreTest
+from Tribler.Core.Session import Session
+from Tribler.Core.SessionConfig import SessionStartupConfig
+from Tribler.Core.Modules.channel.channel import ChannelObject
+from Tribler.Core.exceptions import DuplicateChannelNameError
+from Tribler.Core.Modules.channel.channel_manager import ChannelManager
+from Tribler.dispersy.util import blocking_call_on_reactor_thread
+
+
+class TestChannelManager(TriblerCoreTest):
+
+    @blocking_call_on_reactor_thread
+    def test_create_channel_duplicate_name_error(self):
+        self.config = SessionStartupConfig()
+        self.session = Session(self.config, ignore_singleton=True)
+
+        class LmMock(object):
+            channel_manager = ChannelManager(self.session)
+
+        self.session.lm = LmMock()
+
+        class MockCommunity(object):
+            cid = ""
+
+            def get_channel_name(self):
+                return "Channel name"
+
+        channel_obj = ChannelObject(self.session, MockCommunity(), is_created=True)
+        self.session.lm.channel_manager._channel_list = [channel_obj]
+
+        with self.assertRaises(DuplicateChannelNameError) as cm:
+            self.session.lm.channel_manager.create_channel("Channel name", "description", "open")
+        self.assertEqual(cm.exception.message, u"Channel name already exists: Channel name")
diff --git a/Tribler/Test/Core/test_session.py b/Tribler/Test/Core/test_session.py
index 6208fd76ce9..238239605e9 100644
--- a/Tribler/Test/Core/test_session.py
+++ b/Tribler/Test/Core/test_session.py
@@ -39,3 +39,19 @@ def test_torrent_store_delete(self):
             session.lm.torrent_store.close()
 
         self.assertTrue(raised_key_error)
+
+    def test_create_channel(self):
+        """
+        Test the pass through function of Session.create_channel to the ChannelManager.
+        """
+
+        class LmMock(object):
+            class ChannelManager(object):
+                def create_channel(self, name, description, mode=u"closed"):
+                    pass
+            channel_manager = ChannelManager()
+
+        config = SessionStartupConfig()
+        session = Session(config, ignore_singleton=True)
+        session.lm = LmMock
+        session.create_channel("name", "description", "open")
diff --git a/doc/Tribler REST API.md b/doc/Tribler REST API.md
index cc8381644fd..7ec3d2870b0 100644
--- a/doc/Tribler REST API.md	
+++ b/doc/Tribler REST API.md	
@@ -12,6 +12,29 @@ Some requests require one or more parameters. These parameters are passed using
 curl -X PUT http://localhost:8085/mychannel/rssfeeds/http%3A%2F%2Frssfeed.com%2Frss.xml
 ```
 
+## Error handling
+
+If an unhandled exception occurs the response will have code HTTP 500 and look like this:
+```json
+{
+    "error": {
+        "handled": False,
+        "code": "SomeException",
+        "message": "Human readable error message"
+    }
+}
+```
+If a valid request of a client caused a recoverable error the response will have code HTTP 500 and look like this:
+```json
+{
+    "error": {
+        "handled": True,
+        "code": "DuplicateChannelNameError",
+        "message": "Channel name already exists: foo"
+    }
+}
+```
+
 ## Endpoints
 
 ### Channels
@@ -28,7 +51,8 @@ curl -X PUT http://localhost:8085/mychannel/rssfeeds/http%3A%2F%2Frssfeed.com%2F
 
 | Endpoint | Description |
 | ---- | --------------- |
-| GET /mychannel/overview | Get the name, description and identifier of your channel |
+| GET /mychannel         | Get the name, description and identifier of your channel |
+| PUT /mychannel         | Create your own new channel |
 | GET /mychannel/torrents | Get a list of torrents in your channel |
 | GET /mychannel/rssfeeds | Get a list of rss feeds used by your channel |
 | PUT /mychannel/rssfeeds/{feedurl} | Add a rss feed to your channel |
@@ -149,7 +173,7 @@ Unsubscribe from a specific channel. Returns error 404 if you are not subscribed
 }
 ```
 
-## `GET /mychannel/overview`
+## `GET /mychannel`
 
 Returns an overview of the channel of the user. This includes the name, description and identifier of the channel.
 
@@ -165,6 +189,20 @@ Returns an overview of the channel of the user. This includes the name, descript
 }
 ```
 
+## `PUT /mychannel`
+
+Create your own new channel.
+
+### Example request:
+
+```json
+{
+    "name": "John Smit's channel",
+    "description": "Video's of my cat",
+    "mode" (optional): "open" or "semi-open" or "closed" (default)
+}
+```
+
 ## `GET /mychannel/torrents`
 
 Returns a list of torrents in your channel. Each torrent item in the list contains the infohash, name and the timestamp of addition of the torrent.