diff --git a/api/docs/api.html b/api/docs/api.html
index b5e364eba2053726883f23a0adb0ddd9e46f3ccf..d0c9acac54f8bc2138eb5f97b3f9866bcba09e7f 100644
--- a/api/docs/api.html
+++ b/api/docs/api.html
@@ -35,7 +35,7 @@
 <script>
 window.onload = function() {
 
-  var spec = {"openapi": "3.0.0", "servers": [{"description": "Roadmaps API Server", "url": "https://roadmaps.thecodelabs.de:10000/"}], "info": {"description": "The Official Roadmaps API", "version": "1.0.0", "title": "Roadmaps API"}, "tags": [{"name": "admins", "description": "Secured Admin-only calls"}, {"name": "public", "description": "Operations available to the public"}], "paths": {"/roadmaps": {"get": {"tags": ["public"], "summary": "Gets all roadmaps", "operationId": "roadmaps", "responses": {"200": {"description": "All available roadmaps", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Roadmap"}}}}}}}}, "/roadmap/{roadmapID}": {"get": {"tags": ["public"], "summary": "Gets  a specific roadmap", "operationId": "roadmap", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "The roadmap", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Roadmap"}}}}}}}, "/roadmap/{roadmapID}/full": {"get": {"tags": ["public"], "summary": "Gets  a specific roadmap with all milestones, tasks and sub tasks", "operationId": "roadmapFull", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "The roadmap", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RoadmapFull"}}}}}}}, "/milestones/{roadmapID}": {"get": {"tags": ["public"], "summary": "Gets all milestones for a roadmap", "operationId": "milestones", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All milestones for the given roadmap ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Milestone"}}}}}}}}, "/milestones/{roadmapID}/open": {"get": {"tags": ["public"], "summary": "Gets all open milestones for a roadmap", "operationId": "openMilestones", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All open milestones for the given roadmap ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Milestone"}}}}}}}}, "/milestones/{roadmapID}/latest": {"get": {"tags": ["public"], "summary": "Gets the lastest finished milestone for a roadmap", "operationId": "latestMilestone", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "The latest finished milestone for the given roadmap ID", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Milestone"}}}}}}}, "/milestone/{milestoneID}": {"get": {"tags": ["public"], "summary": "Gets  a specific milestone", "operationId": "milestone", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "The milestone", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Milestone"}}}}}}}, "/tasks/{milestoneID}": {"get": {"tags": ["public"], "summary": "Gets all tasks for a milestone", "operationId": "tasks", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All tasks for the given milestone ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}}, "/tasks/{milestoneID}/open": {"get": {"tags": ["public"], "summary": "Gets all open tasks for a milestone", "operationId": "openTasks", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All open tasks for the given milestone ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}}, "/task/{taskID}": {"get": {"tags": ["public"], "summary": "Gets  a specific task", "operationId": "task", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "The task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}}}}, "/subtasks/{taskID}": {"get": {"tags": ["public"], "summary": "Gets all sub taks for a task", "operationId": "substasks", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All sub tasks for the given task ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/SubTask"}}}}}}}}, "/subtasks/{taskID}/open": {"get": {"tags": ["public"], "summary": "Gets all open sub taks for a task", "operationId": "openSubtasks", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All open sub tasks for the given task ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/SubTask"}}}}}}}}, "/subtask/{subtaskID}": {"get": {"tags": ["public"], "summary": "Gets  a specific sub task", "operationId": "subtask", "parameters": [{"in": "path", "name": "subtaskID", "description": "The sub task ID", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "The sub task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SubTask"}}}}}}}}, "components": {"schemas": {"Roadmap": {"type": "object", "required": ["ID", "Projectname"], "properties": {"id": {"type": "integer", "example": 1}, "name": {"type": "string", "example": "Example Roadmap"}}}, "RoadmapFull": {"allOf": [{"$ref": "#/components/schemas/Roadmap"}, {"type": "object", "properties": {"milestones": {"type": "array", "items": {"allOf": [{"$ref": "#/components/schemas/Milestone"}, {"type": "object", "properties": {"tasks": {"type": "array", "items": {"allOf": [{"$ref": "#/components/schemas/Task"}, {"type": "object", "properties": {"subtasks": {"type": "array", "items": {"$ref": "#/components/schemas/SubTask"}}}}]}}}}]}}}}]}, "Milestone": {"type": "object", "required": ["ID", "RoadmapID", "VersionCode", "VersionName", "Title", "DueDate", "CompletionDate", "Status"], "properties": {"ID": {"type": "integer", "example": 1}, "RoadmapID": {"type": "integer", "example": 2}, "VersionCode": {"type": "integer", "example": 3}, "VersionName": {"type": "string", "example": "v1.0.0"}, "Title": {"type": "string", "example": "My awesome milestone"}, "DueDate": {"type": "string", "format": "date", "example": "2019-05-30"}, "CompletionDate": {"type": "string", "format": "date", "example": "2019-05-30"}, "Status": {"type": "integer", "enum": [0, 1]}}}, "Task": {"type": "object", "required": ["ID", "MilestoneID", "Title", "Description", "Status"], "properties": {"ID": {"type": "integer", "example": 1}, "MilestoneID": {"type": "integer", "example": 2}, "Title": {"type": "string", "example": "My awesome task"}, "Description": {"type": "string", "example": "Lorem Ipsum dolor sit amet"}, "Status": {"type": "integer", "enum": [0, 1]}}}, "SubTask": {"type": "object", "required": ["ID", "TaskID", "Title", "Description", "Status"], "properties": {"ID": {"type": "integer", "example": 1}, "TaskID": {"type": "integer", "example": 2}, "Title": {"type": "string", "example": "My awesome sub task"}, "Description": {"type": "string", "example": "Lorem Ipsum dolor sit amet"}, "Status": {"type": "integer", "enum": [0, 1]}}}}}};
+  var spec = {"openapi": "3.0.0", "servers": [{"description": "Roadmaps API Server", "url": "https://roadmaps.thecodelabs.de:10000/"}], "info": {"description": "The Official Roadmaps API", "version": "1.0.0", "title": "Roadmaps API"}, "tags": [{"name": "admins", "description": "Secured Admin-only calls"}, {"name": "public", "description": "Operations available to the public"}], "paths": {"/login": {"post": {"tags": ["public"], "summary": "Gets a bearer JSON Web Token", "operationId": "login", "requestBody": {"description": "Credentials", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Credentials"}}}}, "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TokenResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/roadmaps": {"get": {"tags": ["public"], "summary": "Gets all roadmaps", "operationId": "roadmaps", "responses": {"200": {"description": "All available roadmaps", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Roadmap"}}}}}}}}, "/roadmap/{roadmapID}": {"get": {"tags": ["public"], "summary": "Gets  a specific roadmap", "operationId": "roadmap", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "The roadmap", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Roadmap"}}}}}}, "delete": {"tags": ["admins"], "description": "Deletes a roadmap based on the given ID", "operationId": "deleteRoadmap", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/roadmap": {"post": {"tags": ["admins"], "summary": "Adds a new roadmap", "operationId": "addRoadmap", "requestBody": {"description": "Roadmap to add", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NewRoadmap"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}, "put": {"tags": ["admins"], "summary": "Updates a roadmap", "operationId": "updateRoadmap", "requestBody": {"description": "Roadmap to update", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Roadmap"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/roadmap/{roadmapID}/full": {"get": {"tags": ["public"], "summary": "Gets  a specific roadmap with all milestones, tasks and sub tasks", "operationId": "roadmapFull", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "The roadmap", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RoadmapFull"}}}}}}}, "/milestones/{roadmapID}": {"get": {"tags": ["public"], "summary": "Gets all milestones for a roadmap", "operationId": "milestones", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All milestones for the given roadmap ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Milestone"}}}}}}}}, "/milestones/{roadmapID}/open": {"get": {"tags": ["public"], "summary": "Gets all open milestones for a roadmap", "operationId": "openMilestones", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All open milestones for the given roadmap ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Milestone"}}}}}}}}, "/milestones/{roadmapID}/latest": {"get": {"tags": ["public"], "summary": "Gets the lastest finished milestone for a roadmap", "operationId": "latestMilestone", "parameters": [{"in": "path", "name": "roadmapID", "description": "The roadmap ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "The latest finished milestone for the given roadmap ID", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Milestone"}}}}}}}, "/milestone/{milestoneID}": {"get": {"tags": ["public"], "summary": "Gets  a specific milestone", "operationId": "milestone", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "The milestone", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Milestone"}}}}}}, "delete": {"tags": ["admins"], "description": "Deletes a milestone based on the given ID", "operationId": "deleteMilestone", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "integer"}}], "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/milestone": {"post": {"tags": ["admins"], "summary": "Adds a new milestone", "operationId": "addMilestone", "requestBody": {"description": "Milestone to add", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NewMilestone"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}, "put": {"tags": ["admins"], "summary": "Updates a milestone", "operationId": "updateMilestone", "requestBody": {"description": "Milestone to update", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Milestone"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/tasks/{milestoneID}": {"get": {"tags": ["public"], "summary": "Gets all tasks for a milestone", "operationId": "tasks", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All tasks for the given milestone ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}}, "/tasks/{milestoneID}/open": {"get": {"tags": ["public"], "summary": "Gets all open tasks for a milestone", "operationId": "openTasks", "parameters": [{"in": "path", "name": "milestoneID", "description": "The milestone ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All open tasks for the given milestone ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/Task"}}}}}}}}, "/task/{taskID}": {"get": {"tags": ["public"], "summary": "Gets  a specific task", "operationId": "task", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "The task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}}}, "delete": {"tags": ["admins"], "description": "Deletes a task based on the given ID", "operationId": "deleteTask", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "integer"}}], "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/task": {"post": {"tags": ["admins"], "summary": "Adds a new task", "operationId": "addTask", "requestBody": {"description": "Task to add", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NewTask"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}, "put": {"tags": ["admins"], "summary": "Updates a task", "operationId": "updateTask", "requestBody": {"description": "Task to update", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Task"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/subtasks/{taskID}": {"get": {"tags": ["public"], "summary": "Gets all sub taks for a task", "operationId": "substasks", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All sub tasks for the given task ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/SubTask"}}}}}}}}, "/subtasks/{taskID}/open": {"get": {"tags": ["public"], "summary": "Gets all open sub taks for a task", "operationId": "openSubtasks", "parameters": [{"in": "path", "name": "taskID", "description": "The task ID", "required": true, "schema": {"type": "integer"}}], "responses": {"200": {"description": "All open sub tasks for the given task ID", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/SubTask"}}}}}}}}, "/subtask/{subtaskID}": {"get": {"tags": ["public"], "summary": "Gets  a specific sub task", "operationId": "subtask", "parameters": [{"in": "path", "name": "subtaskID", "description": "The sub task ID", "required": true, "schema": {"type": "string"}}], "responses": {"200": {"description": "The sub task", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SubTask"}}}}}}, "delete": {"tags": ["admins"], "description": "Deletes a sub task based on the given ID", "operationId": "deleteSubTask", "parameters": [{"in": "path", "name": "subtaskID", "description": "The sub task ID", "required": true, "schema": {"type": "integer"}}], "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/subtask": {"post": {"tags": ["admins"], "summary": "Adds a new sub task", "operationId": "addSubTask", "requestBody": {"description": "Sub task to add", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NewSubTask"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}, "put": {"tags": ["admins"], "summary": "Updates a sub task", "operationId": "updateSubTask", "requestBody": {"description": "Sub task to update", "required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SubTask"}}}}, "security": [{"BearerAuth": []}], "responses": {"200": {"description": "success response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "401": {"description": "unauthorized response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnauthorizedResponse"}}}}, "default": {"description": "error response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}}, "components": {"securitySchemes": {"BearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "JWT"}}, "schemas": {"Credentials": {"type": "object", "required": ["username", "password"], "properties": {"username": {"type": "string", "example": "admin"}, "password": {"type": "string", "example": "123"}}}, "Roadmap": {"type": "object", "required": ["ID", "Projectname"], "properties": {"ID": {"type": "integer", "example": 1}, "Projectname": {"type": "string", "example": "Example Roadmap"}}}, "RoadmapFull": {"allOf": [{"$ref": "#/components/schemas/Roadmap"}, {"type": "object", "properties": {"milestones": {"type": "array", "items": {"allOf": [{"$ref": "#/components/schemas/Milestone"}, {"type": "object", "properties": {"tasks": {"type": "array", "items": {"allOf": [{"$ref": "#/components/schemas/Task"}, {"type": "object", "properties": {"subtasks": {"type": "array", "items": {"$ref": "#/components/schemas/SubTask"}}}}]}}}}]}}}}]}, "NewRoadmap": {"type": "object", "required": ["Projectname"], "properties": {"Projectname": {"type": "string", "example": "Example Roadmap"}}}, "Milestone": {"type": "object", "required": ["ID", "RoadmapID", "VersionCode", "VersionName", "Title", "DueDate", "CompletionDate", "Status"], "properties": {"ID": {"type": "integer", "example": 1}, "RoadmapID": {"type": "integer", "example": 2}, "VersionCode": {"type": "integer", "example": 3}, "VersionName": {"type": "string", "example": "v1.0.0"}, "Title": {"type": "string", "example": "My awesome milestone"}, "DueDate": {"type": "string", "format": "date", "example": "2019-05-30"}, "CompletionDate": {"type": "string", "format": "date", "example": "2019-05-30"}, "Status": {"type": "integer", "enum": [0, 1]}}}, "NewMilestone": {"type": "object", "required": ["RoadmapID", "VersionCode", "VersionName", "Title", "DueDate", "CompletionDate"], "properties": {"RoadmapID": {"type": "integer", "example": 2}, "VersionCode": {"type": "integer", "example": 3}, "VersionName": {"type": "string", "example": "v1.0.0"}, "Title": {"type": "string", "example": "My awesome milestone"}, "DueDate": {"type": "string", "format": "date", "example": "2019-05-30"}, "CompletionDate": {"type": "string", "format": "date", "example": "2019-05-30"}}}, "Task": {"type": "object", "required": ["ID", "MilestoneID", "Title", "Description", "Status"], "properties": {"ID": {"type": "integer", "example": 1}, "MilestoneID": {"type": "integer", "example": 2}, "Title": {"type": "string", "example": "My awesome task"}, "Description": {"type": "string", "example": "Lorem Ipsum dolor sit amet"}, "Status": {"type": "integer", "enum": [0, 1]}}}, "NewTask": {"type": "object", "required": ["MilestoneID", "Title", "Description"], "properties": {"MilestoneID": {"type": "integer", "example": 2}, "Title": {"type": "string", "example": "My awesome task"}, "Description": {"type": "string", "example": "Lorem Ipsum dolor sit amet"}}}, "SubTask": {"type": "object", "required": ["ID", "TaskID", "Title", "Description", "Status"], "properties": {"ID": {"type": "integer", "example": 1}, "TaskID": {"type": "integer", "example": 2}, "Title": {"type": "string", "example": "My awesome sub task"}, "Description": {"type": "string", "example": "Lorem Ipsum dolor sit amet"}, "Status": {"type": "integer", "enum": [0, 1]}}}, "NewSubTask": {"type": "object", "required": ["TaskID", "Title", "Description"], "properties": {"TaskID": {"type": "integer", "example": 2}, "Title": {"type": "string", "example": "My awesome sub task"}, "Description": {"type": "string", "example": "Lorem Ipsum dolor sit amet"}}}, "UnauthorizedResponse": {"description": "Access token is missing or invalid", "properties": {"msg": {"type": "string", "example": "Missing Authorization Header"}}}, "TokenResponse": {"description": "JSON web token", "properties": {"access_token": {"type": "string"}}}, "SuccessResponse": {"required": ["success"], "properties": {"success": {"type": "boolean"}}}, "ErrorResponse": {"required": ["success", "msg"], "properties": {"success": {"type": "boolean"}, "msg": {"type": "string"}}}}}};
 
   // Build a system
   const ui = SwaggerUIBundle({
diff --git a/api/docs/api.yml b/api/docs/api.yml
index a8fab3c9b4df62b81af7b7f74543fb75bd66fb43..cb5441cf8a8c2fb3dcffa8bae5d9e448f6e67527 100644
--- a/api/docs/api.yml
+++ b/api/docs/api.yml
@@ -11,7 +11,41 @@ tags:
     description: Secured Admin-only calls
   - name: public
     description: Operations available to the public
+
 paths:
+  /login:
+    post:
+      tags:
+        - public
+      summary: Gets a bearer JSON Web Token
+      operationId: login
+      requestBody:
+        description: Credentials
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Credentials'
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/TokenResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+
   /roadmaps:
     get:
       tags:
@@ -47,6 +81,106 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Roadmap'
+    delete:
+      tags:
+        - admins
+      description: Deletes a roadmap based on the given ID
+      operationId: deleteRoadmap
+      parameters:
+        - in: path
+          name: roadmapID
+          description: The roadmap ID
+          required: true
+          schema:
+            type: integer
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /roadmap:
+    post:
+      tags:
+        - admins
+      summary: Adds a new roadmap
+      operationId: addRoadmap
+      requestBody:
+        description: Roadmap to add
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/NewRoadmap'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+    put:
+      tags:
+        - admins
+      summary: Updates a roadmap
+      operationId: updateRoadmap
+      requestBody:
+        description: Roadmap to update
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Roadmap'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
   /roadmap/{roadmapID}/full:
     get:
       tags:
@@ -152,6 +286,106 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Milestone'
+    delete:
+      tags:
+        - admins
+      description: Deletes a milestone based on the given ID
+      operationId: deleteMilestone
+      parameters:
+        - in: path
+          name: milestoneID
+          description: The milestone ID
+          required: true
+          schema:
+            type: integer
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /milestone:
+    post:
+      tags:
+        - admins
+      summary: Adds a new milestone
+      operationId: addMilestone
+      requestBody:
+        description: Milestone to add
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/NewMilestone'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+    put:
+      tags:
+        - admins
+      summary: Updates a milestone
+      operationId: updateMilestone
+      requestBody:
+        description: Milestone to update
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Milestone'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
 
   /tasks/{milestoneID}:
     get:
@@ -217,6 +451,106 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Task'
+    delete:
+      tags:
+        - admins
+      description: Deletes a task based on the given ID
+      operationId: deleteTask
+      parameters:
+        - in: path
+          name: taskID
+          description: The task ID
+          required: true
+          schema:
+            type: integer
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /task:
+    post:
+      tags:
+        - admins
+      summary: Adds a new task
+      operationId: addTask
+      requestBody:
+        description: Task to add
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/NewTask'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+    put:
+      tags:
+        - admins
+      summary: Updates a task
+      operationId: updateTask
+      requestBody:
+        description: Task to update
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/Task'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
 
   /subtasks/{taskID}:
     get:
@@ -282,18 +616,138 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/SubTask'
+    delete:
+      tags:
+        - admins
+      description: Deletes a sub task based on the given ID
+      operationId: deleteSubTask
+      parameters:
+        - in: path
+          name: subtaskID
+          description: The sub task ID
+          required: true
+          schema:
+            type: integer
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+  /subtask:
+    post:
+      tags:
+        - admins
+      summary: Adds a new sub task
+      operationId: addSubTask
+      requestBody:
+        description: Sub task to add
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/NewSubTask'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+    put:
+      tags:
+        - admins
+      summary: Updates a sub task
+      operationId: updateSubTask
+      requestBody:
+        description: Sub task to update
+        required: true
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/SubTask'
+      security:
+        - BearerAuth: []
+      responses:
+        '200':
+          description: success response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/SuccessResponse'
+        '401':
+          description: unauthorized response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/UnauthorizedResponse'
+        default:
+          description: error response
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ErrorResponse'
+
 components:
+  securitySchemes:
+    BearerAuth:
+      type: http
+      scheme: bearer
+      bearerFormat: JWT
+
   schemas:
+    Credentials:
+      type: object
+      required:
+        - username
+        - password
+      properties:
+        username:
+          type: string
+          example: "admin"
+        password:
+          type: string
+          example: "123"
+
     Roadmap:
       type: object
       required:
         - ID
         - Projectname
       properties:
-        id:
+        ID:
           type: integer
           example: 1
-        name:
+        Projectname:
           type: string
           example: "Example Roadmap"
 
@@ -321,6 +775,15 @@ components:
                                   items:
                                     $ref: '#/components/schemas/SubTask'
 
+    NewRoadmap:
+      type: object
+      required:
+        - Projectname
+      properties:
+        Projectname:
+          type: string
+          example: "Example Roadmap"
+
     Milestone:
       type: object
       required:
@@ -361,6 +824,38 @@ components:
           enum:
             - 0
             - 1
+
+    NewMilestone:
+      type: object
+      required:
+        - RoadmapID
+        - VersionCode
+        - VersionName
+        - Title
+        - DueDate
+        - CompletionDate
+      properties:
+        RoadmapID:
+          type: integer
+          example: 2
+        VersionCode:
+          type: integer
+          example: 3
+        VersionName:
+          type: string
+          example: "v1.0.0"
+        Title:
+          type: string
+          example: "My awesome milestone"
+        DueDate:
+          type: string
+          format: date
+          example: "2019-05-30"
+        CompletionDate:
+          type: string
+          format: date
+          example: "2019-05-30"
+
     Task:
       type: object
       required:
@@ -387,6 +882,24 @@ components:
           enum:
             - 0
             - 1
+
+    NewTask:
+      type: object
+      required:
+        - MilestoneID
+        - Title
+        - Description
+      properties:
+        MilestoneID:
+          type: integer
+          example: 2
+        Title:
+          type: string
+          example: "My awesome task"
+        Description:
+          type: string
+          example: "Lorem Ipsum dolor sit amet"
+
     SubTask:
       type: object
       required:
@@ -412,4 +925,48 @@ components:
           type: integer
           enum:
             - 0
-            - 1
\ No newline at end of file
+            - 1
+
+    NewSubTask:
+      type: object
+      required:
+        - TaskID
+        - Title
+        - Description
+      properties:
+        TaskID:
+          type: integer
+          example: 2
+        Title:
+          type: string
+          example: "My awesome sub task"
+        Description:
+          type: string
+          example: "Lorem Ipsum dolor sit amet"
+
+    UnauthorizedResponse:
+      description: Access token is missing or invalid
+      properties:
+        msg:
+          type: string
+          example: "Missing Authorization Header"
+    TokenResponse:
+      description: JSON web token
+      properties:
+        access_token:
+          type: string
+    SuccessResponse:
+      required:
+        - success
+      properties:
+        success:
+          type: boolean
+    ErrorResponse:
+      required:
+        - success
+        - msg
+      properties:
+        success:
+          type: boolean
+        msg:
+          type: string
\ No newline at end of file