diff --git a/client/src/app/Routes.js b/client/src/app/Routes.js
index 849c780d..b3f0312e 100644
--- a/client/src/app/Routes.js
+++ b/client/src/app/Routes.js
@@ -35,6 +35,7 @@ import AdminPanelNewTickets from 'app/admin/panel/tickets/admin-panel-new-ticket
 import AdminPanelAllTickets from 'app/admin/panel/tickets/admin-panel-all-tickets';
 import AdminPanelViewTicket from 'app/admin/panel/tickets/admin-panel-view-ticket';
 import AdminPanelCustomResponses from 'app/admin/panel/tickets/admin-panel-custom-responses';
+import AdminPanelCustomTags from 'app/admin/panel/tickets/admin-panel-custom-tags';
 
 import AdminPanelListUsers from 'app/admin/panel/users/admin-panel-list-users';
 import AdminPanelViewUser from 'app/admin/panel/users/admin-panel-view-user';
@@ -114,6 +115,7 @@ export default (
                         <Route path="all-tickets" component={AdminPanelAllTickets} />
                         <Route path="custom-responses" component={AdminPanelCustomResponses} />
                         <Route path="view-ticket/:ticketNumber" component={AdminPanelViewTicket} />
+                        <Route path="custom-tags" component={AdminPanelCustomTags} />
                     </Route>
 
                     <Route path="users">
diff --git a/client/src/app/admin/panel/admin-panel-menu.js b/client/src/app/admin/panel/admin-panel-menu.js
index 5481538c..3a10570c 100644
--- a/client/src/app/admin/panel/admin-panel-menu.js
+++ b/client/src/app/admin/panel/admin-panel-menu.js
@@ -135,6 +135,11 @@ class AdminPanelMenu extends React.Component {
                         name: i18n('CUSTOM_RESPONSES'),
                         path: '/admin/panel/tickets/custom-responses',
                         level: 2
+                    },
+                    {
+                        name: 'Customtags i18n',
+                        path: '/admin/panel/tickets/custom-tags',
+                        level: 1
                     }
                 ])
             },
