diff --git a/projects/views.py b/projects/views.py
index 18ccff62895f9605a94d48f315bf3728b4f4126d..8e82f19d99029815934a4e01c204b3c19610deb9 100644
--- a/projects/views.py
+++ b/projects/views.py
@@ -39,7 +39,7 @@ class ProjectViewSet(viewsets.ReadOnlyModelViewSet):
                 "id": 1,
                 "url": "http://localhost:8000/api/projects/1/",
                 "name": "Oser la Prépa",
-                "description": "Oser la Prépa est un stage d'acclimatation aux Classes Préparatoires de deux semaines qui se déroule chaque été.",
+                "description": "Oser la Prépa est un stage d'acclimatation…",
                 "logo": null
             }
         ]
@@ -421,6 +421,19 @@ class ParticipationViewSet(mixins.CreateModelMixin, mixins.DestroyModelMixin,
     filter_backends = (filters.backends.DjangoFilterBackend,)
     filter_fields = ('user', 'state',)
 
+    @action(methods=['post'], detail=True)
+    def cancel(self, request, pk=None):
+        """Cancel a participation.
+
+        Note: the participation is not removed from the database,
+        it is only marked as cancelled.
+        Use [destroy](#project-participation-destroy) to delete it.
+        """
+        participation = self.get_object()
+        participation.state = Participation.STATE_CANCELLED
+        participation.save()
+        return Response(None, status=status.HTTP_204_NO_CONTENT)
+
     @action(methods=['get'], detail=True)
     def form_entry(self, request, pk=None):
         """Return the answers to the edition form for a participation.