diff --git a/.gitignore b/.gitignore
index 68fb58f9cc19962a9f53a6f1790192189166791e..75dcbca188c57392a75a90a60eb0ede042feae01 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 .venv
 .idea
+.vscode
 __pycache__
 *.pyc
 .DS_Store
\ No newline at end of file
diff --git a/app.py b/app.py
index 2c7d1cfaba5245a9a3ed67e0b8e6d76af7111c88..b69248b6ce4e37522af0c0d3ac7d5a5b73a85f06 100644
--- a/app.py
+++ b/app.py
@@ -1,19 +1,36 @@
 from flask import Flask, jsonify
 from flask_jwt_extended import JWTManager
 from flask_cors import CORS
+from jsonschema.exceptions import ValidationError
+from werkzeug.exceptions import BadRequest
 
+# These imports are required
 from areas import api_v1
-# There imports are required
 from areas import users
 from areas import apps
 from areas import auth
+
+from helpers import (
+    BadRequest,
+    KratosError,
+    bad_request_error,
+    validation_error,
+    kratos_error,
+    global_error,
+)
 from config import *
 
 app = Flask(__name__)
 cors = CORS(app)
-app.config['SECRET_KEY'] = SECRET_KEY
+app.config["SECRET_KEY"] = SECRET_KEY
 app.register_blueprint(api_v1)
 
+# Error handlers
+app.register_error_handler(Exception, global_error)
+app.register_error_handler(BadRequest, bad_request_error)
+app.register_error_handler(ValidationError, validation_error)
+app.register_error_handler(KratosError, kratos_error)
+
 jwt = JWTManager(app)
 
 
@@ -22,9 +39,9 @@ jwt = JWTManager(app)
 @jwt.unauthorized_loader
 @jwt.expired_token_loader
 def expired_token_callback(*args):
-    return jsonify({'errorMessage': 'Unauthorized'}), 401
+    return jsonify({"errorMessage": "Unauthorized"}), 401
 
 
-@app.route('/')
+@app.route("/")
 def index():
-    return 'Open App Stack API v1.0'
+    return "Open App Stack API v1.0"
diff --git a/areas/users/users.py b/areas/users/users.py
index 7ad285ca68d0c878bc20f3309f3c926375f6a64d..73d7a5d063b15426d11be60c27891e37cb9df459 100644
--- a/areas/users/users.py
+++ b/areas/users/users.py
@@ -1,57 +1,56 @@
 from flask import jsonify, request
 from flask_jwt_extended import jwt_required
 from flask_cors import cross_origin
+from flask_expects_json import expects_json
 
 from areas import api_v1
-from helpers.kratos_api import KratosApi
+from helpers import KratosApi
+from .validation import schema
 
 
-@api_v1.route('/users', methods=['GET'])
+@api_v1.route("/users", methods=["GET"])
 @jwt_required()
 @cross_origin()
 def get_users():
-    res = KratosApi.get('/identities')
+    res = KratosApi.get("/identities")
     return jsonify(res.json())
 
-@api_v1.route('/users/<string:id>', methods=['GET'])
+
+@api_v1.route("/users/<string:id>", methods=["GET"])
 @jwt_required()
 @cross_origin()
 def get_user(id):
-    res = KratosApi.get('/identities/{}'.format(id))
+    res = KratosApi.get("/identities/{}".format(id))
     return jsonify(res.json())
 
 
-@api_v1.route('/users', methods=['POST'])
+@api_v1.route("/users", methods=["POST"])
 @jwt_required()
 @cross_origin()
+@expects_json(schema)
 def post_user():
     data = request.get_json()
-    kratos_data = {
-        "schema_id": "default",
-        "traits": data
-    }
-    res = KratosApi.post('/identities', kratos_data)
+    kratos_data = {"schema_id": "default", "traits": data}
+    res = KratosApi.post("/identities", kratos_data)
     return jsonify(res.json()), res.status_code
 
 
-@api_v1.route('/users/<string:id>', methods=['PUT'])
+@api_v1.route("/users/<string:id>", methods=["PUT"])
 @jwt_required()
 @cross_origin()
+@expects_json(schema)
 def put_user(id):
     data = request.get_json()
-    kratos_data = {
-        "schema_id": "default",
-        "traits": data
-    }
-    res = KratosApi.put('/identities/{}'.format(id), kratos_data)
+    kratos_data = {"schema_id": "default", "traits": data}
+    res = KratosApi.put("/identities/{}".format(id), kratos_data)
     return jsonify(res.json()), res.status_code
 
 
-@api_v1.route('/users/<string:id>', methods=['DELETE'])
+@api_v1.route("/users/<string:id>", methods=["DELETE"])
 @jwt_required()
 @cross_origin()
 def delete_user(id):
-    res = KratosApi.delete('/identities/{}'.format(id))
-    if (res.status_code == 204):
+    res = KratosApi.delete("/identities/{}".format(id))
+    if res.status_code == 204:
         return jsonify(), res.status_code
     return jsonify(res.json()), res.status_code
