--- a
+++ b/qiita_db/handlers/plugin.py
@@ -0,0 +1,265 @@
+# -----------------------------------------------------------------------------
+# Copyright (c) 2014--, The Qiita Development Team.
+#
+# Distributed under the terms of the BSD 3-clause License.
+#
+# The full license is in the file LICENSE, distributed with this software.
+# -----------------------------------------------------------------------------
+
+from json import loads
+from glob import glob
+from os.path import join
+
+from tornado.web import HTTPError
+
+from .oauth2 import OauthBaseHandler, authenticate_oauth
+from qiita_core.qiita_settings import qiita_config
+import qiita_db as qdb
+
+
+def _get_plugin(name, version):
+    """Returns the plugin with the given name and version
+
+    Parameters
+    ----------
+    name : str
+        The name of the plugin
+    version : str
+        The version of the plugin
+
+    Returns
+    -------
+    qiita_db.software.Software
+        The requested plugin
+
+    Raises
+    ------
+    HTTPError
+        If the plugin does not exist, with error code 404
+        If there is a problem instantiating the plugin, with error code 500
+    """
+    try:
+        plugin = qdb.software.Software.from_name_and_version(name, version)
+    except qdb.exceptions.QiitaDBUnknownIDError:
+        raise HTTPError(404)
+    except Exception as e:
+        raise HTTPError(500, reason='Error instantiating plugin %s %s: %s'
+                        % (name, version, str(e)))
+
+    return plugin
+
+
+class PluginHandler(OauthBaseHandler):
+    @authenticate_oauth
+    def get(self, name, version):
+        """Retrieve the plugin information
+
+        Parameters
+        ----------
+        name : str
+            The plugin name
+        version : str
+            The plugin version
+
+        Returns
+        -------
+        dict
+            The plugin information:
+            'name': the plugin name
+            'version': the plugin version
+            'description': the plugin description
+            'commands': list of the plugin commands
+            'publications': list of publications
+            'default_workflows': list of the plugin default workflows
+            'type': the plugin type
+            'active': whether the plugin is active or not
+        """
+        with qdb.sql_connection.TRN:
+            plugin = _get_plugin(name, version)
+            response = {
+                'name': plugin.name,
+                'version': plugin.version,
+                'description': plugin.description,
+                'commands': [c.name for c in plugin.commands],
+                'publications': [{'DOI': doi, 'PubMed': pubmed}
+                                 for doi, pubmed in plugin.publications],
+                'type': plugin.type,
+                'active': plugin.active}
+        self.write(response)
+
+
+class CommandListHandler(OauthBaseHandler):
+    @authenticate_oauth
+    def post(self, name, version):
+        """Create new command for a plugin
+
+        Parameters
+        ----------
+        name : str
+            The name of the plugin
+        version : str
+            The version of the plugin
+        """
+        with qdb.sql_connection.TRN:
+            plugin = _get_plugin(name, version)
+
+            cmd_name = self.get_argument('name')
+            cmd_desc = self.get_argument('description')
+            req_params = loads(self.get_argument('required_parameters'))
+            opt_params = loads(self.get_argument('optional_parameters'))
+
+            for p_name, vals in opt_params.items():
+                if vals[0].startswith('mchoice'):
+                    opt_params[p_name] = [vals[0], loads(vals[1])]
+                    if len(vals) == 2:
+                        opt_params[p_name] = [vals[0], loads(vals[1])]
+                    elif len(vals) == 4:
+                        opt_params[p_name] = [vals[0], loads(vals[1]), vals[2],
+                                              vals[3]]
+                    else:
+                        raise qdb.exceptions.QiitaDBError(
+                            "Malformed parameters dictionary, the format "
+                            "should be either {param_name: [parameter_type, "
+                            "default]} or {parameter_name: (parameter_type, "
+                            "default, name_order, check_biom_merge)}. Found: "
+                            "%s for parameter name %s"
+                            % (vals, p_name))
+                # adding an extra element to make sure the parser knows this is
+                # an optional parameter
+                opt_params[p_name].extend(['qiita_optional_parameter'])
+
+            outputs = self.get_argument('outputs', None)
+            if outputs:
+                outputs = loads(outputs)
+            dflt_param_set = loads(self.get_argument('default_parameter_sets'))
+            analysis_only = self.get_argument('analysis_only', False)
+
+            parameters = req_params
+            parameters.update(opt_params)
+
+            cmd = qdb.software.Command.create(
+                plugin, cmd_name, cmd_desc, parameters, outputs,
+                analysis_only=analysis_only)
+
+            if dflt_param_set is not None:
+                for name, vals in dflt_param_set.items():
+                    qdb.software.DefaultParameters.create(name, cmd, **vals)
+
+        self.finish()
+
+
+def _get_command(plugin_name, plugin_version, cmd_name):
+    """Returns the command with the given name within the given plugin
+
+    Parameters
+    ----------
+    plugin_name : str
+        The name of the plugin
+    plugin_version : str
+        The version of the plugin
+    cmd_name : str
+        The name of the command in the plugin
+
+    Returns
+    -------
+    qiita_db.software.Command
+        The requested command
+
+    Raises
+    ------
+    HTTPError
+        If the command does not exist, with error code 404
+        If there is a problem instantiating the command, with error code 500
+    """
+    plugin = _get_plugin(plugin_name, plugin_version)
+    try:
+        cmd = plugin.get_command(cmd_name)
+    except qdb.exceptions.QiitaDBUnknownIDError:
+        raise HTTPError(404)
+    except Exception as e:
+        raise HTTPError(500, reason='Error instantiating cmd %s of plugin '
+                        '%s %s: %s' % (cmd_name, plugin_name,
+                                       plugin_version, str(e)))
+
+    return cmd
+
+
+class CommandHandler(OauthBaseHandler):
+    @authenticate_oauth
+    def get(self, plugin_name, plugin_version, cmd_name):
+        """Retrieve the command information
+
+        Parameters
+        ----------
+        plugin_name : str
+            The plugin name
+        plugin_version : str
+            The plugin version
+        cmd_name : str
+            The command name
+
+        Returns
+        -------
+        dict
+            The command information
+            'name': the command name
+            'description': the command description
+            'required_parameters': dict with the required parameters, in the
+                format {parameter_name: [type, [subtypes]]}
+            'optional_parameters': dict with the optional parameters, in the
+                format {parameter_name: [type, default value]}
+            'default_parameter_sets': dict with the default parameter sets, in
+                the format {parameter set name: {parameter_name: value}}
+        """
+        with qdb.sql_connection.TRN:
+            cmd = _get_command(plugin_name, plugin_version, cmd_name)
+            response = {
+                'name': cmd.name,
+                'description': cmd.description,
+                'required_parameters': cmd.required_parameters,
+                'optional_parameters': cmd.optional_parameters,
+                'default_parameter_sets': {
+                    p.name: p.values for p in cmd.default_parameter_sets},
+                'outputs': cmd.outputs}
+        self.write(response)
+
+
+class CommandActivateHandler(OauthBaseHandler):
+    @authenticate_oauth
+    def post(self, plugin_name, plugin_version, cmd_name):
+        """Activates the command
+
+        Parameters
+        ----------
+        plugin_name : str
+            The plugin name
+        plugin_version : str
+            The plugin version
+        cmd_name : str
+            The command name
+        """
+        with qdb.sql_connection.TRN:
+            cmd = _get_command(plugin_name, plugin_version, cmd_name)
+            cmd.activate()
+
+        self.finish()
+
+
+class ReloadPluginAPItestHandler(OauthBaseHandler):
+    @authenticate_oauth
+    def post(self):
+        """Reloads the plugins"""
+        conf_files = sorted(glob(join(qiita_config.plugin_dir, "*.conf")))
+        software = set([qdb.software.Software.from_file(fp, update=True)
+                        for fp in conf_files])
+        definition = set(
+            [s for s in software if s.type == 'artifact definition'])
+        transformation = software - definition
+        for s in definition:
+            s.activate()
+            s.register_commands()
+        for s in transformation:
+            s.activate()
+            s.register_commands()
+
+        self.finish()