diff --git a/server/app/apis/__init__.py b/server/app/apis/__init__.py
index 53589ca1b1beaf91595a3e460d5fa84479e288d6..91928ba2dfc19fa3f97b66c5760f097474941ba2 100644
--- a/server/app/apis/__init__.py
+++ b/server/app/apis/__init__.py
@@ -114,19 +114,12 @@ def protect_route(allowed_roles=None, allowed_views=None):
 # from .users import api as user_ns
 
 # flask_api = Api()
-# flask_api.add_namespace(media_ns, path="/api/media")
-# flask_api.add_namespace(misc_ns, path="/api/misc")
-# # flask_api.add_namespace(user_ns, path="/api/users")
-# flask_api.regis
-# flask_api.add_namespace(auth_ns, path="/api/auth")
-# flask_api.add_namespace(comp_ns, path="/api/competitions")
 # flask_api.add_namespace(slide_ns, path="/api/competitions/<competition_id>/slides")
 # flask_api.add_namespace(
 #     alternative_ns, path="/api/competitions/<competition_id>/slides/<slide_id>/questions/<question_id>/alternatives"
 # )
 # flask_api.add_namespace(team_ns, path="/api/competitions/<competition_id>/teams")
 # flask_api.add_namespace(code_ns, path="/api/competitions/<competition_id>/codes")
-# flask_api.add_namespace(question_ns, path="/api/competitions/<competition_id>")
 # flask_api.add_namespace(component_ns, path="/api/competitions/<competition_id>/slides/<slide_id>/components")
 # flask_api.add_namespace(answer_ns, path="/api/competitions/<competition_id>/teams/<team_id>/answers")
 # flask_api.add_namespace(score_ns, path="/api/competitions/<competition_id>/teams/<team_id>/answers/question_scores")
@@ -142,6 +135,7 @@ def init_api():
     from .competitions import blp as competitions_blp
     from .media import blp as media_blp
     from .misc import blp as misc_blp
+    from .questions import blp as questions_blp
     from .slides import blp as slide_blp
     from .users import blp as user_blp
 
@@ -151,3 +145,4 @@ def init_api():
     flask_api.register_blueprint(misc_blp)
     flask_api.register_blueprint(media_blp)
     flask_api.register_blueprint(slide_blp)
