diff --git a/VERSION b/VERSION
index fc34e249..d986e55c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-20250411.1
+20250412
diff --git a/src/Colours/ColoursApiRoutes.php b/src/Colours/ColoursApiRoutes.php
index 4a4675c6..43716904 100644
--- a/src/Colours/ColoursApiRoutes.php
+++ b/src/Colours/ColoursApiRoutes.php
@@ -51,11 +51,13 @@ final class ColoursApiRoutes implements RouteHandler {
     /** @return int|mixed[] */
     #[AccessControl]
     #[ExactRoute('GET', '/api/v1/colours/presets')]
-    public function getPresets(HttpRequest $request): array|int {
+    public function getPresets(HttpResponseBuilder $response, HttpRequest $request): array|int {
         $transformer = $this->createPresetTransformer();
         if(!$transformer->filter($request))
             return 400;
 
+        $response->setCacheControl('max-age=3600', 'stale-if-error=86400', 'public', 'immutable');
+
         return XArray::select(
             $this->coloursCtx->presets->getPresets(),
             fn($preset) => $transformer->convert($preset),
@@ -65,7 +67,7 @@ final class ColoursApiRoutes implements RouteHandler {
     /** @return int|mixed[] */
     #[AccessControl]
     #[PatternRoute('GET', '/api/v1/colours/presets/([A-Za-z0-9\-_]+)')]
-    public function getPreset(HttpRequest $request, string $name): array|int {
+    public function getPreset(HttpResponseBuilder $response, HttpRequest $request, string $name): array|int {
         if(empty($name))
             return 404;
 
@@ -73,6 +75,8 @@ final class ColoursApiRoutes implements RouteHandler {
         if(!$transformer->filter($request))
             return 400;
 
+        $response->setCacheControl('max-age=3600', 'stale-if-error=86400', 'public', 'immutable');
+
         try {
             $preset = $this->coloursCtx->presets->getPreset(
                 $name,
diff --git a/src/Emoticons/EmotesApiRoutes.php b/src/Emoticons/EmotesApiRoutes.php
index 248de7d8..3afe691b 100644
--- a/src/Emoticons/EmotesApiRoutes.php
+++ b/src/Emoticons/EmotesApiRoutes.php
@@ -48,11 +48,13 @@ final class EmotesApiRoutes implements RouteHandler {
     /** @return int|mixed[] */
     #[AccessControl]
     #[ExactRoute('GET', '/api/v1/emotes')]
-    public function getEmotes(HttpRequest $request): array|int {
+    public function getEmotes(HttpResponseBuilder $response, HttpRequest $request): array|int {
         $transformer = $this->createEmoteTransformer();
         if(!$transformer->filter($request))
             return 400;
 
+        $response->setCacheControl('max-age=3600', 'stale-if-error=86400', 'public', 'immutable');
+
         return XArray::select(
             $this->emotesCtx->emotes->getEmotes(orderBy: 'order'),
             fn($emote) => $transformer->convert($emote),
@@ -62,7 +64,7 @@ final class EmotesApiRoutes implements RouteHandler {
     /** @return int|mixed[] */
     #[AccessControl]
     #[PatternRoute('GET', '/api/v1/emotes/([0-9]+)')]
-    public function getEmote(HttpRequest $request, string $id): array|int {
+    public function getEmote(HttpResponseBuilder $response, HttpRequest $request, string $id): array|int {
         if(empty($id))
             return 404;
 
@@ -76,6 +78,8 @@ final class EmotesApiRoutes implements RouteHandler {
             return 404;
         }
 
+        $response->setCacheControl('max-age=3600', 'stale-if-error=86400', 'public', 'immutable');
+
         return $transformer->convert($emote);
     }
 
@@ -95,7 +99,7 @@ final class EmotesApiRoutes implements RouteHandler {
     /** @return int|mixed[] */
     #[AccessControl]
     #[PatternRoute('GET', '/api/v1/emotes/([0-9]+)/strings')]
-    public function getEmoteStrings(HttpRequest $request, string $id): array|int {
+    public function getEmoteStrings(HttpResponseBuilder $response, HttpRequest $request, string $id): array|int {
         if(empty($id))
             return 404;
 
@@ -109,6 +113,8 @@ final class EmotesApiRoutes implements RouteHandler {
             return 404;
         }
 
+        $response->setCacheControl('max-age=3600', 'stale-if-error=86400', 'public', 'immutable');
+
         return XArray::select(
             $this->emotesCtx->emotes->getEmoteStrings($emote),
             fn($emote) => $transformer->convert($emote),
diff --git a/src/Users/UsersApiRoutes.php b/src/Users/UsersApiRoutes.php
index b2fe0dac..57576a48 100644
--- a/src/Users/UsersApiRoutes.php
+++ b/src/Users/UsersApiRoutes.php
@@ -132,7 +132,7 @@ final class UsersApiRoutes implements RouteHandler {
     #[Before('authz:bearer', required: false)]
     #[Before('authz:misuzu', required: false)]
     public function getMe(HttpResponseBuilder $response, HttpRequest $request): int|array {
-        $response->setHeader('Cache-Control', 'no-store');
+        $response->setCacheControl('no-store');
 
         $openid = $this->authInfo->hasScope('openid');
         if(!$openid