diff --git a/hypha/apply/api/urls.py b/hypha/apply/api/urls.py
index 52f7c206e9b288a4582041c19bdfac655c795555..1c3b8c4f5287d1236558b9b01be8525b6ad24019 100644
--- a/hypha/apply/api/urls.py
+++ b/hypha/apply/api/urls.py
@@ -1,10 +1,28 @@
 from django.urls import include, path
+from drf_yasg import openapi
+from drf_yasg.views import get_schema_view
+from rest_framework import permissions
 
 from .v1 import urls as v1_urls
 
 app_name = 'api'
 
+schema_url_patterns = [
+    path('api/v1/', include(v1_urls)),
+]
+
+schema_view = get_schema_view(
+    openapi.Info(
+        title="Hypha API",
+        default_version='v1',
+        description="Hypha APIs specification",
+    ),
+    public=False,
+    patterns=schema_url_patterns,
+    permission_classes=(permissions.AllowAny,),
+)
 
 urlpatterns = [
     path('v1/', include(v1_urls)),
+    path('doc/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
 ]
diff --git a/hypha/apply/api/v1/views.py b/hypha/apply/api/v1/views.py
index e4b247cfb744fa2cf074badbb6d9d9b4f25da691..3d483dfd5707ae8d167c0874df51040fa05a39be 100644
--- a/hypha/apply/api/v1/views.py
+++ b/hypha/apply/api/v1/views.py
@@ -68,6 +68,9 @@ class SubmissionsFilter(filters.FilterSet):
 
 
 class SubmissionList(generics.ListAPIView):
+    """
+    List all the submissions.
+    """
     queryset = ApplicationSubmission.objects.current().with_latest_update()
     serializer_class = SubmissionListSerializer
     permission_classes = (
@@ -79,6 +82,9 @@ class SubmissionList(generics.ListAPIView):
 
 
 class SubmissionDetail(generics.RetrieveAPIView):
+    """
+    Get details about a submission by it's id.
+    """
     queryset = ApplicationSubmission.objects.all().prefetch_related(
         Prefetch('reviews', Review.objects.submitted()),
     )
@@ -89,6 +95,11 @@ class SubmissionDetail(generics.RetrieveAPIView):
 
 
 class SubmissionAction(generics.RetrieveAPIView):
+    """
+    List all the actions that can be taken on a submission.
+
+    E.g. All the states this submission can be transistion to.
+    """
     queryset = ApplicationSubmission.objects.all()
     serializer_class = SubmissionActionSerializer
     permission_classes = (
@@ -96,6 +107,16 @@ class SubmissionAction(generics.RetrieveAPIView):
     )
 
     def post(self, request, *args, **kwargs):
+        """
+        Transistion a submission from one state to other.
+
+        E.g. To transition a submission from `Screening` to `Internal Review`
+        following post data can be used:
+
+        ```
+        {"action": "internal_review"}
+        ```
+        """
         action = request.data.get('action')
         if not action:
             raise ValidationError('Action must be provided.')
@@ -126,6 +147,9 @@ class SubmissionAction(generics.RetrieveAPIView):
 
 
 class RoundLabDetail(generics.RetrieveAPIView):
+    """
+    Get detail about a round or a lab.
+    """
     queryset = RoundsAndLabs.objects.all()
     serializer_class = RoundLabDetailSerializer
     permission_classes = (
@@ -137,6 +161,9 @@ class RoundLabDetail(generics.RetrieveAPIView):
 
 
 class RoundLabList(generics.ListAPIView):
+    """
+    List all the rounds and labs current user has access to.
+    """
     queryset = RoundsAndLabs.objects.specific()
     serializer_class = RoundLabSerializer
     permission_classes = (
@@ -169,6 +196,9 @@ class AllCommentFilter(CommentFilter):
 
 
 class CommentList(generics.ListAPIView):
+    """
+    List all the comments for a user.
+    """
     queryset = Activity.comments.all()
     serializer_class = CommentSerializer
     permission_classes = (
@@ -183,6 +213,9 @@ class CommentList(generics.ListAPIView):
 
 
 class CommentListCreate(generics.ListCreateAPIView):
+    """
+    List all the comments on a submission.
+    """
     queryset = Activity.comments.all().select_related('user')
     serializer_class = CommentCreateSerializer
     permission_classes = (
@@ -198,6 +231,9 @@ class CommentListCreate(generics.ListCreateAPIView):
         ).visible_to(self.request.user)
 
     def perform_create(self, serializer):
+        """
+        Add a comment on a submission.
+        """
         obj = serializer.save(
             timestamp=timezone.now(),
             type=COMMENT,
@@ -218,6 +254,9 @@ class CommentEdit(
         mixins.CreateModelMixin,
         generics.GenericAPIView,
 ):
+    """
+    Edit a comment.
+    """
     queryset = Activity.comments.all().select_related('user')
     serializer_class = CommentEditSerializer
     permission_classes = (
diff --git a/hypha/settings/base.py b/hypha/settings/base.py
index 55956fa8407d8afd826f96d95e2518c873f2417a..f54966426e4372f3b257fb302f2b676670f862cc 100644
--- a/hypha/settings/base.py
+++ b/hypha/settings/base.py
@@ -127,6 +127,7 @@ INSTALLED_APPS = [
     'django_otp.plugins.otp_totp',
     'django_otp.plugins.otp_static',
     'two_factor',
+    'drf_yasg',
     'rest_framework',
     'rest_framework_api_key',
     'wagtailcache',
diff --git a/requirements.txt b/requirements.txt
index 06544ec01bddf13310086fce9530a29d48c343a9..806d694391b24b70871d43f6fc04daf06a722364 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -28,6 +28,7 @@ django_select2==7.2.2
 djangorestframework==3.9.2
 djangorestframework-api-key==1.4.1
 django==2.2.14
+drf-yasg==1.17.1
 gunicorn==20.0.4
 mailchimp3==3.0.14
 mistune==0.8.4