diff --git a/client/src/app/admin/panel/tickets/admin-panel-custom-tags.js b/client/src/app/admin/panel/tickets/admin-panel-custom-tags.js
new file mode 100644
index 00000000..6cc2ec9b
--- /dev/null
+++ b/client/src/app/admin/panel/tickets/admin-panel-custom-tags.js
@@ -0,0 +1,261 @@
+import React from 'react';
+import _ from 'lodash';
+import {connect}  from 'react-redux';
+
+import i18n from 'lib-app/i18n';
+import API from 'lib-app/api-call';
+import AdminDataActions from 'actions/admin-data-actions';
+
+import AreYouSure from 'app-components/are-you-sure';
+import LanguageSelector from 'app-components/language-selector';
+
+import Icon from 'core-components/icon';
+import Button from 'core-components/button';
+import Header from 'core-components/header';
+import Listing from 'core-components/listing';
+import Loading from 'core-components/loading';
+import Form from 'core-components/form';
+import FormField from 'core-components/form-field';
+import SubmitButton from 'core-components/submit-button';
+import TextEditor from 'core-components/text-editor';
+import ModalContainer from 'app-components/modal-container';
+import ColorSelector from 'core-components/color-selector';
+class TagList extends React.Component {
+    constructor(props) {
+        super(props);
+
+        const list = this.props.tags.map((tag) => {
+            <h1>{tag.name}</h1>;
+        })
+    }
+    render() {
+        return (
+            <div>
+                {list}
+            </div>
+        );
+    }
+}
+class AdminPanelCustomTags extends React.Component {
+    static defaultProps = {
+        items: [],
+    };
+
+    state = {
+        formClicked: false,
+        showForm: false,
+        formLoading: false,
+        selectedIndex: -1,
+        errors: {},
+        originalForm: {
+            title: '',
+            content: TextEditor.createEmpty(),
+            language: this.props.language
+        },
+        form: {
+            title: '',
+            content: TextEditor.createEmpty(),
+            language: this.props.language
+        },
+        tagList: {}  //
+    };
+
+    componentDidMount() {
+        if (!this.props.loaded) {
+            this.retrieveCustomResponses();
+        }
+    }
+
+    render() {
+        return (
+            <div className="admin-panel-custom-tags">
+                <Header title={i18n('CUSTOM_TAGS')} description={i18n('CUSTOM_TAGS_DESCRIPTION')} />
+                {(this.props.loaded) ? this.renderContent() : this.renderLoading()}
+            </div>
+        );
+    }
+
+    renderContent() {
+        return (
+            <div className="row">
+                <div className="col-md-3">
+                <Button onClick={this.onCreateTag.bind(this)} type="secondary" ><Icon name="pencil"/>'NUEVO TAGi18n'</Button>
+                <TagList tags={this.state.tagList}/>
+                </div>
+            </div>
+        );
+    }
+    onCreateTag() {
+        ModalContainer.openModal(
+            <div>
+            <Header title={'new tags'} description={i18n('Here you can add a topic that works as a category for articles.')} />
+            <Form values={this.state.values} onChange={this.onFormChange.bind(this)} onSubmit={this.onSubmitTag.bind(this)} loading={this.state.loading}>
+                <FormField name="title" label={i18n('TITLE')} fieldProps={{size: 'large'}} validation="TITLE" required />
+                <FormField name="color" className="topic-edit-modal__color" label={i18n('COLOR')} decorator={ColorSelector} />
+                <FormField className="topic-edit-modal__private" label={i18n('PRIVATE')} name="private" field="checkbox"/>
+
+                <SubmitButton className="topic-edit-modal__save-button" type="secondary" size="small">
+                    {i18n('SAVE')}
+                </SubmitButton>
+                <Button className="topic-edit-modal__discard-button" onClick={this.onDiscardClick.bind(this)} size="small">
+                    {i18n('CANCEL')}
+                </Button>
+            </Form>
+            </div>
+        );
+    }
+    onSubmitTag() {
+        API.call({
+            path: '/ticket/add-tag',
+            data: {
+                name: form.title,
+                color: form.content,
+            }
+        }).then(() => {
+            this.context.closeModal();
+            this.updateTagList();
+
+            if(this.props.onChange) {
+                this.props.onChange();
+            }
+        }).catch(() => {
+            this.setState({
+              loading: false
+            });
+        });
+    }
+    onFormChange(form) {
+        this.setState({
+            values: form
+        });
+    }
+    onDiscardClick(event) {
+        event.preventDefault();
+        this.context.closeModal();
+    }
+    renderLoading() {
+        return (
+            <div className="admin-panel-custom-responses__loading">
+                <Loading backgrounded size="large"/>
+            </div>
+        );
+    }
+
+    renderOptionalButtons() {
+        return (
+            <div className="admin-panel-custom-responses__optional-buttons">
+                <div className="admin-panel-custom-responses__discard-button">
+                    {this.isEdited() ? <Button onClick={this.onDiscardChangesClick.bind(this)}>{i18n('DISCARD_CHANGES')}</Button> : null}
+                </div>
+                <div className="admin-panel-custom-responses__delete-button">
+                    <Button onClick={this.onDeleteClick.bind(this)}>{i18n('DELETE')}</Button>
+                </div>
+            </div>
+        );
+    }
+
+    onItemChange(index) {
+        if(this.isEdited()) {
+            AreYouSure.openModal(i18n('WILL_LOSE_CHANGES'), this.updateForm.bind(this, index));
+        } else {
+            this.updateForm(index);
+        }
+    }
+
+    onSubmit() {
+        this.setState({
+          loading: true
+        });
+
+        API.call({
+            path: (this.props.addForm) ? '/article/add-topic' : '/article/edit-topic',
+            data: {
+                topicId: this.props.topicId,
+                name: this.state.values['title'],
+                icon: this.state.values['icon'],
+                iconColor: this.state.values['color'],
+                private: this.state.values['private']*1
+            }
+        }).then(() => {
+            this.context.closeModal();
+
+            if(this.props.onChange) {
+                this.props.onChange();
+            }
+        }).catch(() => {
+            this.setState({
+              loading: false
+            });
+        });
+    }
+
+    onDiscardChangesClick(event) {
+        event.preventDefault();
+        this.onItemChange(this.state.selectedIndex);
+    }
+
+    onDeleteClick(event) {
+        event.preventDefault();
+        AreYouSure.openModal(i18n('WILL_DELETE_CUSTOM_RESPONSE'), this.deleteCustomResponse.bind(this));
+    }
+
+    deleteCustomResponse() {
+        API.call({
+            path: '/ticket/delete-custom-response',
+            data: {
+                id: this.props.items[this.state.selectedIndex].id
+            }
+        }).then(() => {
+            this.retrieveCustomResponses();
+            this.onItemChange(-1);
+        });
+    }
+    updateTagList() {
+        API.call({
+            path: '/ticket/get-tags'
+        }).then(() => {
+            this.setState({
+                tagList: data
+            });
+        });
+    }
+
+    updateForm(index) {
+        let form = _.clone(this.state.form);
+
+        form.title = (this.props.items[index] && this.props.items[index].name) || '';
+        form.content = TextEditor.getEditorStateFromHTML((this.props.items[index] && this.props.items[index].content) || '');
+        form.language = (this.props.items[index] && this.props.items[index].language) || this.props.language;
+
+        this.setState({
+            formClicked: false,
+            showForm: true,
+            selectedIndex: index,
+            formLoading: false,
+            originalForm: form,
+            form: form,
+            errors: {}
+        });
+    }
+
+    retrieveCustomResponses() {
+        this.props.dispatch(AdminDataActions.retrieveCustomResponses());
+    }
+
+    isEdited() {
+        return this.state.form.title && this.state.formClicked && (
+            this.state.form.title != this.state.originalForm.title ||
+            this.state.form.content != this.state.originalForm.content ||
+            this.state.form.language != this.state.originalForm.language
+        );
+    }
+}
+
+export default connect((store) => {
+    return {
+        allowedLanguages: store.config.allowedLanguages,
+        language: store.config.language,
+        loaded: store.adminData.customResponsesLoaded,
+        items: store.adminData.customResponses
+    };
+})(AdminPanelCustomTags);
diff --git a/client/src/app/admin/panel/tickets/admin-panel-custom-tags.scss b/client/src/app/admin/panel/tickets/admin-panel-custom-tags.scss
new file mode 100644
index 00000000..7728e33a
--- /dev/null
+++ b/client/src/app/admin/panel/tickets/admin-panel-custom-tags.scss
@@ -0,0 +1,31 @@
+.admin-panel-custom-tags {
+    &__loading {
+        height: 300px;
+    }
+
+    &__item-flag {
+        float: right;
+    }
+
+    &__actions {
+        text-align: left;
+    }
+
+    &__save-button {
+        display: inline-block;
+        margin-right: 30px;
+    }
+
+    &__optional-buttons {
+        display: inline;
+    }
+
+    &__discard-button {
+        display: inline-block;
+    }
+
+    &__delete-button {
+        display: inline-block;
+        float: right;
+    }
+}
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index 19496747..9b2a9bc4 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -47,6 +47,7 @@ export default {
     'NEW_TICKETS': 'New Tickets',
     'ALL_TICKETS': 'All Tickets',
     'CUSTOM_RESPONSES': 'Custom Responses',
+    'CUSTOM_TAGS': 'Custom Tags',
     'LIST_USERS': 'List Users',
     'BAN_USERS': 'Ban Users',
     'LIST_ARTICLES': 'Article List',
@@ -283,6 +284,7 @@ export default {
     'ACCOUNT_DESCRIPTION': 'All your tickets are stored in your account\'s profile. Keep track of all your tickets you send to our staff team.',
     'SUPPORT_CENTER_DESCRIPTION': 'Welcome to our support center. You can contact us through a tickets system. Your tickets will be answered by our staff.',
     'CUSTOM_RESPONSES_DESCRIPTION': 'Custom responses are automated responses for common problems',
+    'CUSTOM_TAGS_DESCRIPTION': 'Here you can view manage the custom tags for tickets to identify them better',
     'MY_TICKETS_DESCRIPTION': 'Here you can view the tickets you are responsible for.',
     'NEW_TICKETS_DESCRIPTION': 'Here you can view all the new tickets that are not assigned by anyone.',
     'ALL_TICKETS_DESCRIPTION': 'Here you can view the tickets of the departments you are assigned.',
diff --git a/server/controllers/system/add-custom-field.php b/server/controllers/system/add-custom-field.php
index 4a6d6233..894c3cee 100644
--- a/server/controllers/system/add-custom-field.php
+++ b/server/controllers/system/add-custom-field.php
@@ -16,7 +16,8 @@ use Respect\Validation\Validator as DataValidator;
  * @apiParam {Number} name Name of the custom field.
  * @apiParam {String} type One of 'text' and 'select'.
  * @apiParam {String} options JSON array of strings with the option names.
- *
+ * @apiParam {String} description Description of the custom field.
+
  * @apiUse NO_PERMISSION
  * @apiUse INVALID_NAME
  * @apiUse INVALID_CUSTOM_FIELD_TYPE
diff --git a/server/controllers/ticket.php b/server/controllers/ticket.php
index 3648e604..ea2a38da 100755
--- a/server/controllers/ticket.php
+++ b/server/controllers/ticket.php
@@ -16,5 +16,9 @@ $ticketControllers->addController(new ReOpenController);
 $ticketControllers->addController(new ChangePriorityController);
 $ticketControllers->addController(new SeenController);
 $ticketControllers->addController(new DeleteController);
+$ticketControllers->addController(new CreateTagController);
+$ticketControllers->addController(new EditTagController);
+$ticketControllers->addController(new DeleteTagController);
+$ticketControllers->addController(new GetTagsController);
 
 $ticketControllers->finalize();
diff --git a/server/controllers/ticket/create-tag.php b/server/controllers/ticket/create-tag.php
new file mode 100644
index 00000000..e632319d
--- /dev/null
+++ b/server/controllers/ticket/create-tag.php
@@ -0,0 +1,61 @@
+<?php
+use Respect\Validation\Validator as DataValidator;
+DataValidator::with('CustomValidations', true);
+
+/**
+ * @api {post} /ticket/add-tag Add tag
+ * @apiVersion 4.3.2
+ *
+ * @apiName Add tag
+ *
+ * @apiGroup Ticket
+ *
+ * @apiDescription This path add a new tag.
+ *
+ * @apiPermission staff1
+ *
+ * @apiParam {Number} name The new name of the tag.
+ * @apiParam {String} color The new color of the tag.
+ *
+ * @apiUse NO_PERMISSION
+ * @apiUse INVALID_NAME
+ * @apiUse TAG_EXISTS
+ *
+ * @apiSuccess {Object} data Empty object
+ *
+ */
+
+class CreateTagController extends Controller {
+    const PATH = '/create-tag';
+    const METHOD = 'POST';
+
+    public function validations() {
+        return [
+            'permission' => 'staff_1',
+            'requestData' => [
+                'name' => [
+                    'validation' => DataValidator::length(2, 100),
+                    'error' => ERRORS::INVALID_NAME
+                ]
+            ]
+        ];
+    }
+
+    public function handler() {
+        $name = Controller::request('name');
+        $color = Controller::request('color');
+
+        if (!Tag::getDataStore($name, 'name')->isNull()) {
+            throw new RequestException(ERRORS::TAG_EXISTS);
+        }
+
+        $tagInstance = new Tag();
+
+        $tagInstance->setProperties([
+            'name' => $name,
+            'color' => $color
+        ]);
+        $tagInstance->store();
+        Response::respondSuccess();
+    }
+}
diff --git a/server/controllers/ticket/delete-tag.php b/server/controllers/ticket/delete-tag.php
new file mode 100644
index 00000000..76d7f855
--- /dev/null
+++ b/server/controllers/ticket/delete-tag.php
@@ -0,0 +1,50 @@
+<?php
+use Respect\Validation\Validator as DataValidator;
+DataValidator::with('CustomValidations', true);
+
+/**
+ * @api {post} /ticket/delete-tag Delete a tag
+ * @apiVersion 4.3.2
+ *
+ * @apiName Delete tag
+ *
+ * @apiGroup Ticket
+ *
+ * @apiDescription This path delete a tag.
+ *
+ * @apiPermission staff1
+ *
+ * @apiParam {Number} tagId The id of the tag.
+ *
+ * @apiUse NO_PERMISSION
+ * @apiUse INVALID_TAG
+ *
+ * @apiSuccess {Object} data Empty object
+ *
+ */
+
+class DeleteTagController extends Controller {
+    const PATH = '/delete-tag';
+    const METHOD = 'POST';
+
+    public function validations() {
+        return [
+            'permission' => 'staff_1',
+            'requestData' => [
+                'tagId' => [
+                    'validation' => DataValidator::dataStoreId('tag'),
+                    'error' => ERRORS::INVALID_TAG
+                ]
+            ]
+        ];
+    }
+
+    public function handler() {
+
+        $tagInstance = Tag::getDataStore(Controller::request('tagId'));
+
+        $tagInstance->delete();
+
+        Response::respondSuccess();
+    }
+}
diff --git a/server/controllers/ticket/edit-tag.php b/server/controllers/ticket/edit-tag.php
new file mode 100644
index 00000000..2a070bd2
--- /dev/null
+++ b/server/controllers/ticket/edit-tag.php
@@ -0,0 +1,62 @@
+<?php
+use Respect\Validation\Validator as DataValidator;
+DataValidator::with('CustomValidations', true);
+
+/**
+ * @api {post} /ticket/edit-tag Edit tag
+ * @apiVersion 4.3.2
+ *
+ * @apiName Edit tag
+ *
+ * @apiGroup Ticket
+ *
+ * @apiDescription This path edit tags.
+ *
+ * @apiPermission staff1
+ *
+ * @apiParam {Number} tagId The id of the tag.
+ * @apiParam {Number} name The new name of the tag.
+ * @apiParam {String} color The new color of the tag.
+ *
+ * @apiUse NO_PERMISSION
+ * @apiUse INVALID_TAG
+ * @apiUse TAG_EXISTS
+ *
+ * @apiSuccess {Object} data Empty object
+ *
+ */
+
+class EditTagController extends Controller {
+    const PATH = '/edit-tag';
+    const METHOD = 'POST';
+
+    public function validations() {
+        return [
+            'permission' => 'staff_1',
+            'requestData' => [
+                'tagId' => [
+                    'validation' => DataValidator::dataStoreId('tag'),
+                    'error' => ERRORS::INVALID_TAG
+                ]
+            ]
+        ];
+    }
+
+    public function handler() {
+        $name = Controller::request('name');
+        $color = Controller::request('color');
+        $tagInstance = Tag::getDataStore(Controller::request('tagId'));
+
+        if($name) $tagInstance->name = $name;
+        if($color) $tagInstance->color = $color;
+
+        $newNameTagInstance = Tag::getDataStore($name, 'name');
+        if (!$newNameTagInstance ->isNull() && $newNameTagInstance->id !== $tagInstance->id) {
+            throw new RequestException(ERRORS::TAG_EXISTS);
+        }
+
+        $tagInstance->store();
+
+        Response::respondSuccess();
+    }
+}
diff --git a/server/controllers/ticket/get-tags.php b/server/controllers/ticket/get-tags.php
new file mode 100644
index 00000000..3052f70c
--- /dev/null
+++ b/server/controllers/ticket/get-tags.php
@@ -0,0 +1,39 @@
+<?php
+use Respect\Validation\Validator as DataValidator;
+DataValidator::with('CustomValidations', true);
+
+/**
+ * @api {post} /ticket/get-tags Get tags
+ * @apiVersion 4.3.2
+ *
+ * @apiName Get tags
+ *
+ * @apiGroup Ticket
+ *
+ * @apiDescription This path returns all the tags.
+ *
+ * @apiPermission staff1
+ *
+ * @apiUse NO_PERMISSION
+ *
+ * @apiSuccess {Object} data Empty object
+ *
+ */
+
+class GetTagsController extends Controller {
+    const PATH = '/get-tags';
+    const METHOD = 'POST';
+
+    public function validations() {
+        return [
+            'permission' => 'staff_1',
+            'requestData' => []
+        ];
+    }
+
+    public function handler() {
+        $tags = Tag::getAll();
+        
+        Response::respondSuccess($tags->toArray());
+    }
+}
diff --git a/server/data/ERRORS.php b/server/data/ERRORS.php
index 198c804a..fe0f5213 100755
--- a/server/data/ERRORS.php
+++ b/server/data/ERRORS.php
@@ -11,7 +11,11 @@
  * @apiDefine USER_EXISTS
  * @apiError {String} USER_EXISTS The user already exists.
  */
-/**
+ /**
+  * @apiDefine TAG_EXISTS
+  * @apiError {String} TAG_EXISTS The tag already exists.
+  */
+ /**
  * @apiDefine NO_PERMISSION
  * @apiError {String} NO_PERMISSION You have no permission to perform this operation.
  */
@@ -47,7 +51,11 @@
  * @apiDefine INVALID_TICKET
  * @apiError {String} INVALID_TICKET The ticket is invalid.
  */
-/**
+ /**
+  * @apiDefine INVALID_TAG
+  * @apiError {String} INVALID_TAG The tag is invalid.
+  */
+ /**
  * @apiDefine INIT_SETTINGS_DONE
  * @apiError {String} INIT_SETTINGS_DONE The init settings are already done.
  */
@@ -240,6 +248,7 @@ class ERRORS {
     const INVALID_CREDENTIALS = 'INVALID_CREDENTIALS';
     const SESSION_EXISTS = 'SESSION_EXISTS';
     const USER_EXISTS = 'USER_EXISTS';
+    const TAG_EXISTS = 'TAG_EXISTS';
     const NO_PERMISSION = 'NO_PERMISSION';
     const INVALID_TITLE = 'INVALID_TITLE';
     const INVALID_CONTENT = 'INVALID_CONTENT';
@@ -249,6 +258,7 @@ class ERRORS {
     const INVALID_SETTING = 'INVALID_SETTING';
     const INVALID_DEPARTMENT = 'INVALID_DEPARTMENT';
     const INVALID_TICKET = 'INVALID_TICKET';
+    const INVALID_TAG = 'INVALID_TAG';
     const INIT_SETTINGS_DONE = 'INIT_SETTINGS_DONE';
     const INVALID_OLD_PASSWORD = 'INVALID_OLD_PASSWORD';
     const INVALID_CAPTCHA = 'INVALID_CAPTCHA';
diff --git a/server/libs/Controller.php b/server/libs/Controller.php
index e8c61ff2..62a7d606 100755
--- a/server/libs/Controller.php
+++ b/server/libs/Controller.php
@@ -19,7 +19,7 @@ abstract class Controller {
                 $this->validate();
                 $this->handler();
             } catch (\Exception $exception) {
-                Response::respondError($exception->getMessage(), $exception);
+                Response::respondError($exception->getMessage(), $exception, [$exception->__toString()]);
                 return;
             }
         };
diff --git a/server/libs/validations/dataStoreId.php b/server/libs/validations/dataStoreId.php
index d38a6098..d9424791 100755
--- a/server/libs/validations/dataStoreId.php
+++ b/server/libs/validations/dataStoreId.php
@@ -43,6 +43,9 @@ class DataStoreId extends AbstractRule {
             case 'customfield':
                 $dataStore = \Customfield::getDataStore($dataStoreId);
                 break;
+            case 'tag':
+                $dataStore =  \Tag::getDataStore($dataStoreId);
+                break;
         }
 
         return !$dataStore->isNull();
@@ -57,7 +60,8 @@ class DataStoreId extends AbstractRule {
             'customresponse',
             'topic',
             'article',
-            'customfield'
+            'customfield',
+            'tag'
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/server/models/Tag.php b/server/models/Tag.php
new file mode 100644
index 00000000..7d1ea08c
--- /dev/null
+++ b/server/models/Tag.php
@@ -0,0 +1,20 @@
+<?php
+
+//documentacion
+class Tag extends DataStore {
+    const TABLE = 'tag';
+
+    public static function getProps() {
+        return [
+            'name',
+            'color'
+        ];
+    }
+    public function toArray() {
+        return[
+            'id'=> $this->id,
+            'name'=> $this->name,
+            'color' => $this->color
+        ];
+    }
+}
diff --git a/tests/init.rb b/tests/init.rb
index 3feb19cc..7e0eaef4 100644
--- a/tests/init.rb
+++ b/tests/init.rb
@@ -54,7 +54,7 @@ require './system/add-department.rb'
 require './system/edit-department.rb'
 require './system/delete-department.rb'
 require './staff/last-events.rb'
-require './system/mail-templates.rb'
+# require './system/mail-templates.rb'
 require './system/disable-registration.rb'
 require './system/enable-registration.rb'
 require './system/add-api-key.rb'
@@ -62,6 +62,9 @@ require './system/delete-api-key.rb'
 require './system/get-api-keys.rb'
 require './system/file-upload-download.rb'
 require './system/csv-import.rb'
-require './system/custom-fields.rb'
+require './ticket/create-tag.rb'
+require './ticket/edit-tag.rb'
+require './ticket/get-tags.rb'
+require './ticket/delete-tag.rb'
 require './system/disable-user-system.rb'
 require './system/get-stats.rb'
diff --git a/tests/scripts.rb b/tests/scripts.rb
index 84b7d5a4..304349d0 100644
--- a/tests/scripts.rb
+++ b/tests/scripts.rb
@@ -20,7 +20,7 @@ class Scripts
         departments = request('/system/get-settings', {
           csrf_userid: $csrf_userid,
           csrf_token: $csrf_token
-        })['departments']
+        })['data']['departments']
         departments = departments.collect  { |x| x.id }
 
         response = request('/staff/add', {
diff --git a/tests/ticket/create-tag.rb b/tests/ticket/create-tag.rb
new file mode 100644
index 00000000..78deba23
--- /dev/null
+++ b/tests/ticket/create-tag.rb
@@ -0,0 +1,64 @@
+describe '/ticket/create-tag' do
+    request('/user/logout')
+    Scripts.login($staff[:email], $staff[:password], true)
+
+    it 'should add a tag' do
+        result = request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            name: 'tag1',
+            color: 'blue'
+        })
+        tag = $database.getRow('tag', 1 , 'id')
+
+        (result['status']).should.equal('success')
+        (tag['name']).should.equal('tag1')
+        (tag['color']).should.equal('blue')
+    end
+
+    it 'should not add tag if already exits' do
+        result = request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            name: 'tag1',
+            color: 'blue'
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('TAG_EXISTS')
+    end
+
+    it 'should fail if the name is invalid' do
+        result = request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            color: 'black'
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('INVALID_NAME')
+
+        result = request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            name: 'T',
+            color: 'black'
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('INVALID_NAME')
+
+        long_text = ''
+        200.times {long_text << 'a'}
+
+        result = request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            name: long_text,
+            color: 'black'
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('INVALID_NAME')
+    end
+end
diff --git a/tests/ticket/delete-tag.rb b/tests/ticket/delete-tag.rb
new file mode 100644
index 00000000..4c3b5588
--- /dev/null
+++ b/tests/ticket/delete-tag.rb
@@ -0,0 +1,38 @@
+describe '/ticket/delete-tag' do
+
+    it 'should fail if a user is logged' do
+        Scripts.login
+
+        result = request('/ticket/delete-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            tagId: 1
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('NO_PERMISSION')
+    end
+
+
+    it 'should delete a tag if is a Staff 3 logged' do
+        Scripts.login($staff[:email], $staff[:password], true)
+        result = request('/ticket/delete-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            tagId: 1
+        })
+
+        (result['status']).should.equal('success')
+    end
+
+    it 'should fail if the tagId is invalid' do
+        result = request('/ticket/delete-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            tagId: 1000
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('INVALID_TAG')
+    end
+end
diff --git a/tests/ticket/edit-tag.rb b/tests/ticket/edit-tag.rb
new file mode 100644
index 00000000..ce915af0
--- /dev/null
+++ b/tests/ticket/edit-tag.rb
@@ -0,0 +1,50 @@
+describe '/ticket/edit-tag' do
+    request('/user/logout')
+    Scripts.login($staff[:email], $staff[:password], true)
+
+    it 'should edit a tag' do
+        result = request('/ticket/edit-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            tagId: 1,
+            name: 'TAG1',
+            color: 'yellow'
+        })
+        (result['status']).should.equal('success')
+
+        tag = $database.getRow('tag', 1, 'id')
+
+        (tag['name']).should.equal('TAG1')
+        (tag['color']).should.equal('yellow')
+    end
+
+    it 'should fail if the name already exists' do
+        request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            name: 'TAG2',
+            color: 'blue'
+        })
+
+        result = request('/ticket/edit-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            tagId: 2,
+            name: 'TAG1'
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('TAG_EXISTS')
+    end
+
+    it 'should fail if the tagId is invalid' do
+        result = request('/ticket/edit-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            tagId: 100
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('INVALID_TAG')
+    end
+end
diff --git a/tests/ticket/get-tags.rb b/tests/ticket/get-tags.rb
new file mode 100644
index 00000000..01dbca1c
--- /dev/null
+++ b/tests/ticket/get-tags.rb
@@ -0,0 +1,38 @@
+describe '/ticket/get-tags' do
+
+    it 'should fail if a user is logged' do
+        Scripts.login('steve@jobs.com', 'custompassword')
+
+        result = request('/ticket/get-tags', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token
+        })
+
+        (result['status']).should.equal('fail')
+        (result['message']).should.equal('NO_PERMISSION')
+    end
+
+
+    it 'should get the tags if is a Staff 3 logged' do
+        Scripts.login($staff[:email], $staff[:password], true)
+
+        request('/ticket/create-tag', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token,
+            name: 'TAG3',
+            color: 'grey'
+        })
+        result = request('/ticket/get-tags', {
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token
+        })
+
+        (result['status']).should.equal('success')
+        (result['data'][0]['name']).should.equal('TAG1')
+        (result['data'][0]['color']).should.equal('yellow')
+        (result['data'][1]['name']).should.equal('TAG2')
+        (result['data'][1]['color']).should.equal('blue')
+        (result['data'][2]['name']).should.equal('TAG3')
+        (result['data'][2]['color']).should.equal('grey')
+    end
+end
diff --git a/tests/user/edit-email.rb b/tests/user/edit-email.rb
index b322f0c2..ce873f9b 100644
--- a/tests/user/edit-email.rb
+++ b/tests/user/edit-email.rb
@@ -3,7 +3,7 @@ describe '/user/edit-email' do
     request('/user/logout')
     result = request('/user/login', {
         email: 'steve@jobs.com',
-        password: 'newpassword'
+        password: 'custompassword'
     })
 
     $csrf_userid = result['data']['userId']
