Add drf_yasg app for creating automated documentation

Further cleanup code to match the expectations of the linters and
add tox commands for building the documentation.

Issue: HIC-167
Change-Id: I816a578bc7995f4560c19003d0cc907a22e740b6
diff --git a/.gitignore b/.gitignore
index edea457..714a6fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -89,6 +89,13 @@
 # Rope project settings
 .ropeproject
 
+# Jar for generating documentation
+swagger2markup-cli-*.jar
+
+# Generated openapi documentation artifacts
+documentation/hiccup-api.json
+documentation/api-endpoints.adoc
+documentation/api-endpoints.html
 
 saved_crashredports
 
diff --git a/README.md b/README.md
index 8e61986..8b61430 100644
--- a/README.md
+++ b/README.md
@@ -103,6 +103,31 @@
 * Go back to the user list at `http://localhost:8000/hiccup/admin/auth/user/` and add your
   super-user to the new group.
 
+## API Documentation
+
+The Hiccup REST API documentation is created automatically using
+[drf_yasg](https://github.com/axnsan12/drf-yasg) and
+[swagger2markup](https://github.com/Swagger2Markup/swagger2markup).
+
+It can be generated using tox:
+
+    (hiccupenv) $ tox -e docs
+
+The generated documentation file can be found under
+`documentation/api-endpoints.md`.
+
+It is also possible to create an HTML version of the docs. Make sure you
+have asciidoctor installed:
+
+    (hiccupenv) $ sudo apt install asciidoctor
+
+Then generate the html docs using tox:
+
+    (hiccupenv) $ tox -e docs-html
+
+The generated documentation file can be found under
+`documentation/api-endpoints.html`.
+
 
 ## Development
 
diff --git a/documentation/hiccup-api.json b/documentation/hiccup-api.json
deleted file mode 100644
index 4ad2a40..0000000
--- a/documentation/hiccup-api.json
+++ /dev/null
@@ -1,1442 +0,0 @@
-{
-  "swagger": "2.0",
-  "info": {
-    "title": "Hiccup API",
-    "description": "",
-    "version": ""
-  },
-  "paths": {
-    "/hiccup/api/v1/devices/": {
-      "post": {
-        "tags": [
-          "devices"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "201": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "schema": {
-              "required": [
-                "board_date",
-                "last_heartbeat",
-                "user"
-              ],
-              "type": "object",
-              "properties": {
-                "board_date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_per_heartbeat_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_per_crashreport_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "token": {
-                  "type": "string",
-                  "description": ""
-                },
-                "user": {
-                  "type": "string",
-                  "description": ""
-                },
-                "imei": {
-                  "type": "string",
-                  "description": ""
-                },
-                "chipset": {
-                  "type": "string",
-                  "description": ""
-                },
-                "last_heartbeat": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "devices_create"
-      }
-    },
-    "/hiccup/api/v1/devices/register/": {
-      "post": {
-        "tags": [
-          "register"
-        ],
-        "responses": {
-          "201": {
-            "description": ""
-          }
-        },
-        "parameters": [],
-        "operationId": "register_create"
-      }
-    },
-    "/hiccup/api/v1/devices/{device__uuid}/crashreports/{device_local_id}/": {
-      "get": {
-        "tags": [
-          "crashreports"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device__uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "limit",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "offset",
-            "in": "query"
-          }
-        ],
-        "operationId": "crashreports_read"
-      },
-      "put": {
-        "tags": [
-          "crashreports"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device__uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "required": [
-                "uuid",
-                "date",
-                "app_version",
-                "uptime",
-                "build_fingerprint",
-                "boot_reason",
-                "power_on_reason",
-                "power_off_reason"
-              ],
-              "type": "object",
-              "properties": {
-                "uptime": {
-                  "type": "string",
-                  "description": ""
-                },
-                "is_fake_report": {
-                  "type": "string",
-                  "description": ""
-                },
-                "uuid": {
-                  "type": "string",
-                  "description": ""
-                },
-                "boot_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "power_on_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "build_fingerprint": {
-                  "type": "string",
-                  "description": ""
-                },
-                "power_off_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "radio_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_logfile_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "app_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "device_local_id": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "crashreports_update"
-      },
-      "patch": {
-        "tags": [
-          "crashreports"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device__uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "type": "object",
-              "properties": {
-                "uptime": {
-                  "type": "string",
-                  "description": ""
-                },
-                "is_fake_report": {
-                  "type": "string",
-                  "description": ""
-                },
-                "uuid": {
-                  "type": "string",
-                  "description": ""
-                },
-                "boot_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "power_on_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "build_fingerprint": {
-                  "type": "string",
-                  "description": ""
-                },
-                "power_off_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "radio_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_logfile_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "app_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "device_local_id": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "crashreports_partial_update"
-      },
-      "delete": {
-        "tags": [
-          "crashreports"
-        ],
-        "responses": {
-          "204": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device__uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          }
-        ],
-        "operationId": "crashreports_destroy"
-      }
-    },
-    "/hiccup/api/v1/devices/{uuid}/": {
-      "get": {
-        "tags": [
-          "devices"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "limit",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "offset",
-            "in": "query"
-          }
-        ],
-        "operationId": "devices_read"
-      },
-      "put": {
-        "tags": [
-          "devices"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "required": [
-                "board_date",
-                "last_heartbeat",
-                "user"
-              ],
-              "type": "object",
-              "properties": {
-                "board_date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_per_heartbeat_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_per_crashreport_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "token": {
-                  "type": "string",
-                  "description": ""
-                },
-                "user": {
-                  "type": "string",
-                  "description": ""
-                },
-                "imei": {
-                  "type": "string",
-                  "description": ""
-                },
-                "chipset": {
-                  "type": "string",
-                  "description": ""
-                },
-                "last_heartbeat": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "devices_update"
-      },
-      "patch": {
-        "tags": [
-          "devices"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "type": "object",
-              "properties": {
-                "board_date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_per_heartbeat_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_per_crashreport_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "token": {
-                  "type": "string",
-                  "description": ""
-                },
-                "user": {
-                  "type": "string",
-                  "description": ""
-                },
-                "imei": {
-                  "type": "string",
-                  "description": ""
-                },
-                "chipset": {
-                  "type": "string",
-                  "description": ""
-                },
-                "last_heartbeat": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "devices_partial_update"
-      },
-      "delete": {
-        "tags": [
-          "devices"
-        ],
-        "responses": {
-          "204": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          }
-        ],
-        "operationId": "devices_destroy"
-      }
-    },
-    "/hiccup/api/v1/devices/{uuid}/crashreports/": {
-      "post": {
-        "tags": [
-          "crashreports"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "201": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "required": [
-                "uuid",
-                "date",
-                "app_version",
-                "uptime",
-                "build_fingerprint",
-                "boot_reason",
-                "power_on_reason",
-                "power_off_reason"
-              ],
-              "type": "object",
-              "properties": {
-                "uptime": {
-                  "type": "string",
-                  "description": ""
-                },
-                "is_fake_report": {
-                  "type": "string",
-                  "description": ""
-                },
-                "uuid": {
-                  "type": "string",
-                  "description": ""
-                },
-                "boot_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "power_on_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "build_fingerprint": {
-                  "type": "string",
-                  "description": ""
-                },
-                "power_off_reason": {
-                  "type": "string",
-                  "description": ""
-                },
-                "radio_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "next_logfile_key": {
-                  "type": "string",
-                  "description": ""
-                },
-                "date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "app_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "device_local_id": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "crashreports_create"
-      }
-    },
-    "/hiccup/api/v1/devices/{uuid}/crashreports/{device_local_id}/logfile_put/{filename}/": {
-      "post": {
-        "tags": [
-          "logfile_put"
-        ],
-        "responses": {
-          "201": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "filename",
-            "in": "path"
-          }
-        ],
-        "operationId": "logfile_put_create"
-      }
-    },
-    "/hiccup/api/v1/devices/{uuid}/heartbeats/": {
-      "post": {
-        "tags": [
-          "heartbeats"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "201": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "required": [
-                "uuid",
-                "date",
-                "app_version",
-                "uptime",
-                "build_fingerprint"
-              ],
-              "type": "object",
-              "properties": {
-                "uptime": {
-                  "type": "string",
-                  "description": ""
-                },
-                "uuid": {
-                  "type": "string",
-                  "description": ""
-                },
-                "build_fingerprint": {
-                  "type": "string",
-                  "description": ""
-                },
-                "radio_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "app_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "device_local_id": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "heartbeats_create"
-      }
-    },
-    "/hiccup/api/v1/devices/{uuid}/heartbeats/{device_local_id}/": {
-      "get": {
-        "tags": [
-          "heartbeats"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "limit",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "offset",
-            "in": "query"
-          }
-        ],
-        "operationId": "heartbeats_read"
-      },
-      "put": {
-        "tags": [
-          "heartbeats"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "required": [
-                "uuid",
-                "date",
-                "app_version",
-                "uptime",
-                "build_fingerprint"
-              ],
-              "type": "object",
-              "properties": {
-                "uptime": {
-                  "type": "string",
-                  "description": ""
-                },
-                "uuid": {
-                  "type": "string",
-                  "description": ""
-                },
-                "build_fingerprint": {
-                  "type": "string",
-                  "description": ""
-                },
-                "radio_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "app_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "device_local_id": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "heartbeats_update"
-      },
-      "patch": {
-        "tags": [
-          "heartbeats"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "type": "object",
-              "properties": {
-                "uptime": {
-                  "type": "string",
-                  "description": ""
-                },
-                "uuid": {
-                  "type": "string",
-                  "description": ""
-                },
-                "build_fingerprint": {
-                  "type": "string",
-                  "description": ""
-                },
-                "radio_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "date": {
-                  "type": "string",
-                  "description": ""
-                },
-                "app_version": {
-                  "type": "string",
-                  "description": ""
-                },
-                "device_local_id": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "heartbeats_partial_update"
-      },
-      "delete": {
-        "tags": [
-          "heartbeats"
-        ],
-        "responses": {
-          "204": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "device_local_id",
-            "in": "path"
-          }
-        ],
-        "operationId": "heartbeats_destroy"
-      }
-    },
-    "/hiccup/api/v1/logfiles/{pk}/": {
-      "get": {
-        "tags": [
-          "logfiles"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "pk",
-            "in": "path"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "limit",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "offset",
-            "in": "query"
-          }
-        ],
-        "operationId": "logfiles_read"
-      },
-      "put": {
-        "tags": [
-          "logfiles"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "pk",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "required": [
-                "logfile",
-                "crashreport"
-              ],
-              "type": "object",
-              "properties": {
-                "logfile": {
-                  "type": "string",
-                  "description": ""
-                },
-                "crashreport": {
-                  "type": "string",
-                  "description": ""
-                },
-                "crashreport_local_id": {
-                  "type": "string",
-                  "description": ""
-                },
-                "logfile_type": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "logfiles_update"
-      },
-      "patch": {
-        "tags": [
-          "logfiles"
-        ],
-        "consumes": [
-          "application/json"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "pk",
-            "in": "path"
-          },
-          {
-            "schema": {
-              "type": "object",
-              "properties": {
-                "logfile": {
-                  "type": "string",
-                  "description": ""
-                },
-                "crashreport": {
-                  "type": "string",
-                  "description": ""
-                },
-                "crashreport_local_id": {
-                  "type": "string",
-                  "description": ""
-                },
-                "logfile_type": {
-                  "type": "string",
-                  "description": ""
-                }
-              }
-            },
-            "name": "data",
-            "in": "body"
-          }
-        ],
-        "operationId": "logfiles_partial_update"
-      },
-      "delete": {
-        "tags": [
-          "logfiles"
-        ],
-        "responses": {
-          "204": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "pk",
-            "in": "path"
-          }
-        ],
-        "operationId": "logfiles_destroy"
-      }
-    },
-    "/hiccup/docs/": {
-      "get": {
-        "tags": [
-          "docs"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [],
-        "operationId": "docs_read"
-      }
-    },
-    "/hiccup_stats/api/v1/device_overview/{uuid}/": {
-      "get": {
-        "tags": [
-          "device_overview"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          }
-        ],
-        "operationId": "device_overview_read"
-      }
-    },
-    "/hiccup_stats/api/v1/device_report_history/{uuid}/": {
-      "get": {
-        "tags": [
-          "device_report_history"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          }
-        ],
-        "operationId": "device_report_history_read"
-      }
-    },
-    "/hiccup_stats/api/v1/device_update_history/{uuid}/": {
-      "get": {
-        "tags": [
-          "device_update_history"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "uuid",
-            "in": "path"
-          }
-        ],
-        "operationId": "device_update_history_read"
-      }
-    },
-    "/hiccup_stats/api/v1/logfile_download/{id}/": {
-      "get": {
-        "tags": [
-          "logfile_download"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": true,
-            "type": "string",
-            "name": "id",
-            "in": "path"
-          }
-        ],
-        "operationId": "logfile_download_read"
-      }
-    },
-    "/hiccup_stats/api/v1/status/": {
-      "get": {
-        "tags": [
-          "status"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [],
-        "operationId": "status_read"
-      }
-    },
-    "/hiccup_stats/api/v1/version_daily/": {
-      "get": {
-        "tags": [
-          "version_daily"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "limit",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "offset",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "date",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "heartbeats",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "prob_crashes",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "smpl",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "other",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "version",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "date_start",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "date_end",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "version__build_fingerprint",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "version__is_official_release",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "version__is_beta_release",
-            "in": "query"
-          }
-        ],
-        "operationId": "version_daily_read"
-      }
-    },
-    "/hiccup_stats/api/v1/versions/": {
-      "get": {
-        "tags": [
-          "versions"
-        ],
-        "responses": {
-          "200": {
-            "description": ""
-          }
-        },
-        "parameters": [
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "limit",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "offset",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "is_official_release",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "is_beta_release",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "first_seen_on",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "released_on",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "heartbeats",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "prob_crashes",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "smpl",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "other",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "build_fingerprint",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "first_seen_before",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "first_seen_after",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "released_before",
-            "in": "query"
-          },
-          {
-            "description": "",
-            "required": false,
-            "type": "string",
-            "name": "released_after",
-            "in": "query"
-          }
-        ],
-        "operationId": "versions_read"
-      }
-    }
-  },
-  "securityDefinitions": {
-    "basic": {
-      "type": "basic"
-    }
-  }
-}
diff --git a/documentation/swagger-asciidoc.properties b/documentation/swagger-asciidoc.properties
new file mode 100644
index 0000000..6b54a25
--- /dev/null
+++ b/documentation/swagger-asciidoc.properties
@@ -0,0 +1,2 @@
+import swagger.properties
+swagger2markup.markupLanguage=ASCIIDOC
\ No newline at end of file
diff --git a/hiccup/settings.py b/hiccup/settings.py
index 42b15bb..f20c3c8 100644
--- a/hiccup/settings.py
+++ b/hiccup/settings.py
@@ -54,6 +54,7 @@
     'allauth.account',
     'allauth.socialaccount',
     'allauth.socialaccount.providers.google',
+    'drf_yasg'
 ]
 
 MIDDLEWARE_CLASSES = [
@@ -212,6 +213,14 @@
     },
 }
 
+
+# Automatic documentation generation
+# https://drf-yasg.readthedocs.io/en/stable/index.html
+
+SWAGGER_SETTINGS = {
+   'DEFAULT_INFO': 'hiccup.urls.api_info',
+}
+
 try:
     from local_settings import *  # noqa: F403, F401
 except ImportError as e:
diff --git a/hiccup/urls.py b/hiccup/urls.py
index f3e9c83..3a6cf76 100644
--- a/hiccup/urls.py
+++ b/hiccup/urls.py
@@ -1,7 +1,13 @@
+"""Define all Hiccup REST API URLs."""
+
 from django.conf.urls import include, url
 from django.contrib import admin
-from django.views.generic.base import RedirectView
-from django.contrib.auth import views as auth_views
+from drf_yasg import openapi
+
+api_info = openapi.Info(
+    title="Hiccup API",
+    default_version='v1',
+)
 
 urlpatterns = [
     url(r'^hiccup/admin/', admin.site.urls),
diff --git a/requirements.txt b/requirements.txt
index fb9d75c..82fe059 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -19,6 +19,7 @@
 django-taggit==0.22.2
 django-user-accounts==2.0.3
 djangorestframework==3.8.2
+drf-yasg==1.10.0
 entrypoints==0.2.2
 enum34==1.1.6
 idna==2.6
diff --git a/tox.ini b/tox.ini
index c0f3881..1441f97 100644
--- a/tox.ini
+++ b/tox.ini
@@ -41,3 +41,39 @@
 [flake8]
 format = ${cyan}%(path)s${reset}:${yellow_bold}%(row)d${reset}:${green_bold}%(col)d${reset}: ${red_bold}%(code)s${reset} %(text)s
 max-complexity = 10
+
+# Documentation
+# Shared commands for both docs options
+[docs]
+swagger_version = 1.3.3
+commands =
+    python manage.py generate_swagger --overwrite documentation/hiccup-api.json
+    wget -nc https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup-cli/{[docs]swagger_version}/swagger2markup-cli-{[docs]swagger_version}.jar
+whitelist_externals=
+    java
+    wget
+
+# Create markdown docs
+[testenv:docs]
+deps = {[testenv]deps}
+commands =
+    {[docs]commands}
+    java -jar swagger2markup-cli-{[docs]swagger_version}.jar convert \
+        -f documentation/api-endpoints \
+        -i documentation/hiccup-api.json \
+        -c documentation/swagger.properties
+whitelist_externals = {[docs]whitelist_externals}
+
+# Create HTML docs
+[testenv:docs-html]
+deps = {[testenv]deps}
+commands =
+    {[docs]commands}
+    java -jar swagger2markup-cli-{[docs]swagger_version}.jar convert \
+        -f documentation/api-endpoints \
+        -i documentation/hiccup-api.json \
+        -c documentation/swagger-asciidoc.properties
+    asciidoctor documentation/api-endpoints.adoc
+whitelist_externals =
+    {[docs]whitelist_externals}
+    asciidoctor
\ No newline at end of file