diff --git a/src/Api/Actions/JsonApiAction.php b/src/Api/Actions/JsonApiAction.php
index 09e54dcf4..932d96174 100644
--- a/src/Api/Actions/JsonApiAction.php
+++ b/src/Api/Actions/JsonApiAction.php
@@ -13,8 +13,6 @@ namespace Flarum\Api\Actions;
 use Flarum\Api\Request;
 use Illuminate\Contracts\Validation\ValidationException;
 use Illuminate\Database\Eloquent\ModelNotFoundException;
-use Flarum\Core\Exceptions\ValidationFailureException;
-use Flarum\Core\Exceptions\PermissionDeniedException;
 use Zend\Diactoros\Response\JsonResponse;
 
 abstract class JsonApiAction implements Action
@@ -40,14 +38,6 @@ abstract class JsonApiAction implements Action
                 ];
             }
             return new JsonResponse(['errors' => $errors], 422);
-        } catch (\Flarum\Core\Exceptions\ValidationException $e) {
-            $errors = [];
-            foreach ($e->getMessages() as $path => $detail) {
-                $errors[] = compact('path', 'detail');
-            }
-            return new JsonResponse(['errors' => $errors], 422);
-        } catch (PermissionDeniedException $e) {
-            return new JsonResponse(null, 401);
         } catch (ModelNotFoundException $e) {
             return new JsonResponse(null, 404);
         }
diff --git a/src/Api/Middleware/JsonApiErrors.php b/src/Api/Middleware/JsonApiErrors.php
index 0b76a70a1..8293d4767 100644
--- a/src/Api/Middleware/JsonApiErrors.php
+++ b/src/Api/Middleware/JsonApiErrors.php
@@ -10,6 +10,7 @@
 
 namespace Flarum\Api\Middleware;
 
+use Flarum\Core\Exceptions\JsonApiSerializable;
 use Psr\Http\Message\ResponseInterface as Response;
 use Psr\Http\Message\ServerRequestInterface as Request;
 use Zend\Diactoros\Response\JsonResponse;
@@ -22,23 +23,29 @@ class JsonApiErrors implements ErrorMiddlewareInterface
      */
     public function __invoke($error, Request $request, Response $response, callable $out = null)
     {
-        $errorObject = [
-            'title' => $error->getMessage(),
-        ];
+        if ($error instanceof JsonApiSerializable) {
+            $status = $error->getStatusCode();
 
-        $status = 500;
+            $errors = $error->getErrors();
+        } else {
+            $status = 500;
 
-        // If it seems to be a valid HTTP status code, we pass on the
-        // exception's status.
-        $errorCode = $error->getCode();
-        if (is_int($errorCode) && $errorCode >= 400 && $errorCode < 600) {
-            $status = $errorCode;
+            $errors = [
+                ['title' => $error->getMessage()]
+            ];
+
+            // If it seems to be a valid HTTP status code, we pass on the
+            // exception's status.
+            $errorCode = $error->getCode();
+            if (is_int($errorCode) && $errorCode >= 400 && $errorCode < 600) {
+                $status = $errorCode;
+            }
         }
 
         // JSON API errors must be collected in an array under the
         // "errors" key in the top level of the document
         $data = [
-            'errors' => [$errorObject]
+            'errors' => $errors,
         ];
 
         return new JsonResponse($data, $status);