diff --git a/hodor/controllers/challenges.py b/hodor/controllers/challenges.py
new file mode 100644
index 0000000000000000000000000000000000000000..eb109c3024c9e9b97c8b5b96af652ea3570210ae
--- /dev/null
+++ b/hodor/controllers/challenges.py
@@ -0,0 +1,134 @@
+from hodor import app
+from flask import request, jsonify, abort, make_response
+from hodor.models.challenges import Challenges
+from sqlalchemy.exc import IntegrityError
+
+###########################
+#   Add a new challenge to the platform #
+###########################
+@app.route('/challenges/new', methods=['POST'])
+def add_new_chall():
+    """
+    This function is used to add new challenges to the platform
+    :return: Response Code
+    """
+    newchall=dict()
+
+    if request.method == "POST":
+        try:
+            newchall['chall_id'] = request.data.get('chall_id').strip()
+            newchall['name'] = str(request.data.get('name').strip())
+            newchall['points'] = request.data.get('points').strip()
+            newchall['description'] = str(request.data.get('description').strip())
+            newchall['hints'] = str(request.data.get('hints').strip())
+        except Exception as e:
+            print(e)
+            abort(500)
+        chall = Challenges(**newchall)
+        chall.save()
+    return make_response(jsonify(status=201, msg="Challenge {} successfully added".format(chall.chall_id) +
+                                 "to database"), 201)
+
+###########################
+#   Edit an existing challenge
+###########################
+@app.route('/challenges/edit', methods=['PUT'])
+def edit_chall():
+    """
+    This function enables to edit existing challenges
+    :return: Response Code
+    """
+    chall_id=request.data.get('chall_id').strip()
+    get_id = Challenges.query.get(chall_id)
+    chall={}
+    if(get_id):
+            try:
+                get_id.name = str(request.data.get('name').strip())
+                get_id.points = str(request.data.get('points').strip())
+                get_id.description = str(request.data.get('description').strip())
+                get_id.hints = str(request.data.get('hints').strip())
+            except Exception as e:
+                print(e)
+                abort(500)
+            get_id.commit()
+            return make_response(jsonify(status=200, msg="Record succesfully edited"), 200)
+    else:
+        return make_response(jsonify(status=404, msg="No such challenge ID found"), 404)
+
+###########################
+# Deleting an existing challenge
+###########################
+@app.route('/challenges/<id_slug>', methods=['DELETE'])
+def del_chall(id_slug):
+    """
+    This function deletes existing challenge
+    :return: Response Code
+    """
+    check_id = id_slug.strip()
+    get_id = Challenges.query.filter_by(chall_id=check_id)
+    if get_id:
+        Challenges.query.filter_by(chall_id=id_slug).delete()
+        return make_response(jsonify(status=200, msg="Record succesfully deleted"), 200)
+    else:
+        return make_response(jsonify(status=404, msg="No such challenge ID found"), 404)
+
+###########################
+# Extracting required fields
+###########################
+def _extract_required_fields(chall):
+    filter_chall = dict()
+    '''
+    This can be done by directly dumping the dictionary but there's always
+    a risk of data leak.So, we pick what we need to give out out of the API
+    '''
+    filter_chall['name'] = chall.name
+    filter_chall['description'] = chall.description
+    filter_chall['points'] = chall.points
+    filter_chall['hints'] = chall.hints
+    filter_chall['chall_id'] = chall.chall_id
+
+    return filter_chall
+
+
+###########################
+#Get all challenge IDs
+###########################
+@app.route('/challenges', methods=['GET','POST'])
+def get_all_challids():
+    """
+    Returns all challenge IDs and names
+    :return: Response Code
+    """
+    response = dict()
+    response['status'] = 200
+    response['data'] = []
+
+    for challenge in Challenges.get_all():
+        '''
+        All records for each challenge is retrieved and name, id are only returned
+        '''
+        response['data'].append(_extract_required_fields(challenge))
+
+    return response
+
+
+################################################
+# Handle Integrity Exceptions in API           #
+################################################
+@app.errorhandler(IntegrityError)
+def handle_sql_assertion_error(err):
+    try:
+        '''
+        err.orig.args is from the DBAPIError class of SQLAlchemy. It usually
+        contains the original error message.
+        The below is an attempt to clean up the message and only return the
+        relevant part to API
+        '''
+        try:
+            errmsg = err.orig.args[0].split('\n')[1][9:]
+        except IndexError:
+            errmsg = err.orig.args[0].split('\n')
+    except IndexError:
+        errmsg = err.orig.args[0]
+
+    return make_response(jsonify(status=400, msg=errmsg), 400)
diff --git a/hodor/models/challenges.py b/hodor/models/challenges.py
index 615b5eebb80f02e64424fc714e02d84deb03a7ec..5c1e639b6f3d0dae4bdcfe3fe6ee9b6242504f60 100644
--- a/hodor/models/challenges.py
+++ b/hodor/models/challenges.py
@@ -7,13 +7,13 @@ class Challenges(db.Model):
     __tablename__= 'challenges'
 
     # Data variables for each challenge
-    id = db.Column(db.String(32), primary_key=True, unique=True, nullable=False)
+    chall_id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
     name = db.Column(db.String(32), nullable=False)
     points = db.Column(db.Integer, nullable=False)
     description = db.Column(db.String(2048), nullable=False)
     hints = db.Column(db.String(512), nullable=False)
 
-    @staticmethod
+
     def save(self):
         db.session.add(self)
         db.session.commit()
@@ -22,5 +22,10 @@ class Challenges(db.Model):
         db.session.delete(self)
         db.session.commit()
 
+    @staticmethod
     def get_all():
         return Challenges.query.all()
+
+    @staticmethod
+    def commit():
+        return db.session.commit()