diff --git a/areas/users/validation.py b/areas/users/validation.py
new file mode 100644
index 0000000000000000000000000000000000000000..84c3dea0e26124a1d520f783b78124b3a87ad157
--- /dev/null
+++ b/areas/users/validation.py
@@ -0,0 +1,14 @@
+import re
+
+schema = {
+    "type": "object",
+    "properties": {
+        "email": {
+            "type": "string",
+            "description": "Email of the user",
+            "pattern": r"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])",
+            "minLength": 1,
+        }
+    },
+    "required": ["email"],
+}
diff --git a/helpers/__init__.py b/helpers/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..67433630fc15347655a98a2916bf24383cea60a7
--- /dev/null
+++ b/helpers/__init__.py
@@ -0,0 +1,2 @@
+from .kratos_api import *
+from .error_handler import *
diff --git a/helpers/error_handler.py b/helpers/error_handler.py
new file mode 100644
index 0000000000000000000000000000000000000000..4c1949847b1d2e3b50037c1c82dffdab269f6ba6
--- /dev/null
+++ b/helpers/error_handler.py
@@ -0,0 +1,34 @@
+from flask import jsonify
+from jsonschema import ValidationError
+
+
+class KratosError(Exception):
+    pass
+
+
+class BadRequest(Exception):
+    pass
+
+
+def bad_request_error(e):
+    message = e.args[0] if e.args else "Bad request to the server."
+    return jsonify({"errorMessage": message})
+
+
+def validation_error(e):
+    original_error = e.description
+    return (
+        jsonify({"errorMessage": "{} is not valid.".format(original_error.path[0])}),
+        400,
+    )
+
+
+def kratos_error(e):
+    message = e.args[0] if e.args else "Failed to contant Kratos."
+    status_code = e.args[1] if e.args else 500
+    return jsonify({"errorMessage": message}), status_code
+
+
+def global_error(e):
+    message = e.args[0] if e.args else "Something went wrong."
+    return jsonify({"errorMessage": message})
diff --git a/helpers/kratos_api.py b/helpers/kratos_api.py
index 5a25b311662731efd96d9cbbd550e0415e60a82a..739f9a03469f2fb4edf51758dad768e30ba9029f 100644
--- a/helpers/kratos_api.py
+++ b/helpers/kratos_api.py
@@ -1,32 +1,55 @@
+from logging import error
 import requests
 
 from config import *
+from .error_handler import KratosError
+
+
+class KratosApi:
+    @staticmethod
+    def __handleError(res):
+        if res.status_code >= 400:
+            message = res.json()["error"]["message"]
+            raise KratosError(message, res.status_code)
 
-class KratosApi():
     @staticmethod
     def get(url):
         try:
-            return requests.get('{}{}'.format(KRATOS_URL, url))
+            res = requests.get("{}{}".format(KRATOS_URL, url))
+            KratosApi.__handleError(res)
+            return res
         except:
-            return "Failed to contact Kratos"
+            raise KratosError()
 
     @staticmethod
     def post(url, data):
         try:
-            return requests.post('{}{}'.format(KRATOS_URL, url), json=data)
+            res = requests.post("{}{}".format(KRATOS_URL, url), json=data)
+            KratosApi.__handleError(res)
+            return res
+        except KratosError as err:
+            raise err
         except:
-            return "Failed to contact Kratos"
+            raise KratosError()
 
     @staticmethod
     def put(url, data):
         try:
-            return requests.put('{}{}'.format(KRATOS_URL, url), json=data)
+            res = requests.put("{}{}".format(KRATOS_URL, url), json=data)
+            KratosApi.__handleError(res)
+            return res
+        except KratosError as err:
+            raise err
         except:
-            return "Failed to contact Kratos"
+            raise KratosError()
 
     @staticmethod
     def delete(url):
         try:
-            return requests.delete('{}{}'.format(KRATOS_URL, url))
+            res = requests.delete("{}{}".format(KRATOS_URL, url))
+            KratosApi.__handleError(res)
+            return res
+        except KratosError as err:
+            raise err
         except:
-            return "Failed to contact Kratos"
\ No newline at end of file
+            raise KratosError()
diff --git a/requirements.txt b/requirements.txt
index dbc89579c46839c1d546d0f842925090e0397675..d21805a46b2d199354dca480d4fd08a06156b831 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,5 @@
+attrs==21.2.0
+black==21.9b0
 certifi==2021.10.8
 cffi==1.15.0
 charset-normalizer==2.0.7
@@ -5,15 +7,25 @@ click==8.0.3
 cryptography==35.0.0
 Flask==2.0.2
 Flask-Cors==3.0.10
+flask-expects-json==1.6.0
 Flask-JWT-Extended==4.3.1
 gunicorn==20.1.0
 idna==3.3
+install==1.3.4
 itsdangerous==2.0.1
 Jinja2==3.0.2
+jsonschema==4.1.2
 MarkupSafe==2.0.1
+mypy-extensions==0.4.3
+pathspec==0.9.0
+platformdirs==2.4.0
 pycparser==2.20
 PyJWT==2.3.0
+pyrsistent==0.18.0
+regex==2021.10.23
 requests==2.26.0
 six==1.16.0
+tomli==1.2.2
+typing-extensions==3.10.0.2
 urllib3==1.26.7
 Werkzeug==2.0.2