diff --git a/mobile/openapi/doc/AssetApi.md b/mobile/openapi/doc/AssetApi.md
index 319deb2ac..c71b4151d 100644
--- a/mobile/openapi/doc/AssetApi.md
+++ b/mobile/openapi/doc/AssetApi.md
@@ -822,7 +822,7 @@ Name | Type | Description  | Notes
 ### HTTP request headers
 
  - **Content-Type**: Not defined
- - **Accept**: application/octet-stream
+ - **Accept**: image/jpeg, image/webp
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
diff --git a/mobile/openapi/doc/PersonApi.md b/mobile/openapi/doc/PersonApi.md
index dd1c0eb8e..aa37a294e 100644
--- a/mobile/openapi/doc/PersonApi.md
+++ b/mobile/openapi/doc/PersonApi.md
@@ -228,7 +228,7 @@ Name | Type | Description  | Notes
 ### HTTP request headers
 
  - **Content-Type**: Not defined
- - **Accept**: application/octet-stream
+ - **Accept**: image/jpeg
 
 [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
 
diff --git a/server/immich-openapi-specs.json b/server/immich-openapi-specs.json
index caae449e2..5f664730f 100644
--- a/server/immich-openapi-specs.json
+++ b/server/immich-openapi-specs.json
@@ -1673,7 +1673,13 @@
         "responses": {
           "200": {
             "content": {
-              "application/octet-stream": {
+              "image/jpeg": {
+                "schema": {
+                  "type": "string",
+                  "format": "binary"
+                }
+              },
+              "image/webp": {
                 "schema": {
                   "type": "string",
                   "format": "binary"
@@ -2704,7 +2710,7 @@
         "responses": {
           "200": {
             "content": {
-              "application/octet-stream": {
+              "image/jpeg": {
                 "schema": {
                   "type": "string",
                   "format": "binary"
diff --git a/server/src/immich/api-v1/asset/asset.controller.ts b/server/src/immich/api-v1/asset/asset.controller.ts
index c2d3e6b39..7cd93bd7e 100644
--- a/server/src/immich/api-v1/asset/asset.controller.ts
+++ b/server/src/immich/api-v1/asset/asset.controller.ts
@@ -19,7 +19,7 @@ import {
   ValidationPipe,
 } from '@nestjs/common';
 import { FileFieldsInterceptor } from '@nestjs/platform-express';
-import { ApiBody, ApiConsumes, ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger';
+import { ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger';
 import { Response as Res } from 'express';
 import { Authenticated, AuthUser, SharedLinkRoute } from '../../app.guard';
 import { assetUploadOption, ImmichFile } from '../../config/asset-upload.config';
@@ -122,7 +122,6 @@ export class AssetController {
   @SharedLinkRoute()
   @Get('/file/:id')
   @Header('Cache-Control', 'private, max-age=86400, no-transform')
-  @ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
   serveFile(
     @AuthUser() authUser: AuthUserDto,
     @Headers() headers: Record<string, string>,
@@ -136,7 +135,6 @@ export class AssetController {
   @SharedLinkRoute()
   @Get('/thumbnail/:id')
   @Header('Cache-Control', 'private, max-age=86400, no-transform')
-  @ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
   getAssetThumbnail(
     @AuthUser() authUser: AuthUserDto,
     @Headers() headers: Record<string, string>,
diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts
index 0a1ee8e0e..26c0ca7bb 100644
--- a/server/src/immich/api-v1/asset/asset.service.ts
+++ b/server/src/immich/api-v1/asset/asset.service.ts
@@ -256,8 +256,8 @@ export class AssetService {
     }
 
     try {
-      const thumbnailPath = this.getThumbnailPath(asset, query.format);
-      return this.streamFile(thumbnailPath, res, headers);
+      const [thumbnailPath, contentType] = this.getThumbnailPath(asset, query.format);
+      return this.streamFile(thumbnailPath, res, headers, contentType);
     } catch (e) {
       res.header('Cache-Control', 'none');
       this.logger.error(`Cannot create read stream for asset ${asset.id}`, 'getAssetThumbnail');
@@ -522,16 +522,17 @@ export class AssetService {
   private getThumbnailPath(asset: AssetEntity, format: GetAssetThumbnailFormatEnum) {
     switch (format) {
       case GetAssetThumbnailFormatEnum.WEBP:
-        if (asset.webpPath && asset.webpPath.length > 0) {
-          return asset.webpPath;
+        if (asset.webpPath) {
+          return [asset.webpPath, 'image/webp'];
         }
+        this.logger.warn(`WebP thumbnail requested but not found for asset ${asset.id}, falling back to JPEG`);
 
       case GetAssetThumbnailFormatEnum.JPEG:
       default:
         if (!asset.resizePath) {
-          throw new NotFoundException('resizePath not set');
+          throw new NotFoundException(`No thumbnail found for asset ${asset.id}`);
         }
-        return asset.resizePath;
+        return [asset.resizePath, 'image/jpeg'];
     }
   }
 
diff --git a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts
index 5a8dc0687..ad0e755d6 100644
--- a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts
+++ b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts
@@ -1,5 +1,5 @@
 import { ApiProperty } from '@nestjs/swagger';
-import { IsOptional } from 'class-validator';
+import { IsEnum, IsOptional } from 'class-validator';
 
 export enum GetAssetThumbnailFormatEnum {
   JPEG = 'JPEG',
@@ -8,6 +8,7 @@ export enum GetAssetThumbnailFormatEnum {
 
 export class GetAssetThumbnailDto {
   @IsOptional()
+  @IsEnum(GetAssetThumbnailFormatEnum)
   @ApiProperty({
     type: String,
     enum: GetAssetThumbnailFormatEnum,
diff --git a/server/src/immich/controllers/person.controller.ts b/server/src/immich/controllers/person.controller.ts
index 575230459..2e8135161 100644
--- a/server/src/immich/controllers/person.controller.ts
+++ b/server/src/immich/controllers/person.controller.ts
@@ -7,7 +7,7 @@ import {
   PersonUpdateDto,
 } from '@app/domain';
 import { Body, Controller, Get, Param, Put, StreamableFile } from '@nestjs/common';
-import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
+import { ApiTags } from '@nestjs/swagger';
 import { Authenticated, AuthUser } from '../app.guard';
 import { UseValidation } from '../app.utils';
 import { UUIDParamDto } from './dto/uuid-param.dto';
@@ -43,7 +43,6 @@ export class PersonController {
   }
 
   @Get(':id/thumbnail')
-  @ApiOkResponse({ content: { 'application/octet-stream': { schema: { type: 'string', format: 'binary' } } } })
   getPersonThumbnail(@AuthUser() authUser: AuthUserDto, @Param() { id }: UUIDParamDto) {
     return this.service.getThumbnail(authUser, id).then(asStreamableFile);
   }