diff --git a/server/app/apis/__init__.py b/server/app/apis/__init__.py
index 109252e64bf7bb7f52af20a6ba4236d7bdf15ba0..31d1be3df8d545c7c8e7ac658e545e6dc970dfd8 100644
--- a/server/app/apis/__init__.py
+++ b/server/app/apis/__init__.py
@@ -139,7 +139,9 @@ flask_api = Api()
 def init_api():
 
     from .auth import blp as auth_blp
+    from .misc import blp as misc_blp
     from .users import blp as user_blp
 
     flask_api.register_blueprint(user_blp)
     flask_api.register_blueprint(auth_blp)
+    flask_api.register_blueprint(misc_blp)
diff --git a/server/app/apis/auth.py b/server/app/apis/auth.py
index dc5af792ec96f3e26bbd2f938ee2e8e0cc393fac..cb40f58349886183263253b25955509b15015008 100644
--- a/server/app/apis/auth.py
+++ b/server/app/apis/auth.py
@@ -45,13 +45,13 @@ if has_app_context():
 
 
 def get_user_claims(item_user):
-    """ Gets user details for jwt-token. """
+    """ Gets user details for jwt. """
 
     return {"role": item_user.role.name, "city_id": item_user.city_id}
 
 
 def get_code_claims(item_code):