+    flask_api.register_blueprint(questions_blp)
diff --git a/server/app/apis/questions.py b/server/app/apis/questions.py
index 6ba32382fa524180c76eef35bd02a68382e552c6..29785906568bf7ceafd76322c8e64e177dbb6299 100644
--- a/server/app/apis/questions.py
+++ b/server/app/apis/questions.py
@@ -3,87 +3,87 @@ All API calls concerning question answers.
 Default route: /api/competitions/<competition_id>
 """
 
-import app.core.http_codes as codes
 import app.database.controller as dbc
-from app.apis import item_response, list_response, protect_route
-from app.core.dto import QuestionDTO
-from app.core.parsers import sentinel
-from flask_restx import Resource, reqparse
-
-api = QuestionDTO.api
-schema = QuestionDTO.schema
-list_schema = QuestionDTO.list_schema
-
-question_parser_add = reqparse.RequestParser()
-question_parser_add.add_argument("name", type=str, default=None, location="json")
-question_parser_add.add_argument("total_score", type=int, default=None, location="json")
-question_parser_add.add_argument("type_id", type=int, required=True, location="json")
-question_parser_add.add_argument("correcting_instructions", type=str, default=None, location="json")
-
-question_parser_edit = reqparse.RequestParser()
-question_parser_edit.add_argument("name", type=str, default=sentinel, location="json")
-question_parser_edit.add_argument("total_score", type=int, default=sentinel, location="json")
-question_parser_edit.add_argument("type_id", type=int, default=sentinel, location="json")
-question_parser_edit.add_argument("correcting_instructions", type=str, default=sentinel, location="json")
-
-
-@api.route("/questions")
-@api.param("competition_id")
-class QuestionList(Resource):
-    @protect_route(allowed_roles=["*"])
-    def get(self, competition_id):
-        """ Gets all questions in the specified competition. """
+from app.apis import protect_route
+from app.core import ma
+from app.core.schemas import BaseSchema, QuestionSchema, SlideSchema
+from app.database import models
+from app.database.controller.edit import default
+from flask.views import MethodView
+from flask_smorest import Blueprint
+
+from . import http_codes
+
+blp = Blueprint(
+    "question",
+    "question",
+    url_prefix="/api/competitions/<competition_id>/slides/<slide_id>/questions",
+    description="Adding, updating and deleting questions",
+)
+
+
+class QuestionAddArgsSchema(BaseSchema):
+    class Meta(BaseSchema.Meta):
+        model = models.Question
+
+    name = ma.auto_field(required=False, missing="")
+    total_score = ma.auto_field(required=False, missing=None)
+    type_id = ma.auto_field(required=True)
+    correcting_instructions = ma.auto_field(required=False, missing=None)
+
+
+class QuestionEditArgsSchema(BaseSchema):
+    class Meta(BaseSchema.Meta):
+        model = models.Question
 
-        items = dbc.get.question_list_for_competition(competition_id)
-        return list_response(list_schema.dump(items))
+    name = ma.auto_field(required=False)
+    total_score = ma.auto_field(required=False)
+    type_id = ma.auto_field(required=False)
+    correcting_instructions = ma.auto_field(required=False)
 
 
-@api.route("/slides/<slide_id>/questions")
-@api.param("competition_id, slide_id")
-class QuestionListForSlide(Resource):
+@blp.route("")
+class Questions(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, QuestionSchema(many=True))
     def get(self, competition_id, slide_id):
         """ Gets all questions in the specified competition and slide. """
-
-        items = dbc.get.question_list(competition_id, slide_id)
-        return list_response(list_schema.dump(items))
+        return dbc.get.question_list(competition_id, slide_id)
 
     @protect_route(allowed_roles=["*"])
-    def post(self, competition_id, slide_id):
+    @blp.arguments(QuestionAddArgsSchema)
+    @blp.response(http_codes.OK, QuestionSchema)
+    @blp.alt_response(http_codes.CONFLICT, None, description="Could not add question")
+    def post(self, args, competition_id, slide_id):
         """ Posts a new question to the specified slide using the provided arguments. """
-
-        args = question_parser_add.parse_args(strict=True)
-        item = dbc.add.question(slide_id=slide_id, **args)
-        return item_response(schema.dump(item))
+        return dbc.add.question(slide_id=slide_id, **args)
 
 
-@api.route("/slides/<slide_id>/questions/<question_id>")
-@api.param("competition_id, slide_id, question_id")
-class QuestionById(Resource):
+@blp.route("/<question_id>")
+class QuestionById(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, QuestionSchema)
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find question")
     def get(self, competition_id, slide_id, question_id):
         """
         Gets the specified question using the specified competition and slide.
         """
-
-        item_question = dbc.get.question(competition_id, slide_id, question_id)
-        return item_response(schema.dump(item_question))
+        return dbc.get.question(competition_id, slide_id, question_id)
 
     @protect_route(allowed_roles=["*"])
-    def put(self, competition_id, slide_id, question_id):
+    @blp.arguments(QuestionEditArgsSchema)
+    @blp.response(http_codes.OK, QuestionSchema)
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find question")
+    @blp.alt_response(http_codes.CONFLICT, None, description="Could not edit question")
+    def put(self, args, competition_id, slide_id, question_id):
         """ Edits the specified question with the provided arguments. """
-
-        args = question_parser_edit.parse_args(strict=True)
-
-        item_question = dbc.get.question(competition_id, slide_id, question_id)
-        item_question = dbc.edit.default(item_question, **args)
-
-        return item_response(schema.dump(item_question))
+        return dbc.edit.default(dbc.get.question(competition_id, slide_id, question_id), **args)
 
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.NO_CONTENT, QuestionSchema)
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find question")
+    @blp.alt_response(http_codes.CONFLICT, None, description="Could not delete question")
     def delete(self, competition_id, slide_id, question_id):
         """ Deletes the specified question. """
-
-        item_question = dbc.get.question(competition_id, slide_id, question_id)
-        dbc.delete.question(item_question)
-        return {}, codes.NO_CONTENT
+        dbc.delete.question(dbc.get.question(competition_id, slide_id, question_id))
+        return None