diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index f2672cf57..36bdf845d 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -9,7 +9,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Validation\ValidationException;
-use Symfony\Component\HttpKernel\Exception\HttpException;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
 use Throwable;
 
 class Handler extends ExceptionHandler
@@ -82,7 +82,7 @@ class Handler extends ExceptionHandler
         $code = 500;
         $headers = [];
 
-        if ($e instanceof HttpException) {
+        if ($e instanceof HttpExceptionInterface) {
             $code = $e->getStatusCode();
             $headers = $e->getHeaders();
         }
@@ -103,10 +103,6 @@ class Handler extends ExceptionHandler
             $code = $e->status;
         }
 
-        if (method_exists($e, 'getStatus')) {
-            $code = $e->getStatus();
-        }
-
         $responseData['error']['code'] = $code;
 
         return new JsonResponse($responseData, $code, $headers);
diff --git a/app/Exceptions/NotifyException.php b/app/Exceptions/NotifyException.php
index 307916db7..b62b8fde6 100644
--- a/app/Exceptions/NotifyException.php
+++ b/app/Exceptions/NotifyException.php
@@ -4,29 +4,39 @@ namespace BookStack\Exceptions;
 
 use Exception;
 use Illuminate\Contracts\Support\Responsable;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
 
-class NotifyException extends Exception implements Responsable
+class NotifyException extends Exception implements Responsable, HttpExceptionInterface
 {
     public $message;
-    public $redirectLocation;
-    protected $status;
+    public string $redirectLocation;
+    protected int $status;
 
     public function __construct(string $message, string $redirectLocation = '/', int $status = 500)
     {
         $this->message = $message;
         $this->redirectLocation = $redirectLocation;
         $this->status = $status;
+
         parent::__construct();
     }
 
     /**
-     * Get the desired status code for this exception.
+     * Get the desired HTTP status code for this exception.
      */
-    public function getStatus(): int
+    public function getStatusCode(): int
     {
         return $this->status;
     }
 
+    /**
+     * Get the desired HTTP headers for this exception.
+     */
+    public function getHeaders(): array
+    {
+        return [];
+    }
+
     /**
      * Send the response for this type of exception.
      *
@@ -38,7 +48,7 @@ class NotifyException extends Exception implements Responsable
 
         // Front-end JSON handling. API-side handling managed via handler.
         if ($request->wantsJson()) {
-            return response()->json(['error' => $message], 403);
+            return response()->json(['error' => $message], $this->getStatusCode());
         }
 
         if (!empty($message)) {
diff --git a/app/Exceptions/PrettyException.php b/app/Exceptions/PrettyException.php
index f446442d0..606085231 100644
--- a/app/Exceptions/PrettyException.php
+++ b/app/Exceptions/PrettyException.php
@@ -4,18 +4,12 @@ namespace BookStack\Exceptions;
 
 use Exception;
 use Illuminate\Contracts\Support\Responsable;
+use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
 
-class PrettyException extends Exception implements Responsable
+class PrettyException extends Exception implements Responsable, HttpExceptionInterface
 {
-    /**
-     * @var ?string
-     */
-    protected $subtitle = null;
-
-    /**
-     * @var ?string
-     */
-    protected $details = null;
+    protected ?string $subtitle = null;
+    protected ?string $details = null;
 
     /**
      * Render a response for when this exception occurs.
@@ -24,7 +18,7 @@ class PrettyException extends Exception implements Responsable
      */
     public function toResponse($request)
     {
-        $code = ($this->getCode() === 0) ? 500 : $this->getCode();
+        $code = $this->getStatusCode();
 
         return response()->view('errors.' . $code, [
             'message'  => $this->getMessage(),
@@ -46,4 +40,20 @@ class PrettyException extends Exception implements Responsable
 
         return $this;
     }
+
+    /**
+     * Get the desired HTTP status code for this exception.
+     */
+    public function getStatusCode(): int
+    {
+        return ($this->getCode() === 0) ? 500 : $this->getCode();
+    }
+
+    /**
+     * Get the desired HTTP headers for this exception.
+     */
+    public function getHeaders(): array
+    {
+        return [];
+    }
 }
diff --git a/tests/Api/PagesApiTest.php b/tests/Api/PagesApiTest.php
index 12b38bc07..75cc2807f 100644
--- a/tests/Api/PagesApiTest.php
+++ b/tests/Api/PagesApiTest.php
@@ -159,6 +159,27 @@ class PagesApiTest extends TestCase
         $this->assertStringContainsString('testing', $html);
     }
 
+    public function test_read_endpoint_returns_not_found()
+    {
+        $this->actingAsApiEditor();
+        // get an id that is not used
+        $id = Page::orderBy('id', 'desc')->first()->id + 1;
+        $this->assertNull(Page::find($id));
+
+        $resp = $this->getJson($this->baseEndpoint . "/$id");
+
+        $resp->assertNotFound();
+        $this->assertNull($resp->json('id'));
+        $resp->assertJsonIsObject('error');
+        $resp->assertJsonStructure([
+            'error' => [
+                'code',
+                'message',
+            ],
+        ]);
+        $this->assertSame(404, $resp->json('error')['code']);
+    }
+
     public function test_update_endpoint()
     {
         $this->actingAsApiEditor();