diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php
index b63406696..41decd23d 100644
--- a/app/Api/ApiDocsGenerator.php
+++ b/app/Api/ApiDocsGenerator.php
@@ -106,7 +106,7 @@ class ApiDocsGenerator
             return strpos($route->uri, 'api/') === 0;
         })->map(function ($route) {
             [$controller, $controllerMethod] = explode('@', $route->action['uses']);
-            $baseModelName = explode('/', $route->uri)[1];
+            $baseModelName = explode('.', explode('/', $route->uri)[1])[0];
             $shortName = $baseModelName . '-' . $controllerMethod;
             return [
                 'name' => $shortName,
diff --git a/app/Http/Controllers/Api/ApiDocsController.php b/app/Http/Controllers/Api/ApiDocsController.php
index bfb0c1834..84ddd5215 100644
--- a/app/Http/Controllers/Api/ApiDocsController.php
+++ b/app/Http/Controllers/Api/ApiDocsController.php
@@ -13,9 +13,9 @@ class ApiDocsController extends ApiController
     public function display()
     {
         $docs = $this->getDocs();
-        dd($docs);
-        // TODO - Build view for API docs
-        return view('');
+        return view('api-docs.index', [
+            'docs' => $docs,
+        ]);
     }
 
     /**
diff --git a/app/Http/Controllers/Api/BooksApiController.php b/app/Http/Controllers/Api/BooksApiController.php
index 8c62b7d7d..fa174dfd3 100644
--- a/app/Http/Controllers/Api/BooksApiController.php
+++ b/app/Http/Controllers/Api/BooksApiController.php
@@ -2,8 +2,11 @@
 
 use BookStack\Entities\Book;
 use BookStack\Entities\Repos\BookRepo;
+use BookStack\Exceptions\NotifyException;
 use BookStack\Facades\Activity;
+use Illuminate\Contracts\Container\BindingResolutionException;
 use Illuminate\Http\Request;
+use Illuminate\Validation\ValidationException;
 
 class BooksApiController extends ApiController
 {
@@ -41,8 +44,8 @@ class BooksApiController extends ApiController
     }
 
     /**
-     * Create a new book.
-     * @throws \Illuminate\Validation\ValidationException
+     * Create a new book in the system.
+     * @throws ValidationException
      */
     public function create(Request $request)
     {
@@ -66,7 +69,7 @@ class BooksApiController extends ApiController
 
     /**
      * Update the details of a single book.
-     * @throws \Illuminate\Validation\ValidationException
+     * @throws ValidationException
      */
     public function update(Request $request, string $id)
     {
@@ -81,9 +84,9 @@ class BooksApiController extends ApiController
     }
 
     /**
-     * Delete a book from the system.
-     * @throws \BookStack\Exceptions\NotifyException
-     * @throws \Illuminate\Contracts\Container\BindingResolutionException
+     * Delete a single book from the system.
+     * @throws NotifyException
+     * @throws BindingResolutionException
      */
     public function delete(string $id)
     {
diff --git a/resources/js/components/details-highlighter.js b/resources/js/components/details-highlighter.js
new file mode 100644
index 000000000..18c5165fa
--- /dev/null
+++ b/resources/js/components/details-highlighter.js
@@ -0,0 +1,18 @@
+import Code from "../services/code"
+class DetailsHighlighter {
+
+    constructor(elem) {
+        this.elem = elem;
+        this.dealtWith = false;
+        elem.addEventListener('toggle', this.onToggle.bind(this));
+    }
+
+    onToggle() {
+        if (this.dealtWith) return;
+
+        Code.highlightWithin(this.elem);
+        this.dealtWith = true;
+    }
+}
+
+export default DetailsHighlighter;
\ No newline at end of file
diff --git a/resources/js/components/index.js b/resources/js/components/index.js
index bbe059898..d3ba539dd 100644
--- a/resources/js/components/index.js
+++ b/resources/js/components/index.js
@@ -30,6 +30,7 @@ import settingColorPicker from "./setting-color-picker";
 import entityPermissionsEditor from "./entity-permissions-editor";
 import templateManager from "./template-manager";
 import newUserPassword from "./new-user-password";
+import detailsHighlighter from "./details-highlighter";
 
 const componentMapping = {
     'dropdown': dropdown,
@@ -64,6 +65,7 @@ const componentMapping = {
     'entity-permissions-editor': entityPermissionsEditor,
     'template-manager': templateManager,
     'new-user-password': newUserPassword,
+    'details-highlighter': detailsHighlighter,
 };
 
 window.components = {};
diff --git a/resources/js/services/code.js b/resources/js/services/code.js
index 26dee5bfb..834a547e3 100644
--- a/resources/js/services/code.js
+++ b/resources/js/services/code.js
@@ -87,9 +87,20 @@ const modeMap = {
  * Highlight pre elements on a page
  */
 function highlight() {
-    let codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
-    for (let i = 0; i < codeBlocks.length; i++) {
-        highlightElem(codeBlocks[i]);
+    const codeBlocks = document.querySelectorAll('.page-content pre, .comment-box .content pre');
+    for (const codeBlock of codeBlocks) {
+        highlightElem(codeBlock);
+    }
+}
+
+/**
+ * Highlight all code blocks within the given parent element
+ * @param {HTMLElement} parent
+ */
+function highlightWithin(parent) {
+    const codeBlocks = parent.querySelectorAll('pre');
+    for (const codeBlock of codeBlocks) {
+        highlightElem(codeBlock);
     }
 }
 
@@ -308,6 +319,7 @@ function getMetaKey() {
 
 export default {
     highlight: highlight,
+    highlightWithin: highlightWithin,
     wysiwygView: wysiwygView,
     popupEditor: popupEditor,
     setMode: setMode,
diff --git a/resources/sass/_blocks.scss b/resources/sass/_blocks.scss
index 2cb17a18d..cc42dc736 100644
--- a/resources/sass/_blocks.scss
+++ b/resources/sass/_blocks.scss
@@ -236,4 +236,26 @@
 
 .tag-list div:last-child .tag-item {
   margin-bottom: 0;
+}
+
+/**
+ * API Docs
+ */
+.api-method {
+  font-size: 0.75rem;
+  background-color: #888;
+  padding: $-xs;
+  line-height: 1.3;
+  opacity: 0.7;
+  vertical-align: top;
+  border-radius: 3px;
+  color: #FFF;
+  display: inline-block;
+  min-width: 60px;
+  text-align: center;
+  font-weight: bold;
+  &[data-method="GET"] { background-color: #077b70 }
+  &[data-method="POST"] { background-color: #cf4d03 }
+  &[data-method="PUT"] { background-color: #0288D1 }
+  &[data-method="DELETE"] { background-color: #ab0f0e }
 }
\ No newline at end of file
diff --git a/resources/sass/_text.scss b/resources/sass/_text.scss
index cf78c162b..77e0773eb 100644
--- a/resources/sass/_text.scss
+++ b/resources/sass/_text.scss
@@ -213,6 +213,18 @@ blockquote {
   }
 }
 
+.text-mono {
+  font-family: $mono;
+}
+
+.text-uppercase {
+  text-transform: uppercase;
+}
+
+.text-capitals {
+  text-transform: capitalize;
+}
+
 .code-base {
     background-color: #F8F8F8;
     font-size: 0.80em;
diff --git a/resources/views/api-docs/index.blade.php b/resources/views/api-docs/index.blade.php
new file mode 100644
index 000000000..181bcd746
--- /dev/null
+++ b/resources/views/api-docs/index.blade.php
@@ -0,0 +1,51 @@
+@extends('simple-layout')
+
+@section('body')
+
+    <div class="container pt-xl">
+
+        <div class="grid right-focus reverse-collapse">
+
+            <div>
+                @foreach($docs as $model => $endpoints)
+                    <p class="text-uppercase text-muted mb-xm mt-l"><strong>{{ $model }}</strong></p>
+
+                    @foreach($endpoints as $endpoint)
+                        <div class="mb-xs">
+                            <a href="#{{ $endpoint['name'] }}" class="text-mono">
+                                <span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
+                                /{{ $endpoint['uri'] }}
+                            </a>
+                        </div>
+                    @endforeach
+                @endforeach
+            </div>
+
+            <div>
+                @foreach($docs as $model => $endpoints)
+                    <section class="card content-wrap auto-height">
+                        <h1 class="list-heading text-capitals">{{ $model }}</h1>
+
+                        @foreach($endpoints as $endpoint)
+                            <h5 id="{{ $endpoint['name'] }}" class="text-mono mb-m">
+                                <span class="api-method" data-method="{{ $endpoint['method'] }}">{{ $endpoint['method'] }}</span>
+                                {{ url($endpoint['uri']) }}
+                            </h5>
+                            <p class="mb-m">{{ $endpoint['description'] ?? '' }}</p>
+                            @if($endpoint['example_response'] ?? false)
+                                <details details-highlighter>
+                                    <summary class="text-muted">Example Response</summary>
+                                    <pre><code class="language-json">{{ $endpoint['example_response'] }}</code></pre>
+                                </details>
+                                <hr class="mt-m">
+                            @endif
+                        @endforeach
+                    </section>
+                @endforeach
+            </div>
+
+        </div>
+
+
+    </div>
+@stop
\ No newline at end of file