Add documentation for crashreports, heartbeats and logfiles endpoints

Add docstrings and method annotations as well as perform some cleanup
to match the expectations of the linters. Further update the automated
documentation file.

Issue: HIC-168
Change-Id: Iee65c44e93a056f3a6ef00ffa98d945b3401a85f
diff --git a/crashreports/rest_api_crashreports.py b/crashreports/rest_api_crashreports.py
index df99732..8cf051b 100644
--- a/crashreports/rest_api_crashreports.py
+++ b/crashreports/rest_api_crashreports.py
@@ -1,22 +1,70 @@
-from rest_framework import generics
-from crashreports.models import Crashreport
+"""REST API for accessing crash reports."""
+from drf_yasg import openapi
+from drf_yasg.utils import swagger_auto_schema
 from django.shortcuts import get_object_or_404
+from django.utils.decorators import method_decorator
+from rest_framework import status, generics
+from rest_framework.response import Response
+from rest_framework.exceptions import NotFound, ValidationError
+
 from crashreports.permissions import HasRightsOrIsDeviceOwnerDeviceCreation
 from crashreports.serializers import CrashReportSerializer
-from rest_framework import status
-from rest_framework.response import Response
+from crashreports.models import Crashreport
+from crashreports.response_descriptions import default_desc
 
 
+class CreateCrashreportResponseSchema(CrashReportSerializer):
+    """Response schema for successful crash report creation."""
+
+    class Meta:  # noqa: D106
+        model = Crashreport
+        fields = ["device_local_id"]
+
+
+@method_decorator(
+    name="get",
+    decorator=swagger_auto_schema(operation_description="List crash reports"),
+)
+@method_decorator(
+    name="post",
+    decorator=swagger_auto_schema(
+        operation_description="Create a crash report",
+        request_body=CrashReportSerializer,
+        responses=dict(
+            [
+                default_desc(ValidationError),
+                (
+                    status.HTTP_404_NOT_FOUND,
+                    openapi.Response(
+                        "No device with the given uuid could be found."
+                    ),
+                ),
+                (
+                    status.HTTP_201_CREATED,
+                    openapi.Response(
+                        "The crash report has been successfully created.",
+                        CreateCrashreportResponseSchema,
+                    ),
+                ),
+            ]
+        ),
+    ),
+)
 class ListCreateView(generics.ListCreateAPIView):
+    """Endpoint for listing crash reports and creating new crash reports."""
+
     queryset = Crashreport.objects.all()
     paginate_by = 20
     permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
     serializer_class = CrashReportSerializer
     filter_fields = ("device", "build_fingerprint", "radio_version")
 
-    pass
-
     def dispatch(self, *args, **kwargs):
