diff --git a/beat/web/toolchains/api.py b/beat/web/toolchains/api.py
index 61449b657e3cc2f9487b272e1fe9e1ee11e55a7a..1d861e1b985cb1f2649a73c4cf8c2ac1925dc2fe 100644
--- a/beat/web/toolchains/api.py
+++ b/beat/web/toolchains/api.py
@@ -25,16 +25,6 @@
 #                                                                             #
 ###############################################################################
 
-import simplejson as json
-
-from django.conf import settings
-from django.shortcuts import get_object_or_404
-from django.utils import six
-from django.core.exceptions import ValidationError
-
-from rest_framework.response import Response
-from rest_framework import serializers
-from rest_framework import exceptions as drf_exceptions
 
 from ..common.api import (
     CheckContributionNameView,
@@ -47,12 +37,9 @@ from .models import Toolchain
 from .serializers import ToolchainSerializer
 from .serializers import FullToolchainSerializer
 from .serializers import ToolchainCreationSerializer
+from .serializers import ToolchainModSerializer
 
 from ..common.api import ListContributionView
-from ..common.utils import validate_restructuredtext, ensure_html
-from ..experiments.models import Experiment
-
-import beat.core.toolchain
 
 
 # ----------------------------------------------------------
@@ -116,170 +103,4 @@ class RetrieveUpdateDestroyToolchainsView(RetrieveUpdateDestroyContributionView)
 
     model = Toolchain
     serializer_class = FullToolchainSerializer
-
-    def put(self, request, author_name, object_name, version):
-        try:
-            data = request.data
-        except drf_exceptions.ParseError as e:
-            raise serializers.ValidationError({"data": str(e)})
-        else:
-            if not data:
-                raise serializers.ValidationError({"data": "Empty"})
-
-        if "short_description" in data:
-            if not (isinstance(data["short_description"], six.string_types)):
-                raise serializers.ValidationError(
-                    {"short_description", "Invalid short_description data"}
-                )
-            short_description = data["short_description"]
-        else:
-            short_description = None
-
-        if "description" in data:
-            if not (isinstance(data["description"], six.string_types)):
-                raise serializers.ValidationError(
-                    {"description": "Invalid description data"}
-                )
-            description = data["description"]
-            try:
-                validate_restructuredtext(description)
-            except ValidationError as errors:
-                raise serializers.ValidationError(
-                    {"description": [error for error in errors]}
-                )
-        else:
-            description = None
-
-        if "strict" in data:
-            strict = data["strict"]
-        else:
-            strict = True
-
-        if "declaration" in data:
-            if isinstance(data["declaration"], dict):
-                json_declaration = data["declaration"]
-                declaration = json.dumps(json_declaration, indent=4)
-            elif isinstance(data["declaration"], six.string_types):
-                declaration = data["declaration"]
-                try:
-                    json_declaration = json.loads(declaration)
-                except json.decoder.JSONDecodeError:
-                    raise serializers.ValidationError(
-                        {"declaration": "Invalid declaration data"}
-                    )
-            else:
-                raise serializers.ValidationError(
-                    {"declaration": "Invalid declaration data"}
-                )
-
-            if "description" in json_declaration:
-                if short_description is not None:
-                    raise serializers.ValidationError(
-                        {
-                            "short_description": "A short description is already provided in the toolchain declaration"
-                        }
-                    )
-
-                short_description = json_declaration["description"]
-            elif short_description is not None:
-                json_declaration["description"] = short_description
-                declaration = json.dumps(json_declaration, indent=4)
-
-            toolchain_declaration = beat.core.toolchain.Toolchain(
-                settings.PREFIX, json_declaration
-            )
-
-            if not toolchain_declaration.valid:
-                if strict:
-                    raise serializers.ValidationError(
-                        {"declaration": toolchain_declaration.errors}
-                    )
-
-        else:
-            declaration = None
-
-        if (short_description is not None) and (
-            len(short_description)
-            > self.model._meta.get_field("short_description").max_length
-        ):
-            raise serializers.ValidationError(
-                {"short_description": "Short description too long"}
-            )
-
-        # Process the query string
-        if "fields" in request.GET:
-            fields_to_return = request.GET["fields"].split(",")
-        else:
-            # Available fields (not returned by default):
-            #    - html_description
-            fields_to_return = ["errors"]
-
-        # Retrieve the toolchain
-        dbtoolchain = get_object_or_404(
-            Toolchain,
-            author__username__iexact=author_name,
-            name__iexact=object_name,
-            version=version,
-        )
-
-        # Check that the object can still be modified (if applicable, the
-        # documentation can always be modified)
-        if declaration is not None and not dbtoolchain.modifiable():
-            raise drf_exceptions.PermissionDenied(
-                "The {} isn't modifiable anymore (either shared with someone else, or needed by an attestation)".format(
-                    dbtoolchain.model_name()
-                )
-            )
-
-        errors = None
-
-        # Modification of the short_description
-        if (short_description is not None) and (declaration is None):
-            tmp_declaration = dbtoolchain.declaration
-            tmp_declaration["description"] = short_description
-            dbtoolchain.declaration = tmp_declaration
-
-        # Modification of the description
-        if description is not None:
-            dbtoolchain.description = description
-
-        # Modification of the declaration
-        if declaration is not None:
-            errors = ""
-            if not toolchain_declaration.valid:
-                errors = " * %s" % "\n * ".join(toolchain_declaration.errors)
-
-            dbtoolchain.errors = errors
-            dbtoolchain.declaration = declaration
-
-            experiments = Experiment.objects.filter(toolchain=dbtoolchain)
-            experiments.delete()
-
-        # Save the toolchain model
-        try:
-            dbtoolchain.save()
-        except Exception as e:
-            raise drf_exceptions.APIException(str(e))
-
-        # Nothing to return?
-        if len(fields_to_return) == 0:
-            return Response(status=204)
-
-        result = {}
-
-        # Retrieve the errors (if necessary)
-        if "errors" in fields_to_return:
-            if errors:
-                result["errors"] = errors
-            else:
-                result["errors"] = ""
-
-        # Retrieve the description in HTML format (if necessary)
-        if "html_description" in fields_to_return:
-            description = dbtoolchain.description
-            if len(description) > 0:
-                result["html_description"] = ensure_html(description)
-            else:
-                result["html_description"] = ""
-
-        return Response(result)
+    writing_serializer_class = ToolchainModSerializer