diff --git a/server/app/apis/__init__.py b/server/app/apis/__init__.py
index 91928ba2dfc19fa3f97b66c5760f097474941ba2..58a42b0371cb131ab99890e6b38b2758f917d4b7 100644
--- a/server/app/apis/__init__.py
+++ b/server/app/apis/__init__.py
@@ -114,14 +114,19 @@ def protect_route(allowed_roles=None, allowed_views=None):
 # from .users import api as user_ns
 
 # flask_api = Api()
+
 # 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(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")
 
 from flask_smorest import Api
@@ -132,17 +137,19 @@ flask_api = Api()
 def init_api():
 
     from .auth import blp as auth_blp
-    from .competitions import blp as competitions_blp
+    from .competitions import blp as competition_blp
     from .media import blp as media_blp
     from .misc import blp as misc_blp
-    from .questions import blp as questions_blp
+    from .questions import blp as question_blp
     from .slides import blp as slide_blp
+    from .teams import blp as team_blp
     from .users import blp as user_blp
 
     flask_api.register_blueprint(user_blp)
     flask_api.register_blueprint(auth_blp)
-    flask_api.register_blueprint(competitions_blp)
+    flask_api.register_blueprint(competition_blp)
     flask_api.register_blueprint(misc_blp)
     flask_api.register_blueprint(media_blp)
     flask_api.register_blueprint(slide_blp)
-    flask_api.register_blueprint(questions_blp)
+    flask_api.register_blueprint(question_blp)
+    flask_api.register_blueprint(team_blp)
diff --git a/server/app/apis/teams.py b/server/app/apis/teams.py
index 913deeb789340939c3dcb37f4a3edefbd7d06e95..4071a89ddee43e8d7783a2a78f71507c99e15230 100644
--- a/server/app/apis/teams.py
+++ b/server/app/apis/teams.py
@@ -3,70 +3,76 @@ All API calls concerning question alternatives.
 Default route: /api/competitions/<competition_id>/teams
 """
 
-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 TeamDTO
-from app.core.parsers import sentinel
-from flask_restx import Resource, reqparse
+from app.apis import protect_route
+from app.core import ma
+from app.core.schemas import BaseSchema, TeamSchema
+from app.database import models
+from flask.views import MethodView
+from flask_smorest import Blueprint
 
-api = TeamDTO.api
-schema = TeamDTO.schema
-list_schema = TeamDTO.list_schema
+from . import http_codes
 
-team_parser_add = reqparse.RequestParser()
-team_parser_add.add_argument("name", type=str, required=True, location="json")
+blp = Blueprint(
+    "team",
+    "team",
+    url_prefix="/api/competitions/<competition_id>/teams",
+    description="Operations on teams",
+)
 
-team_parser_edit = reqparse.RequestParser()
-team_parser_edit.add_argument("name", type=str, default=sentinel, location="json")
 
+class TeamAddArgsSchema(BaseSchema):
+    class Meta(BaseSchema.Meta):
+        model = models.Team
 
-@api.route("")
-@api.param("competition_id")
-class TeamsList(Resource):
+    name = ma.auto_field(required=True)
+
+
+class TeamEditArgsSchema(BaseSchema):
+    class Meta(BaseSchema.Meta):
+        model = models.Team
+
+    name = ma.auto_field(required=False)
+
+
+@blp.route("")
+class Teams(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, TeamSchema(many=True))
     def get(self, competition_id):
         """ Gets all teams to the specified competition. """
-
-        items = dbc.get.team_list(competition_id)
-        return list_response(list_schema.dump(items))
+        return dbc.get.team_list(competition_id)
 
     @protect_route(allowed_roles=["*"])
-    def post(self, competition_id):
+    @blp.arguments(TeamAddArgsSchema)
+    @blp.response(http_codes.OK, TeamSchema)
+    @blp.alt_response(http_codes.CONFLICT, None, description="Could not add team")
+    def post(self, args, competition_id):
         """ Posts a new team to the specified competition. """
-
-        args = team_parser_add.parse_args(strict=True)
-        item_team = dbc.add.team(args["name"], competition_id)
-        return item_response(schema.dump(item_team))
+        return dbc.add.team(args["name"], competition_id)
 
 
-@api.route("/<team_id>")
-@api.param("competition_id,team_id")
-class Teams(Resource):
+@blp.route("/<team_id>")
+class TeamsById(MethodView):
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.OK, TeamSchema)
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find team")
     def get(self, competition_id, team_id):
         """ Gets the specified team. """
-
-        item = dbc.get.team(competition_id, team_id)
-        return item_response(schema.dump(item))
+        return dbc.get.team(competition_id, team_id)
 
     @protect_route(allowed_roles=["*"])
-    def put(self, competition_id, team_id):
+    @blp.arguments(TeamEditArgsSchema)
+    @blp.response(http_codes.OK, TeamSchema)
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find team")
+    def put(self, args, competition_id, team_id):
         """ Edits the specified team using the provided arguments. """
-
-        args = team_parser_edit.parse_args(strict=True)
-        name = args.get("name")
-
-        item_team = dbc.get.team(competition_id, team_id)
-
-        item_team = dbc.edit.default(item_team, name=name, competition_id=competition_id)
-        return item_response(schema.dump(item_team))
+        return dbc.edit.default(dbc.get.team(competition_id, team_id), **args)
 
     @protect_route(allowed_roles=["*"])
+    @blp.response(http_codes.NO_CONTENT, None)
+    @blp.alt_response(http_codes.NOT_FOUND, None, description="Could not find team")
     def delete(self, competition_id, team_id):
         """ Deletes the specified team. """
-
-        item_team = dbc.get.team(competition_id, team_id)
-
-        dbc.delete.team(item_team)
-        return {}, codes.NO_CONTENT
+        dbc.delete.team(dbc.get.team(competition_id, team_id))
+        return None