-    """ Gets code details for jwt-token. """
+    """ Gets code details for jwt. """
 
     return {
         "view": item_code.view_type.name,
@@ -111,7 +111,7 @@ class AuthLogin(MethodView):
     @blp.arguments(UserLoginArgsSchema)
     @blp.response(http_codes.OK, UserLoginResponseSchema)
     def post(self, args):
-        """ Logs in the specified user and creates a jwt-token. """
+        """ Logs in the specified user and creates a jwt. """
 
         email = args.get("email")
         password = args.get("password")
diff --git a/server/app/apis/misc.py b/server/app/apis/misc.py
index 552a0ad0c4848c33a08bcb63ccc3e870acd6af48..21054b200c11cd5c3a37b514550513de04cfd7e5 100644
--- a/server/app/apis/misc.py
+++ b/server/app/apis/misc.py
@@ -4,100 +4,114 @@ Default route: /api/misc
 """
 
 import app.database.controller as dbc
-from app.apis import list_response, protect_route
-from app.core import http_codes
-from app.core.dto import MiscDTO
+import marshmallow as ma
+from app.apis import protect_route
+from app.core.schemas import (
+    BaseSchema,
+    CitySchema,
+    ComponentTypeSchema,
+    MediaTypeSchema,
+    QuestionTypeSchema,
+    RoleSchema,
+    ViewTypeSchema,
+)
+from app.database import models
+from app.database.controller.add import competition
 from app.database.models import City, Competition, ComponentType, MediaType, QuestionType, Role, User, ViewType
-from flask_restx import Resource, reqparse
+from flask.views import MethodView
+from flask_smorest import Blueprint, response
+from marshmallow_sqlalchemy import auto_field
 
-api = MiscDTO.api
+from . import http_codes
 
-question_type_schema = MiscDTO.question_type_schema
-media_type_schema = MiscDTO.media_type_schema
-component_type_schema = MiscDTO.component_type_schema
-view_type_schema = MiscDTO.view_type_schema
+blp = Blueprint("misc", "misc", url_prefix="/api/misc", description="Miscellaneous operations")
 
-role_schema = MiscDTO.role_schema
-city_schema = MiscDTO.city_schema
 
+class TypesResponseSchema(BaseSchema):
+    media_types = ma.fields.Nested(MediaTypeSchema, many=True)
+    component_types = ma.fields.Nested(ComponentTypeSchema, many=True)
+    question_types = ma.fields.Nested(QuestionTypeSchema, many=True)
+    view_types = ma.fields.Nested(ViewTypeSchema, many=True)
 
-name_parser = reqparse.RequestParser()
-name_parser.add_argument("name", type=str, required=True, location="json")
 
-
-@api.route("/types")
-class TypesList(Resource):
+@blp.route("/types")
+class Types(MethodView):
+    @blp.response(http_codes.OK, TypesResponseSchema)
     def get(self):
-        """ Gets a list of all types. """
-
-        result = {}
-        result["media_types"] = media_type_schema.dump(dbc.get.all(MediaType))
-        result["component_types"] = component_type_schema.dump(dbc.get.all(ComponentType))
-        result["question_types"] = question_type_schema.dump(dbc.get.all(QuestionType))
-        result["view_types"] = view_type_schema.dump(dbc.get.all(ViewType))
-        return result
+        """ Gets a list of all types """
+        return dict(
+            media_types=dbc.get.all(MediaType),
+            component_types=dbc.get.all(ComponentType),
+            question_types=dbc.get.all(QuestionType),
+            view_types=dbc.get.all(ViewType),
+        )
 
 
-@api.route("/roles")
-class RoleList(Resource):
+@blp.route("/roles")
+class RoleList(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, RoleSchema(many=True))
     def get(self):
         """ Gets a list of all roles. """
+        return dbc.get.all(Role)
+
 
-        items = dbc.get.all(Role)
-        return list_response(role_schema.dump(items))
+class CityAddArgsSchema(BaseSchema):
+    class Meta(BaseSchema.Meta):
+        model = models.City
 
+    name = auto_field()
 
-@api.route("/cities")
-class CitiesList(Resource):
+
+@blp.route("/cities")
+class CitiesList(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, CitySchema(many=True))
     def get(self):
         """ Gets a list of all cities. """
-
-        items = dbc.get.all(City)
-        return list_response(city_schema.dump(items))
+        return dbc.get.all(City)
 
     @protect_route(allowed_roles=["Admin"])
-    def post(self):
+    @blp.arguments(CitySchema)
+    @blp.response(http_codes.OK, CitySchema(many=True))
+    def post(self, args):
         """ Posts the specified city. """
+        dbc.add.city(**args)
+        return dbc.get.all(City)
 
-        args = name_parser.parse_args(strict=True)
-        dbc.add.city(args["name"])
-        items = dbc.get.all(City)
-        return list_response(city_schema.dump(items))
 
-
-@api.route("/cities/<ID>")
-@api.param("ID")
-class Cities(Resource):
+@blp.route("/cities/<city_id>")
+class Cities(MethodView):
     @protect_route(allowed_roles=["Admin"])
-    def put(self, ID):
+    @blp.arguments(CitySchema)
+    @blp.response(http_codes.OK, CitySchema(many=True))
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="City not found")
+    @blp.alt_response(http_codes.CONFLICT, None, description="The city can't be updated with the provided values")
+    def put(self, args, city_id):
         """ Edits the specified city with the provided arguments. """
-
-        item = dbc.get.one(City, ID)
-        args = name_parser.parse_args(strict=True)
-        item.name = args["name"]
-        dbc.utils.commit_and_refresh(item)
-        items = dbc.get.all(City)
-        return list_response(city_schema.dump(items))
+        dbc.edit.default(dbc.get.one(City, city_id), **args)
+        return dbc.get.all(City)
 
     @protect_route(allowed_roles=["Admin"])
-    def delete(self, ID):
+    @blp.response(http_codes.OK, CitySchema(many=True))
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="City not found")
+    @blp.alt_response(http_codes.CONFLICT, None, description="The city can't be updated with the provided values")
+    def delete(self, city_id):
         """ Deletes the specified city. """
+        dbc.delete.default(dbc.get.one(City, city_id))
+        return dbc.get.all(City)
 
-        item = dbc.get.one(City, ID)
-        dbc.delete.default(item)
-        items = dbc.get.all(City)
-        return list_response(city_schema.dump(items))
 
+class StatisticsResponseSchema(BaseSchema):
+    users = ma.fields.Int()
+    competitions = ma.fields.Int()
+    regions = ma.fields.Int()
 
-@api.route("/statistics")
-class Statistics(Resource):
+
+@blp.route("/statistics")
+class Statistics(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, StatisticsResponseSchema)
     def get(self):
         """ Gets statistics. """
-
-        user_count = User.query.count()
-        competition_count = Competition.query.count()
-        region_count = City.query.count()
-        return {"users": user_count, "competitions": competition_count, "regions": region_count}, http_codes.OK
+        return {"users": User.query.count(), "competitions": Competition.query.count(), "regions": City.query.count()}
diff --git a/server/app/database/__init__.py b/server/app/database/__init__.py
index 828c4f962e73d6ceffa4867e93a66aeb0cb3bc9e..594894480efea039c5cdf0c544e964ad4d554b3f 100644
--- a/server/app/database/__init__.py
+++ b/server/app/database/__init__.py
@@ -3,6 +3,7 @@ The database submodule contaisn all functionality that has to do with the
 database. It can add, get, delete, edit, search and copy items.
 """
 
+from app.apis import http_codes
 from flask_smorest import abort
 
 # from flask_restx import abort
@@ -27,7 +28,7 @@ class ExtendedQuery(BaseQuery):
     Extensions to a regular query which makes using the database more convenient.
     """
 
-    def first_api(self, required=True, error_message=None, error_code=404):
+    def first_api(self, required=True, error_message=None, error_code=http_codes.NOT_FOUND):
         """
         Extensions of the first() functions otherwise used on queries. Abort
         if no item was found and it was required.
diff --git a/server/app/database/controller/delete.py b/server/app/database/controller/delete.py
index 9e4f8b3d7d08abeb3f0fa641aea6f4378d3700b5..bd2ff7469e7856f2a874cb1eeeaa47e7f201e110 100644
--- a/server/app/database/controller/delete.py
+++ b/server/app/database/controller/delete.py
@@ -3,8 +3,10 @@ This file contains functionality to delete data to the database.
 """
 
 import app.database.controller as dbc
+from app.apis import http_codes
 from app.core import db
 from app.database.models import QuestionAlternativeAnswer, QuestionScore, Whitelist
+from flask_smorest import abort
 
 # from flask_restx import abort
 from sqlalchemy.exc import IntegrityError
@@ -18,15 +20,10 @@ def default(item):
         db.session.commit()
     except IntegrityError:
         db.session.rollback()
-        pass
-        # abort(codes.CONFLICT, f"Item of type {type(item)} cannot be deleted due to an Integrity Constraint")
+        abort(http_codes.CONFLICT, f"Kunde inte ta bort objektet")
     except:
         db.session.rollback()
-        pass
-        # abort(
-        #     codes.INTERNAL_SERVER_ERROR,
-        #     f"Item of type {type(item)} could not be deleted",
-        # )
+        abort(http_codes.INTERNAL_SERVER_ERROR, f"Kunde inte ta bort objektet")
 
 
 def whitelist_to_blacklist(filters):
diff --git a/server/app/database/controller/edit.py b/server/app/database/controller/edit.py
index 3cd544628616225ad34e53d765946698137c84fa..209c753b5c84c99dff15a0131db227a1486a65b7 100644
--- a/server/app/database/controller/edit.py
+++ b/server/app/database/controller/edit.py
@@ -2,7 +2,9 @@
 This file contains functionality to get data from the database.
 """
 
+from app.apis import http_codes
 from app.core import db
+from flask_smorest import abort
 
 # from flask_restx.errors import abort
 from sqlalchemy import exc
@@ -32,8 +34,7 @@ def default(item, **kwargs):
     try:
         db.session.commit()
     except exc.IntegrityError:
-        pass
-        # abort(codes.CONFLICT, f"Item of type {type(item)} cannot be edited due to an Integrity Constraint")
+        abort(http_codes.CONFLICT, f"Kunde inte utföra ändringen")
 
     db.session.refresh(item)
     return item