diff --git a/src/Controller/JsonapiTaxonomyTree.php b/src/Controller/JsonapiTaxonomyTree.php
index 09d70e41ca81e1d0421baaade4cc49fee44d9226..01b51bf32bbd1c53a6c55b6ddfbaa6c895ab5a77 100644
--- a/src/Controller/JsonapiTaxonomyTree.php
+++ b/src/Controller/JsonapiTaxonomyTree.php
@@ -2,6 +2,8 @@
 
 namespace Drupal\jsonapi_taxonomy_tree\Controller;
 
+use Drupal\Core\Cache\CacheableJsonResponse;
+use Drupal\Core\Cache\CacheableMetadata;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\taxonomy\VocabularyInterface;
 use Symfony\Component\HttpFoundation\JsonResponse;
@@ -65,9 +67,25 @@ class JsonapiTaxonomyTree extends ControllerBase {
         $nextUrl = isset($data['links']['next']['href']) ? $data['links']['next']['href'] : NULL;
       }
       while ($nextUrl);
+      $return_data = [];
+      $return_data['cache_time'] = date('Y-m-d H:i:s');
+      $return_data['data'] = $this->processData($vid, $jsonapi_data);
+      $response = new CacheableJsonResponse($return_data);
 
-      $return_data = $this->processData($vid, $jsonapi_data);
-      return new JsonResponse($return_data);
+      // Handle cache
+      $cacheability = (new CacheableMetadata())->addCacheContexts([
+        // Make sure that different sparse fieldsets are cached differently.
+        'url.query_args:fields',
+        // Make sure that different sets of includes are cached differently.
+        'url.query_args:include',
+        'url.query_args:filter',
+        'url.query_args:sort',
+        'url.query_args:page',
+      ]);
+      $response->addCacheableDependency($cacheability);
+      $response->addCacheableDependency((new CacheableMetadata())->addCacheTags(['taxonomy_term_list:'.$vid]));
+
+      return $response;
     }
     catch (\Exception $e) {
       return new JsonResponse(['error' => $e->getMessage()], 500);