+        """Dispatch an incoming HTTP request to the right method.
+
+        The method is overridden in order to replace the 'device__uuid'
+        parameter value with the 'uuid' value from the parameters.
+        """
         if "uuid" in kwargs:
             self.queryset = Crashreport.objects.filter(
                 device__uuid=kwargs["uuid"]
@@ -24,6 +72,11 @@
         return generics.ListCreateAPIView.dispatch(self, *args, **kwargs)
 
     def perform_create(self, serializer):
+        """Create a crash report instance in the database.
+
+        The method is overridden in order to create a response containing only
+        the device_local_id.
+        """
         serializer.save()
         return Response(
             {"device_local_id": serializer.data["device_local_id"]},
@@ -31,18 +84,51 @@
         )
 
 
+@method_decorator(
+    name="get",
+    decorator=swagger_auto_schema(
+        operation_description="Get a crash report",
+        responses=dict([default_desc(NotFound)]),
+    ),
+)
+@method_decorator(
+    name="put",
+    decorator=swagger_auto_schema(
+        operation_description="Update a crash report",
+        responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+    ),
+)
+@method_decorator(
+    name="patch",
+    decorator=swagger_auto_schema(
+        operation_description="Partially update a crash report",
+        responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+    ),
+)
+@method_decorator(
+    name="delete",
+    decorator=swagger_auto_schema(
+        operation_description="Delete a crash report",
+        responses=dict([default_desc(NotFound)]),
+    ),
+)
 class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
+    """Endpoint for retrieving, updating and deleting crash reports."""
+
+    # pylint: disable=too-many-ancestors
+
     queryset = Crashreport.objects.all()
     permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
     serializer_class = CrashReportSerializer
     multiple_lookup_fields = {"id", "device__uuid", "device_local_id"}
 
     def get_object(self):
+        """Retrieve a crash report."""
         queryset = self.get_queryset()
-        filter = {}
+        query_filter = {}
         for field in self.multiple_lookup_fields:
             if field in self.kwargs:
-                filter[field] = self.kwargs[field]
-        obj = get_object_or_404(queryset, **filter)
+                query_filter[field] = self.kwargs[field]
+        obj = get_object_or_404(queryset, **query_filter)
         self.check_object_permissions(self.request, obj)
         return obj
diff --git a/crashreports/rest_api_heartbeats.py b/crashreports/rest_api_heartbeats.py
index f2e19db..e2e266e 100644
--- a/crashreports/rest_api_heartbeats.py
+++ b/crashreports/rest_api_heartbeats.py
@@ -1,14 +1,46 @@
-from rest_framework import generics
+"""REST API for accessing heartbeats."""
+
 from django.shortcuts import get_object_or_404
+from django.utils.decorators import method_decorator
+from drf_yasg import openapi
+from drf_yasg.utils import swagger_auto_schema
+from rest_framework import generics, status
+from rest_framework.exceptions import NotFound, ValidationError
+
 from crashreports.models import HeartBeat
-from crashreports.serializers import HeartBeatSerializer
 from crashreports.permissions import HasRightsOrIsDeviceOwnerDeviceCreation
+from crashreports.response_descriptions import default_desc
+from crashreports.serializers import HeartBeatSerializer
 
 # TODO: There is quite some code duplciation between here and the corresponding
 #       crashreport code. We should revisit this later.
 
 
+@method_decorator(
+    name="get",
+    decorator=swagger_auto_schema(operation_description="List heartbeats"),
+)
+@method_decorator(
+    name="post",
+    decorator=swagger_auto_schema(
+        operation_description="Create a heartbeat",
+        request_body=HeartBeatSerializer,
+        responses=dict(
+            [
+                default_desc(ValidationError),
+                (
+                    status.HTTP_404_NOT_FOUND,
+                    openapi.Response(
+                        "No device with the given uuid could be found."
+                    ),
+                ),
+            ]
+        ),
+    ),
+)
 class ListCreateView(generics.ListCreateAPIView):
+    """Endpoint for listing heartbeats and creating new heartbeats."""
+
     queryset = HeartBeat.objects.all()
     paginate_by = 20
     permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
@@ -16,6 +48,7 @@
     filter_fields = ("device", "build_fingerprint", "radio_version")
 
     def get(self, *args, **kwargs):
+        """Override device__uuid parameter with uuid."""
         if "uuid" in kwargs:
             self.queryset = HeartBeat.objects.filter(
                 device__uuid=kwargs["uuid"]
@@ -23,18 +56,51 @@
         return generics.ListCreateAPIView.get(self, *args, **kwargs)
 
 
+@method_decorator(
+    name="get",
+    decorator=swagger_auto_schema(
+        operation_description="Get a heartbeat",
+        responses=dict([default_desc(NotFound)]),
+    ),
+)
+@method_decorator(
+    name="put",
+    decorator=swagger_auto_schema(
+        operation_description="Update a heartbeat",
+        responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+    ),
+)
+@method_decorator(
+    name="patch",
+    decorator=swagger_auto_schema(
+        operation_description="Partially update a heartbeat",
+        responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+    ),
+)
+@method_decorator(
+    name="delete",
+    decorator=swagger_auto_schema(
+        operation_description="Delete a heartbeat",
+        responses=dict([default_desc(NotFound)]),
+    ),
+)
 class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
+    """Endpoint for retrieving, updating and deleting heartbeats."""
+
+    # pylint: disable=too-many-ancestors
+
     queryset = HeartBeat.objects.all()
     permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
     serializer_class = HeartBeatSerializer
     multiple_lookup_fields = {"id", "device__uuid", "device_local_id"}
 
     def get_object(self):
+        """Retrieve a heartbeat."""
         queryset = self.get_queryset()
-        filter = {}
+        query_filter = {}
         for field in self.multiple_lookup_fields:
             if field in self.kwargs:
-                filter[field] = self.kwargs[field]
-        obj = get_object_or_404(queryset, **filter)
+                query_filter[field] = self.kwargs[field]
+        obj = get_object_or_404(queryset, **query_filter)
         self.check_object_permissions(self.request, obj)
         return obj
diff --git a/crashreports/rest_api_logfiles.py b/crashreports/rest_api_logfiles.py
index df3bbcb..6563caa 100644
--- a/crashreports/rest_api_logfiles.py
+++ b/crashreports/rest_api_logfiles.py
@@ -1,45 +1,108 @@
-from rest_framework.decorators import api_view
-from rest_framework.decorators import parser_classes
-from rest_framework.decorators import permission_classes
+"""REST API for accessing log files."""
+from django.core.exceptions import ObjectDoesNotExist
+from django.utils.decorators import method_decorator
+from drf_yasg import openapi
+from drf_yasg.utils import swagger_auto_schema
 
+from rest_framework import generics, status
+from rest_framework.decorators import (
+    api_view,
+    parser_classes,
+    permission_classes,
+)
+from rest_framework.exceptions import (
+    PermissionDenied,
+    NotFound,
+    ValidationError,
+)
 from rest_framework.parsers import FileUploadParser
 from rest_framework.permissions import IsAuthenticated
-from rest_framework.exceptions import PermissionDenied
-from rest_framework.exceptions import NotFound
-
 from rest_framework.response import Response
 
+from crashreports.response_descriptions import default_desc
 from crashreports.serializers import LogFileSerializer
-
-from crashreports.models import LogFile
-from crashreports.models import Crashreport
-from crashreports.permissions import user_owns_uuid
-from crashreports.permissions import user_is_hiccup_staff
-from crashreports.permissions import HasRightsOrIsDeviceOwnerDeviceCreation
-from rest_framework import generics
+from crashreports.models import Crashreport, LogFile
+from crashreports.permissions import (
+    HasRightsOrIsDeviceOwnerDeviceCreation,
+    user_owns_uuid,
+    user_is_hiccup_staff,
+)
 
 
+@method_decorator(
+    name="get",
+    decorator=swagger_auto_schema(operation_description="List log files"),
+)
 class ListCreateView(generics.ListAPIView):
+    """Endpoint for listing log files."""
+
     queryset = LogFile.objects.all()
     permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
     serializer_class = LogFileSerializer
 
 
+@method_decorator(
+    name="get",
+    decorator=swagger_auto_schema(
+        operation_description="Get a log file",
+        responses=dict([default_desc(NotFound)]),
+    ),
+)
+@method_decorator(
+    name="put",
+    decorator=swagger_auto_schema(
+        operation_description="Update a log file",
+        responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+    ),
+)
+@method_decorator(
+    name="patch",
+    decorator=swagger_auto_schema(
+        operation_description="Partially update a log file",
+        responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
+    ),
+)
+@method_decorator(
+    name="delete",
+    decorator=swagger_auto_schema(
+        operation_description="Delete a log file",
+        responses=dict([default_desc(NotFound)]),
+    ),
+)
 class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
+    """Endpoint for retrieving, updating and deleting log files."""
+
+    # pylint: disable=too-many-ancestors
+
     queryset = LogFile.objects.all()
     permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
     serializer_class = LogFileSerializer
 
 
+@swagger_auto_schema(
+    method="post",
+    request_body=LogFileSerializer,
+    responses=dict(
+        [
+            default_desc(ValidationError),
+            (
+                status.HTTP_404_NOT_FOUND,
+                openapi.Response("Crashreport does not exist."),
+            ),
+            (status.HTTP_201_CREATED, openapi.Response("Created")),
+        ]
+    ),
+)
 @api_view(http_method_names=["POST"])
 @parser_classes([FileUploadParser])
 @permission_classes([IsAuthenticated])
 def logfile_put(request, uuid, device_local_id, filename):
+    """Upload a log file for a crash report."""
     try:
         crashreport = Crashreport.objects.get(
             device__uuid=uuid, device_local_id=device_local_id
         )
-    except:
+    except ObjectDoesNotExist:
         raise NotFound(detail="Crashreport does not exist.")
 
     if not (
@@ -47,7 +110,7 @@
         or user_is_hiccup_staff(request.user)
     ):
         raise PermissionDenied(detail="Not allowed.")
-    f = request.data["file"]
-    logfile = LogFile(crashreport=crashreport, logfile=f)
+    file = request.data["file"]
+    logfile = LogFile(crashreport=crashreport, logfile=file)
     logfile.save()
     return Response(status=201)
diff --git a/documentation/api-endpoints.md b/documentation/api-endpoints.md
index 1ae3f29..c31c3f0 100644
--- a/documentation/api-endpoints.md
+++ b/documentation/api-endpoints.md
@@ -30,6 +30,10 @@
 <a name="hiccup_api_v1_crashreports_create"></a>
 ### POST /hiccup/api/v1/crashreports/
 
+#### Description
+Create a crash report
+
+
 #### Body parameter
 *Name* : data  
 *Flags* : required  
@@ -38,9 +42,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**201**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**201**|The crash report has been successfully created.|[CreateCrashreportResponseSchema](#createcrashreportresponseschema)|
+|**400**|Invalid input.|No Content|
+|**404**|No device with the given uuid could be found.|No Content|
 
 
 #### Tags
@@ -83,21 +89,7 @@
 ##### Response 201
 ```json
 {
-  "id" : "string",
-  "logfiles" : [ "string" ],
-  "uuid" : "string",
-  "device_local_id" : 0,
-  "date" : "string",
-  "is_fake_report" : true,
-  "app_version" : 0,
-  "uptime" : "string",
-  "build_fingerprint" : "string",
-  "radio_version" : "string",
-  "boot_reason" : "string",
-  "power_on_reason" : "string",
-  "power_off_reason" : "string",
-  "next_logfile_key" : 0,
-  "created_at" : "string"
+  "device_local_id" : 0
 }
 ```
 
@@ -105,6 +97,10 @@
 <a name="hiccup_api_v1_crashreports_list"></a>
 ### GET /hiccup/api/v1/crashreports/
 
+#### Description
+List crash reports
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -157,6 +153,10 @@
 <a name="hiccup_api_v1_crashreports_read"></a>
 ### GET /hiccup/api/v1/crashreports/{id}/
 
+#### Description
+Get a crash report
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -166,9 +166,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[CrashReport](#crashreport)|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -211,6 +212,10 @@
 <a name="hiccup_api_v1_crashreports_update"></a>
 ### PUT /hiccup/api/v1/crashreports/{id}/
 
+#### Description
+Update a crash report
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -226,9 +231,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[CrashReport](#crashreport)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -293,6 +300,10 @@
 <a name="hiccup_api_v1_crashreports_delete"></a>
 ### DELETE /hiccup/api/v1/crashreports/{id}/
 
+#### Description
+Delete a crash report
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -302,9 +313,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**204**|No Content|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**204**||No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -323,6 +335,10 @@
 <a name="hiccup_api_v1_crashreports_partial_update"></a>
 ### PATCH /hiccup/api/v1/crashreports/{id}/
 
+#### Description
+Partially update a crash report
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -338,9 +354,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[CrashReport](#crashreport)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -589,6 +607,10 @@
 <a name="hiccup_api_v1_devices_crashreports_read"></a>
 ### GET /hiccup/api/v1/devices/{device__uuid}/crashreports/{device_local_id}/
 
+#### Description
+Get a crash report
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -599,9 +621,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[CrashReport](#crashreport)|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -644,6 +667,10 @@
 <a name="hiccup_api_v1_devices_crashreports_update"></a>
 ### PUT /hiccup/api/v1/devices/{device__uuid}/crashreports/{device_local_id}/
 
+#### Description
+Update a crash report
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -660,9 +687,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[CrashReport](#crashreport)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -727,6 +756,10 @@
 <a name="hiccup_api_v1_devices_crashreports_delete"></a>
 ### DELETE /hiccup/api/v1/devices/{device__uuid}/crashreports/{device_local_id}/
 
+#### Description
+Delete a crash report
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -737,9 +770,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**204**|No Content|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**204**||No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -758,6 +792,10 @@
 <a name="hiccup_api_v1_devices_crashreports_partial_update"></a>
 ### PATCH /hiccup/api/v1/devices/{device__uuid}/crashreports/{device_local_id}/
 
+#### Description
+Partially update a crash report
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -774,9 +812,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[CrashReport](#crashreport)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1086,6 +1126,10 @@
 <a name="hiccup_api_v1_devices_crashreports_create"></a>
 ### POST /hiccup/api/v1/devices/{uuid}/crashreports/
 
+#### Description
+Create a crash report
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1101,9 +1145,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**201**|[CrashReport](#crashreport)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**201**|The crash report has been successfully created.|[CreateCrashreportResponseSchema](#createcrashreportresponseschema)|
+|**400**|Invalid input.|No Content|
+|**404**|No device with the given uuid could be found.|No Content|
 
 
 #### Tags
@@ -1146,21 +1192,7 @@
 ##### Response 201
 ```json
 {
-  "id" : "string",
-  "logfiles" : [ "string" ],
-  "uuid" : "string",
-  "device_local_id" : 0,
-  "date" : "string",
-  "is_fake_report" : true,
-  "app_version" : 0,
-  "uptime" : "string",
-  "build_fingerprint" : "string",
-  "radio_version" : "string",
-  "boot_reason" : "string",
-  "power_on_reason" : "string",
-  "power_off_reason" : "string",
-  "next_logfile_key" : 0,
-  "created_at" : "string"
+  "device_local_id" : 0
 }
 ```
 
@@ -1168,6 +1200,10 @@
 <a name="hiccup_api_v1_devices_crashreports_list"></a>
 ### GET /hiccup/api/v1/devices/{uuid}/crashreports/
 
+#### Description
+List crash reports
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1221,6 +1257,10 @@
 <a name="hiccup_api_v1_devices_crashreports_logfile_put_create"></a>
 ### POST /hiccup/api/v1/devices/{uuid}/crashreports/{device_local_id}/logfile_put/{filename}/
 
+#### Description
+Upload a log file for a crash report.
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1230,11 +1270,19 @@
 |**Path**|**uuid**  <br>*required*|string|
 
 
+#### Body parameter
+*Name* : data  
+*Flags* : required  
+*Type* : [LogFile](#logfile)
+
+
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**201**|No Content|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**201**|Created|No Content|
+|**400**|Invalid input.|No Content|
+|**404**|Crashreport does not exist.|No Content|
 
 
 #### Consumes
@@ -1255,9 +1303,26 @@
 ```
 
 
+##### Request body
+```json
+{
+  "id" : 0,
+  "logfile_type" : "string",
+  "logfile" : "string",
+  "crashreport_local_id" : 0,
+  "created_at" : "string",
+  "crashreport" : 0
+}
+```
+
+
 <a name="hiccup_api_v1_devices_heartbeats_create"></a>
 ### POST /hiccup/api/v1/devices/{uuid}/heartbeats/
 
+#### Description
+Create a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1273,9 +1338,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**201**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**201**||[HeartBeat](#heartbeat)|
+|**400**|Invalid input.|No Content|
+|**404**|No device with the given uuid could be found.|No Content|
 
 
 #### Tags
@@ -1328,6 +1395,10 @@
 <a name="hiccup_api_v1_devices_heartbeats_list"></a>
 ### GET /hiccup/api/v1/devices/{uuid}/heartbeats/
 
+#### Description
+List heartbeats
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1381,6 +1452,10 @@
 <a name="hiccup_api_v1_devices_heartbeats_read"></a>
 ### GET /hiccup/api/v1/devices/{uuid}/heartbeats/{device_local_id}/
 
+#### Description
+Get a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1391,9 +1466,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[HeartBeat](#heartbeat)|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1430,6 +1506,10 @@
 <a name="hiccup_api_v1_devices_heartbeats_update"></a>
 ### PUT /hiccup/api/v1/devices/{uuid}/heartbeats/{device_local_id}/
 
+#### Description
+Update a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1446,9 +1526,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[HeartBeat](#heartbeat)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1501,6 +1583,10 @@
 <a name="hiccup_api_v1_devices_heartbeats_delete"></a>
 ### DELETE /hiccup/api/v1/devices/{uuid}/heartbeats/{device_local_id}/
 
+#### Description
+Delete a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1511,9 +1597,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**204**|No Content|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**204**||No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1532,6 +1619,10 @@
 <a name="hiccup_api_v1_devices_heartbeats_partial_update"></a>
 ### PATCH /hiccup/api/v1/devices/{uuid}/heartbeats/{device_local_id}/
 
+#### Description
+Partially update a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Schema|
@@ -1548,9 +1639,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[HeartBeat](#heartbeat)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1603,6 +1696,10 @@
 <a name="hiccup_api_v1_heartbeats_create"></a>
 ### POST /hiccup/api/v1/heartbeats/
 
+#### Description
+Create a heartbeat
+
+
 #### Body parameter
 *Name* : data  
 *Flags* : required  
@@ -1611,9 +1708,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**201**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**201**||[HeartBeat](#heartbeat)|
+|**400**|Invalid input.|No Content|
+|**404**|No device with the given uuid could be found.|No Content|
 
 
 #### Tags
@@ -1666,6 +1765,10 @@
 <a name="hiccup_api_v1_heartbeats_list"></a>
 ### GET /hiccup/api/v1/heartbeats/
 
+#### Description
+List heartbeats
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1718,6 +1821,10 @@
 <a name="hiccup_api_v1_heartbeats_read"></a>
 ### GET /hiccup/api/v1/heartbeats/{id}/
 
+#### Description
+Get a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1727,9 +1834,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[HeartBeat](#heartbeat)|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1766,6 +1874,10 @@
 <a name="hiccup_api_v1_heartbeats_update"></a>
 ### PUT /hiccup/api/v1/heartbeats/{id}/
 
+#### Description
+Update a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1781,9 +1893,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[HeartBeat](#heartbeat)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1836,6 +1950,10 @@
 <a name="hiccup_api_v1_heartbeats_delete"></a>
 ### DELETE /hiccup/api/v1/heartbeats/{id}/
 
+#### Description
+Delete a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1845,9 +1963,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**204**|No Content|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**204**||No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1866,6 +1985,10 @@
 <a name="hiccup_api_v1_heartbeats_partial_update"></a>
 ### PATCH /hiccup/api/v1/heartbeats/{id}/
 
+#### Description
+Partially update a heartbeat
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1881,9 +2004,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[HeartBeat](#heartbeat)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[HeartBeat](#heartbeat)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -1936,6 +2061,10 @@
 <a name="hiccup_api_v1_logfiles_list"></a>
 ### GET /hiccup/api/v1/logfiles/
 
+#### Description
+List log files
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1985,6 +2114,10 @@
 <a name="hiccup_api_v1_logfiles_read"></a>
 ### GET /hiccup/api/v1/logfiles/{id}/
 
+#### Description
+Get a log file
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -1994,9 +2127,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[LogFile](#logfile)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[LogFile](#logfile)|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -2030,6 +2164,10 @@
 <a name="hiccup_api_v1_logfiles_update"></a>
 ### PUT /hiccup/api/v1/logfiles/{id}/
 
+#### Description
+Update a log file
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -2045,9 +2183,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[LogFile](#logfile)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[LogFile](#logfile)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -2094,6 +2234,10 @@
 <a name="hiccup_api_v1_logfiles_delete"></a>
 ### DELETE /hiccup/api/v1/logfiles/{id}/
 
+#### Description
+Delete a log file
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -2103,9 +2247,10 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**204**|No Content|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**204**||No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -2124,6 +2269,10 @@
 <a name="hiccup_api_v1_logfiles_partial_update"></a>
 ### PATCH /hiccup/api/v1/logfiles/{id}/
 
+#### Description
+Partially update a log file
+
+
 #### Parameters
 
 |Type|Name|Description|Schema|
@@ -2139,9 +2288,11 @@
 
 #### Responses
 
-|HTTP Code|Schema|
-|---|---|
-|**200**|[LogFile](#logfile)|
+|HTTP Code|Description|Schema|
+|---|---|---|
+|**200**||[LogFile](#logfile)|
+|**400**|Invalid input.|No Content|
+|**404**|Not found.|No Content|
 
 
 #### Tags
@@ -2669,6 +2820,14 @@
 |**uuid**  <br>*required*|**Length** : `1 - 64`  <br>**Example** : `"string"`|string|
 
 
+<a name="createcrashreportresponseschema"></a>
+### CreateCrashreportResponseSchema
+
+|Name|Description|Schema|
+|---|---|---|
+|**device_local_id**  <br>*optional*|**Example** : `0`|integer|
+
+
 <a name="device"></a>
 ### Device