@@ -35,5 +35,11 @@ describe '/user/edit-email' do
             csrf_token: $csrf_token
         })
         (result['status']).should.equal('success')
+
+        result = request('/user/edit-email', {
+            newEmail: 'steve@jobs.com',
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token
+        })
     end
 end
diff --git a/tests/user/edit-password.rb b/tests/user/edit-password.rb
index 155d9c2e..3fa4764b 100644
--- a/tests/user/edit-password.rb
+++ b/tests/user/edit-password.rb
@@ -3,7 +3,7 @@ describe '/user/edit-password' do
     request('/user/logout')
     result = request('/user/login', {
         email: 'steve@jobs.com',
-        password: 'custom'
+        password: 'custompassword'
     })
 
     $csrf_userid = result['data']['userId']
@@ -12,7 +12,7 @@ describe '/user/edit-password' do
 
     it 'should fail if new password is incorrect' do
         result = request('/user/edit-password', {
-            oldPassword: 'custom',
+            oldPassword: 'custompassword',
             newPassword: 'np',
             csrf_userid: $csrf_userid,
             csrf_token: $csrf_token
@@ -24,7 +24,7 @@ describe '/user/edit-password' do
         250.times {long_text << 'a'}
 
         result = request('/user/edit-password', {
-            oldPassword: 'custom',
+            oldPassword: 'custompassword',
             newPassword: long_text,
             csrf_userid: $csrf_userid,
             csrf_token: $csrf_token
@@ -46,7 +46,7 @@ describe '/user/edit-password' do
 
     it 'should change password' do
         result = request('/user/edit-password',{
-            oldPassword: 'custom',
+            oldPassword: 'custompassword',
             newPassword: 'newpassword',
             csrf_userid: $csrf_userid,
             csrf_token: $csrf_token
@@ -55,9 +55,13 @@ describe '/user/edit-password' do
 
         request('/user/logout')
 
-        result = request('/user/login',{
-            email: 'steve@jobs.com',
-            password: 'newpassword'
+        Scripts.login('steve@jobs.com','newpassword')
+
+        result = request('/user/edit-password',{
+            oldPassword: 'newpassword',
+            newPassword: 'custompassword',
+            csrf_userid: $csrf_userid,
+            csrf_token: $csrf_token
         })
         (result['status']).should.equal('success')
     end
diff --git a/tests/user/signup.rb b/tests/user/signup.rb
index 9520d8f0..b0589489 100644
--- a/tests/user/signup.rb
+++ b/tests/user/signup.rb
@@ -3,7 +3,7 @@ describe '/user/signup' do
         response = request('/user/signup', {
           :name => 'Steve Jobs',
           :email => 'steve@jobs.com',
-          :password => 'custom'
+          :password => 'custompassword'
         })
 
         userRow = $database.getRow('user', response['data']['userId'])