From 4ebc25c754a4747282ddb70d25c4adf897cc9b4b Mon Sep 17 00:00:00 2001
From: Arno <46051866+arnolicious@users.noreply.github.com>
Date: Thu, 6 Mar 2025 18:27:43 +0100
Subject: [PATCH] feat(mobile): Folder View for mobile (#15047)

* very rough prototype for folder navigation without assets

* fix: refactored data model and tried to implement asset loading

* fix: openapi generator shadowing query param in /view/folder

* add simple alphanumeric sorting for folders

* basic asset viewing in folders

* rudimentary switch sorting order

* fixed reactivity when toggling sort order

* Fixed trailing comma

* Fixed bad merge conflict resolution

* Regenerated open-api

* Added rudimentary breadcrumbs

* Fixed linting problems

* feat: cleanup

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
---
 mobile/assets/i18n/en-US.json                 |   8 +-
 .../lib/interfaces/folder_api.interface.dart  |   6 +
 .../models/folder/recursive_folder.model.dart |  11 +
 .../lib/models/folder/root_folder.model.dart  |  11 +
 .../lib/pages/library/folder/folder.page.dart | 320 ++++++++++++++++++
 mobile/lib/pages/library/library.page.dart    |  13 +
 mobile/lib/providers/folder.provider.dart     |  62 ++++
 .../repositories/folder_api.repository.dart   |  43 +++
 mobile/lib/routing/router.dart                |   7 +
 mobile/lib/routing/router.gr.dart             |  34 ++
 mobile/lib/services/api.service.dart          |   2 +
 mobile/lib/services/folder.service.dart       | 132 ++++++++
 mobile/lib/widgets/common/immich_app_bar.dart |   7 -
 mobile/openapi/lib/api/activities_api.dart    |  16 +-
 mobile/openapi/lib/api/albums_api.dart        |  44 +--
 mobile/openapi/lib/api/api_keys_api.dart      |  20 +-
 mobile/openapi/lib/api/assets_api.dart        |  68 ++--
 .../openapi/lib/api/authentication_api.dart   |  20 +-
 mobile/openapi/lib/api/deprecated_api.dart    |   4 +-
 mobile/openapi/lib/api/download_api.dart      |   8 +-
 mobile/openapi/lib/api/duplicates_api.dart    |   4 +-
 mobile/openapi/lib/api/faces_api.dart         |  16 +-
 mobile/openapi/lib/api/file_reports_api.dart  |  12 +-
 mobile/openapi/lib/api/jobs_api.dart          |  12 +-
 mobile/openapi/lib/api/libraries_api.dart     |  32 +-
 mobile/openapi/lib/api/map_api.dart           |   8 +-
 mobile/openapi/lib/api/memories_api.dart      |  28 +-
 mobile/openapi/lib/api/notifications_api.dart |   8 +-
 mobile/openapi/lib/api/o_auth_api.dart        |  20 +-
 mobile/openapi/lib/api/partners_api.dart      |  16 +-
 mobile/openapi/lib/api/people_api.dart        |  36 +-
 mobile/openapi/lib/api/search_api.dart        |  32 +-
 mobile/openapi/lib/api/server_api.dart        |  52 +--
 mobile/openapi/lib/api/sessions_api.dart      |  12 +-
 mobile/openapi/lib/api/shared_links_api.dart  |  32 +-
 mobile/openapi/lib/api/stacks_api.dart        |  24 +-
 mobile/openapi/lib/api/sync_api.dart          |  24 +-
 mobile/openapi/lib/api/system_config_api.dart |  16 +-
 .../openapi/lib/api/system_metadata_api.dart  |  12 +-
 mobile/openapi/lib/api/tags_api.dart          |  36 +-
 mobile/openapi/lib/api/timeline_api.dart      |   8 +-
 mobile/openapi/lib/api/trash_api.dart         |  12 +-
 mobile/openapi/lib/api/users_admin_api.dart   |  32 +-
 mobile/openapi/lib/api/users_api.dart         |  50 +--
 mobile/openapi/lib/api/view_api.dart          |   8 +-
 mobile/pubspec.yaml                           |   2 +-
 open-api/bin/generate-open-api.sh             |   6 +-
 open-api/templates/mobile/api.mustache        | 194 +++++++++++
 open-api/templates/mobile/api.mustache.patch  |  29 ++
 49 files changed, 1238 insertions(+), 371 deletions(-)
 create mode 100644 mobile/lib/interfaces/folder_api.interface.dart
 create mode 100644 mobile/lib/models/folder/recursive_folder.model.dart
 create mode 100644 mobile/lib/models/folder/root_folder.model.dart
 create mode 100644 mobile/lib/pages/library/folder/folder.page.dart
 create mode 100644 mobile/lib/providers/folder.provider.dart
 create mode 100644 mobile/lib/repositories/folder_api.repository.dart
 create mode 100644 mobile/lib/services/folder.service.dart
 create mode 100644 open-api/templates/mobile/api.mustache
 create mode 100644 open-api/templates/mobile/api.mustache.patch

diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json
index fd628d4692..3854c0c517 100644
--- a/mobile/assets/i18n/en-US.json
+++ b/mobile/assets/i18n/en-US.json
@@ -252,6 +252,7 @@
   "edit_date_time_dialog_timezone": "Timezone",
   "edit_image_title": "Edit",
   "edit_location_dialog_title": "Location",
+  "empty_folder": "This folder is empty",
   "end_date": "End date",
   "enqueued": "Enqueued",
   "enter_wifi_name": "Enter WiFi name",
@@ -275,6 +276,11 @@
   "favorites_page_title": "Favorites",
   "filename_search": "File name or extension",
   "filter": "Filter",
+  "folders": "Folders",
+  "folder": "Folder",
+  "failed_to_load_folder": "Failed to load folder",
+  "failed_to_load_assets": "Failed to load assets",
+  "folder_not_found": "Folder not found",
   "get_wifiname_error": "Could not get Wi-Fi name. Make sure you have granted the necessary permissions and are connected to a Wi-Fi network",
   "grant_permission": "Grant permission",
   "haptic_feedback_switch": "Enable haptic feedback",
@@ -678,4 +684,4 @@
   "viewer_unstack": "Un-Stack",
   "wifi_name": "WiFi Name",
   "your_wifi_name": "Your WiFi name"
-}
\ No newline at end of file
+}
diff --git a/mobile/lib/interfaces/folder_api.interface.dart b/mobile/lib/interfaces/folder_api.interface.dart
new file mode 100644
index 0000000000..68c1652e21
--- /dev/null
+++ b/mobile/lib/interfaces/folder_api.interface.dart
@@ -0,0 +1,6 @@
+import 'package:immich_mobile/entities/asset.entity.dart';
+
+abstract interface class IFolderApiRepository {
+  Future<List<String>> getAllUniquePaths();
+  Future<List<Asset>> getAssetsForPath(String? path);
+}
diff --git a/mobile/lib/models/folder/recursive_folder.model.dart b/mobile/lib/models/folder/recursive_folder.model.dart
new file mode 100644
index 0000000000..5b54a2e1bf
--- /dev/null
+++ b/mobile/lib/models/folder/recursive_folder.model.dart
@@ -0,0 +1,11 @@
+import 'package:immich_mobile/models/folder/root_folder.model.dart';
+
+class RecursiveFolder extends RootFolder {
+  final String name;
+
+  RecursiveFolder({
+    required this.name,
+    required super.path,
+    required super.subfolders,
+  });
+}
diff --git a/mobile/lib/models/folder/root_folder.model.dart b/mobile/lib/models/folder/root_folder.model.dart
new file mode 100644
index 0000000000..8f72a539c0
--- /dev/null
+++ b/mobile/lib/models/folder/root_folder.model.dart
@@ -0,0 +1,11 @@
+import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
+
+class RootFolder {
+  final List<RecursiveFolder> subfolders;
+  final String path;
+
+  RootFolder({
+    required this.subfolders,
+    required this.path,
+  });
+}
diff --git a/mobile/lib/pages/library/folder/folder.page.dart b/mobile/lib/pages/library/folder/folder.page.dart
new file mode 100644
index 0000000000..af6f295970
--- /dev/null
+++ b/mobile/lib/pages/library/folder/folder.page.dart
@@ -0,0 +1,320 @@
+import 'package:auto_route/auto_route.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_hooks/flutter_hooks.dart';
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/constants/enums.dart';
+import 'package:immich_mobile/extensions/build_context_extensions.dart';
+import 'package:immich_mobile/extensions/theme_extensions.dart';
+import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
+import 'package:immich_mobile/models/folder/root_folder.model.dart';
+import 'package:immich_mobile/pages/common/large_leading_tile.dart';
+import 'package:immich_mobile/providers/folder.provider.dart';
+import 'package:immich_mobile/routing/router.dart';
+import 'package:immich_mobile/utils/bytes_units.dart';
+import 'package:immich_mobile/widgets/asset_grid/thumbnail_image.dart';
+import 'package:immich_mobile/widgets/common/immich_toast.dart';
+
+RecursiveFolder? _findFolderInStructure(
+  RootFolder rootFolder,
+  RecursiveFolder targetFolder,
+) {
+  for (final folder in rootFolder.subfolders) {
+    if (targetFolder.path == '/' &&
+        folder.path.isEmpty &&
+        folder.name == targetFolder.name) {
+      return folder;
+    }
+
+    if (folder.path == targetFolder.path && folder.name == targetFolder.name) {
+      return folder;
+    }
+
+    if (folder.subfolders.isNotEmpty) {
+      final found = _findFolderInStructure(folder, targetFolder);
+      if (found != null) return found;
+    }
+  }
+  return null;
+}
+
+@RoutePage()
+class FolderPage extends HookConsumerWidget {
+  final RecursiveFolder? folder;
+
+  const FolderPage({super.key, this.folder});
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final folderState = ref.watch(folderStructureProvider);
+    final currentFolder = useState<RecursiveFolder?>(folder);
+    final sortOrder = useState<SortOrder>(SortOrder.asc);
+
+    useEffect(
+      () {
+        if (folder == null) {
+          ref
+              .read(folderStructureProvider.notifier)
+              .fetchFolders(sortOrder.value);
+        }
+        return null;
+      },
+      [],
+    );
+
+    // Update current folder when root structure changes
+    useEffect(
+      () {
+        if (folder != null && folderState.hasValue) {
+          final updatedFolder =
+              _findFolderInStructure(folderState.value!, folder!);
+          if (updatedFolder != null) {
+            currentFolder.value = updatedFolder;
+          }
+        }
+        return null;
+      },
+      [folderState],
+    );
+
+    void onToggleSortOrder() {
+      final newOrder =
+          sortOrder.value == SortOrder.asc ? SortOrder.desc : SortOrder.asc;
+
+      ref.read(folderStructureProvider.notifier).fetchFolders(newOrder);
+
+      sortOrder.value = newOrder;
+    }
+
+    return Scaffold(
+      appBar: AppBar(
+        title: Text(currentFolder.value?.name ?? tr("folders")),
+        elevation: 0,
+        centerTitle: false,
+        actions: [
+          IconButton(
+            icon: const Icon(Icons.swap_vert),
+            onPressed: onToggleSortOrder,
+          ),
+        ],
+      ),
+      body: folderState.when(
+        data: (rootFolder) {
+          if (folder == null) {
+            return FolderContent(
+              folder: rootFolder,
+              root: rootFolder,
+              sortOrder: sortOrder.value,
+            );
+          } else {
+            return FolderContent(
+              folder: currentFolder.value!,
+              root: rootFolder,
+              sortOrder: sortOrder.value,
+            );
+          }
+        },
+        loading: () => const Center(
+          child: CircularProgressIndicator(),
+        ),
+        error: (error, stack) {
+          ImmichToast.show(
+            context: context,
+            msg: "failed_to_load_folder".tr(),
+            toastType: ToastType.error,
+          );
+          return Center(child: const Text("failed_to_load_folder").tr());
+        },
+      ),
+    );
+  }
+}
+
+class FolderContent extends HookConsumerWidget {
+  final RootFolder? folder;
+  final RootFolder root;
+  final SortOrder sortOrder;
+
+  const FolderContent({
+    super.key,
+    this.folder,
+    required this.root,
+    this.sortOrder = SortOrder.asc,
+  });
+
+  @override
+  Widget build(BuildContext context, WidgetRef ref) {
+    final folderRenderlist = ref.watch(folderRenderListProvider(folder!));
+
+    // Initial asset fetch
+    useEffect(
+      () {
+        if (folder == null) return;
+        ref
+            .read(folderRenderListProvider(folder!).notifier)
+            .fetchAssets(sortOrder);
+        return null;
+      },
+      [folder],
+    );
+
+    if (folder == null) {
+      return Center(child: const Text("folder_not_found").tr());
+    }
+
+    getSubtitle(int subFolderCount) {
+      if (subFolderCount > 0) {
+        return "$subFolderCount ${tr("folders")}".toLowerCase();
+      }
+
+      if (subFolderCount == 1) {
+        return "1 ${tr("folder")}".toLowerCase();
+      }
+
+      return "";
+    }
+
+    return Column(
+      children: [
+        FolderPath(currentFolder: folder!, root: root),
+        Expanded(
+          child: folderRenderlist.when(
+            data: (list) {
+              if (folder!.subfolders.isEmpty && list.isEmpty) {
+                return Center(child: const Text("empty_folder").tr());
+              }
+
+              return ListView(
+                children: [
+                  if (folder!.subfolders.isNotEmpty)
+                    ...folder!.subfolders.map(
+                      (subfolder) => LargeLeadingTile(
+                        leading: Icon(
+                          Icons.folder,
+                          color: context.primaryColor,
+                          size: 48,
+                        ),
+                        title: Text(
+                          subfolder.name,
+                          softWrap: false,
+                          overflow: TextOverflow.ellipsis,
+                          style: context.textTheme.titleSmall?.copyWith(
+                            fontWeight: FontWeight.w600,
+                          ),
+                        ),
+                        subtitle: subfolder.subfolders.isNotEmpty
+                            ? Text(
+                                getSubtitle(subfolder.subfolders.length),
+                                style: context.textTheme.bodyMedium?.copyWith(
+                                  color: context.colorScheme.onSurfaceSecondary,
+                                ),
+                              )
+                            : null,
+                        onTap: () =>
+                            context.pushRoute(FolderRoute(folder: subfolder)),
+                      ),
+                    ),
+                  if (!list.isEmpty &&
+                      list.allAssets != null &&
+                      list.allAssets!.isNotEmpty)
+                    ...list.allAssets!.map(
+                      (asset) => LargeLeadingTile(
+                        onTap: () => context.pushRoute(
+                          GalleryViewerRoute(
+                            renderList: list,
+                            initialIndex: list.allAssets!.indexOf(asset),
+                          ),
+                        ),
+                        leading: ClipRRect(
+                          borderRadius: const BorderRadius.all(
+                            Radius.circular(15),
+                          ),
+                          child: SizedBox(
+                            width: 80,
+                            height: 80,
+                            child: ThumbnailImage(
+                              asset: asset,
+                              showStorageIndicator: false,
+                            ),
+                          ),
+                        ),
+                        title: Text(
+                          asset.fileName,
+                          maxLines: 2,
+                          softWrap: false,
+                          overflow: TextOverflow.ellipsis,
+                          style: context.textTheme.titleSmall?.copyWith(
+                            fontWeight: FontWeight.w600,
+                          ),
+                        ),
+                        subtitle: Text(
+                          "${asset.exifInfo?.fileSize != null ? formatBytes(asset.exifInfo?.fileSize ?? 0) : ""} • ${DateFormat.yMMMd().format(asset.fileCreatedAt)}",
+                          style: context.textTheme.bodyMedium?.copyWith(
+                            color: context.colorScheme.onSurfaceSecondary,
+                          ),
+                        ),
+                      ),
+                    ),
+                ],
+              );
+            },
+            loading: () => const Center(
+              child: CircularProgressIndicator(),
+            ),
+            error: (error, stack) {
+              ImmichToast.show(
+                context: context,
+                msg: "failed_to_load_assets".tr(),
+                toastType: ToastType.error,
+              );
+              return Center(child: const Text("failed_to_load_assets").tr());
+            },
+          ),
+        ),
+      ],
+    );
+  }
+}
+
+class FolderPath extends StatelessWidget {
+  final RootFolder currentFolder;
+  final RootFolder root;
+
+  const FolderPath({
+    super.key,
+    required this.currentFolder,
+    required this.root,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    if (currentFolder.path.isEmpty || currentFolder.path == '/') {
+      return const SizedBox.shrink();
+    }
+
+    return Container(
+      width: double.infinity,
+      alignment: Alignment.centerLeft,
+      child: SingleChildScrollView(
+        scrollDirection: Axis.horizontal,
+        child: Padding(
+          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
+          child: Row(
+            mainAxisAlignment: MainAxisAlignment.start,
+            children: [
+              Text(
+                currentFolder.path,
+                style: TextStyle(
+                  fontFamily: 'Inconsolata',
+                  fontWeight: FontWeight.bold,
+                  fontSize: 14,
+                  color: context.colorScheme.onSurface.withAlpha(175),
+                ),
+              ),
+            ],
+          ),
+        ),
+      ),
+    );
+  }
+}
diff --git a/mobile/lib/pages/library/library.page.dart b/mobile/lib/pages/library/library.page.dart
index 92fe8cec17..31b465ead7 100644
--- a/mobile/lib/pages/library/library.page.dart
+++ b/mobile/lib/pages/library/library.page.dart
@@ -128,6 +128,19 @@ class QuickAccessButtons extends ConsumerWidget {
                 bottomRight: Radius.circular(partners.isEmpty ? 20 : 0),
               ),
             ),
+            leading: const Icon(
+              Icons.folder_outlined,
+              size: 26,
+            ),
+            title: Text(
+              'folders'.tr(),
+              style: context.textTheme.titleSmall?.copyWith(
+                fontWeight: FontWeight.w500,
+              ),
+            ),
+            onTap: () => context.pushRoute(FolderRoute()),
+          ),
+          ListTile(
             leading: const Icon(
               Icons.group_outlined,
               size: 26,
diff --git a/mobile/lib/providers/folder.provider.dart b/mobile/lib/providers/folder.provider.dart
new file mode 100644
index 0000000000..810c2cea73
--- /dev/null
+++ b/mobile/lib/providers/folder.provider.dart
@@ -0,0 +1,62 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/constants/enums.dart';
+import 'package:immich_mobile/models/folder/root_folder.model.dart';
+import 'package:immich_mobile/services/folder.service.dart';
+import 'package:immich_mobile/widgets/asset_grid/asset_grid_data_structure.dart';
+import 'package:logging/logging.dart';
+
+class FolderStructureNotifier extends StateNotifier<AsyncValue<RootFolder>> {
+  final FolderService _folderService;
+  final Logger _log = Logger("FolderStructureNotifier");
+
+  FolderStructureNotifier(this._folderService) : super(const AsyncLoading());
+
+  Future<void> fetchFolders(SortOrder order) async {
+    try {
+      final folders = await _folderService.getFolderStructure(order);
+      state = AsyncData(folders);
+    } catch (e, stack) {
+      _log.severe("Failed to build folder structure", e, stack);
+      state = AsyncError(e, stack);
+    }
+  }
+}
+
+final folderStructureProvider =
+    StateNotifierProvider<FolderStructureNotifier, AsyncValue<RootFolder>>(
+        (ref) {
+  return FolderStructureNotifier(
+    ref.watch(folderServiceProvider),
+  );
+});
+
+class FolderRenderListNotifier extends StateNotifier<AsyncValue<RenderList>> {
+  final FolderService _folderService;
+  final RootFolder _folder;
+  final Logger _log = Logger("FolderAssetsNotifier");
+
+  FolderRenderListNotifier(this._folderService, this._folder)
+      : super(const AsyncLoading());
+
+  Future<void> fetchAssets(SortOrder order) async {
+    try {
+      final assets = await _folderService.getFolderAssets(_folder, order);
+      final renderList =
+          await RenderList.fromAssets(assets, GroupAssetsBy.none);
+      state = AsyncData(renderList);
+    } catch (e, stack) {
+      _log.severe("Failed to fetch folder assets", e, stack);
+      state = AsyncError(e, stack);
+    }
+  }
+}
+
+final folderRenderListProvider = StateNotifierProvider.family<
+    FolderRenderListNotifier,
+    AsyncValue<RenderList>,
+    RootFolder>((ref, folder) {
+  return FolderRenderListNotifier(
+    ref.watch(folderServiceProvider),
+    folder,
+  );
+});
diff --git a/mobile/lib/repositories/folder_api.repository.dart b/mobile/lib/repositories/folder_api.repository.dart
new file mode 100644
index 0000000000..bd7b035157
--- /dev/null
+++ b/mobile/lib/repositories/folder_api.repository.dart
@@ -0,0 +1,43 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/entities/asset.entity.dart';
+import 'package:immich_mobile/interfaces/folder_api.interface.dart';
+import 'package:immich_mobile/providers/api.provider.dart';
+import 'package:immich_mobile/repositories/api.repository.dart';
+import 'package:logging/logging.dart';
+import 'package:openapi/api.dart';
+
+final folderApiRepositoryProvider = Provider(
+  (ref) => FolderApiRepository(
+    ref.watch(apiServiceProvider).viewApi,
+  ),
+);
+
+class FolderApiRepository extends ApiRepository
+    implements IFolderApiRepository {
+  final ViewApi _api;
+  final Logger _log = Logger("FolderApiRepository");
+
+  FolderApiRepository(this._api);
+
+  @override
+  Future<List<String>> getAllUniquePaths() async {
+    try {
+      final list = await _api.getUniqueOriginalPaths();
+      return list ?? [];
+    } catch (e, stack) {
+      _log.severe("Failed to fetch unique original links", e, stack);
+      return [];
+    }
+  }
+
+  @override
+  Future<List<Asset>> getAssetsForPath(String? path) async {
+    try {
+      final list = await _api.getAssetsByOriginalPath(path ?? '/');
+      return list != null ? list.map(Asset.remote).toList() : [];
+    } catch (e, stack) {
+      _log.severe("Failed to fetch Assets by original path", e, stack);
+      return [];
+    }
+  }
+}
diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart
index ae5419b712..cd7a6f6b98 100644
--- a/mobile/lib/routing/router.dart
+++ b/mobile/lib/routing/router.dart
@@ -5,6 +5,8 @@ import 'package:immich_mobile/domain/models/log.model.dart';
 import 'package:immich_mobile/entities/album.entity.dart';
 import 'package:immich_mobile/entities/asset.entity.dart';
 import 'package:immich_mobile/entities/user.entity.dart';
+import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
+import 'package:immich_mobile/pages/library/folder/folder.page.dart';
 import 'package:immich_mobile/models/memories/memory.model.dart';
 import 'package:immich_mobile/models/search/search_filter.model.dart';
 import 'package:immich_mobile/models/shared_link/shared_link.model.dart';
@@ -207,6 +209,11 @@ class AppRouter extends RootStackRouter {
       guards: [_authGuard, _duplicateGuard],
       transitionsBuilder: TransitionsBuilders.slideLeft,
     ),
+    CustomRoute(
+      page: FolderRoute.page,
+      guards: [_authGuard],
+      transitionsBuilder: TransitionsBuilders.fadeIn,
+    ),
     AutoRoute(
       page: PartnerDetailRoute.page,
       guards: [_authGuard, _duplicateGuard],
diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart
index 299c8a602f..e120f512ae 100644
--- a/mobile/lib/routing/router.gr.dart
+++ b/mobile/lib/routing/router.gr.dart
@@ -1175,6 +1175,40 @@ class PartnerRoute extends PageRouteInfo<void> {
   );
 }
 
+/// manually written (with love) route for
+/// [FolderPage]
+class FolderRoute extends PageRouteInfo<FolderRouteArgs> {
+  FolderRoute({
+    RecursiveFolder? folder,
+    List<PageRouteInfo>? children,
+  }) : super(
+          FolderRoute.name,
+          args: FolderRouteArgs(folder: folder),
+          initialChildren: children,
+        );
+
+  static const String name = 'FolderRoute';
+
+  static PageInfo page = PageInfo(
+    name,
+    builder: (data) {
+      final args = data.argsAs<FolderRouteArgs>();
+      return FolderPage(folder: args.folder);
+    },
+  );
+}
+
+class FolderRouteArgs {
+  const FolderRouteArgs({this.folder});
+
+  final RecursiveFolder? folder;
+
+  @override
+  String toString() {
+    return 'FolderRouteArgs{folder: $folder}';
+  }
+}
+
 /// generated route for
 /// [PeopleCollectionPage]
 class PeopleCollectionRoute extends PageRouteInfo<void> {
diff --git a/mobile/lib/services/api.service.dart b/mobile/lib/services/api.service.dart
index b87e10f020..0ef68e1c41 100644
--- a/mobile/lib/services/api.service.dart
+++ b/mobile/lib/services/api.service.dart
@@ -31,6 +31,7 @@ class ApiService implements Authentication {
   late DownloadApi downloadApi;
   late TrashApi trashApi;
   late StacksApi stacksApi;
+  late ViewApi viewApi;
   late MemoriesApi memoriesApi;
 
   ApiService() {
@@ -64,6 +65,7 @@ class ApiService implements Authentication {
     downloadApi = DownloadApi(_apiClient);
     trashApi = TrashApi(_apiClient);
     stacksApi = StacksApi(_apiClient);
+    viewApi = ViewApi(_apiClient);
     memoriesApi = MemoriesApi(_apiClient);
   }
 
diff --git a/mobile/lib/services/folder.service.dart b/mobile/lib/services/folder.service.dart
new file mode 100644
index 0000000000..5b97b475b2
--- /dev/null
+++ b/mobile/lib/services/folder.service.dart
@@ -0,0 +1,132 @@
+import 'package:hooks_riverpod/hooks_riverpod.dart';
+import 'package:immich_mobile/constants/enums.dart';
+import 'package:immich_mobile/entities/asset.entity.dart';
+import 'package:immich_mobile/models/folder/recursive_folder.model.dart';
+import 'package:immich_mobile/models/folder/root_folder.model.dart';
+import 'package:immich_mobile/repositories/folder_api.repository.dart';
+import 'package:logging/logging.dart';
+
+final folderServiceProvider = Provider(
+  (ref) => FolderService(ref.watch(folderApiRepositoryProvider)),
+);
+
+class FolderService {
+  final FolderApiRepository _folderApiRepository;
+  final Logger _log = Logger("FolderService");
+
+  FolderService(this._folderApiRepository);
+
+  Future<RootFolder> getFolderStructure(SortOrder order) async {
+    final paths = await _folderApiRepository.getAllUniquePaths();
+
+    // Create folder structure
+    Map<String, List<RecursiveFolder>> folderMap = {};
+
+    for (String fullPath in paths) {
+      if (fullPath == '/') continue;
+
+      // Ensure the path starts with a slash
+      if (!fullPath.startsWith('/')) {
+        fullPath = '/$fullPath';
+      }
+
+      List<String> segments = fullPath.split('/')
+        ..removeWhere((s) => s.isEmpty);
+
+      String currentPath = '';
+
+      for (int i = 0; i < segments.length; i++) {
+        String parentPath = currentPath.isEmpty ? '_root_' : currentPath;
+        currentPath =
+            i == 0 ? '/${segments[i]}' : '$currentPath/${segments[i]}';
+
+        if (!folderMap.containsKey(parentPath)) {
+          folderMap[parentPath] = [];
+        }
+
+        if (!folderMap[parentPath]!.any((f) => f.name == segments[i])) {
+          folderMap[parentPath]!.add(
+            RecursiveFolder(
+              path: parentPath == '_root_' ? '' : parentPath,
+              name: segments[i],
+              subfolders: [],
+            ),
+          );
+          // Sort folders based on order parameter
+          folderMap[parentPath]!.sort(
+            (a, b) => order == SortOrder.desc
+                ? b.name.compareTo(a.name)
+                : a.name.compareTo(b.name),
+          );
+        }
+      }
+    }
+
+    void attachSubfolders(RecursiveFolder folder) {
+      String fullPath = folder.path.isEmpty
+          ? '/${folder.name}'
+          : '${folder.path}/${folder.name}';
+
+      if (folderMap.containsKey(fullPath)) {
+        folder.subfolders.addAll(folderMap[fullPath]!);
+        // Sort subfolders based on order parameter
+        folder.subfolders.sort(
+          (a, b) => order == SortOrder.desc
+              ? b.name.compareTo(a.name)
+              : a.name.compareTo(b.name),
+        );
+        for (var subfolder in folder.subfolders) {
+          attachSubfolders(subfolder);
+        }
+      }
+    }
+
+    List<RecursiveFolder> rootSubfolders = folderMap['_root_'] ?? [];
+    // Sort root subfolders based on order parameter
+    rootSubfolders.sort(
+      (a, b) => order == SortOrder.desc
+          ? b.name.compareTo(a.name)
+          : a.name.compareTo(b.name),
+    );
+
+    for (var folder in rootSubfolders) {
+      attachSubfolders(folder);
+    }
+
+    return RootFolder(
+      subfolders: rootSubfolders,
+      path: '/',
+    );
+  }
+
+  Future<List<Asset>> getFolderAssets(
+    RootFolder folder,
+    SortOrder order,
+  ) async {
+    try {
+      if (folder is RecursiveFolder) {
+        String fullPath =
+            folder.path.isEmpty ? folder.name : '${folder.path}/${folder.name}';
+        fullPath = fullPath[0] == '/' ? fullPath.substring(1) : fullPath;
+        var result = await _folderApiRepository.getAssetsForPath(fullPath);
+
+        if (order == SortOrder.desc) {
+          result.sort((a, b) => b.fileCreatedAt.compareTo(a.fileCreatedAt));
+        } else {
+          result.sort((a, b) => a.fileCreatedAt.compareTo(b.fileCreatedAt));
+        }
+
+        return result;
+      }
+      final result = await _folderApiRepository.getAssetsForPath('/');
+      return result;
+    } catch (e, stack) {
+      _log.severe(
+        "Failed to fetch assets for folder ${folder is RecursiveFolder ? folder.name : "root"}",
+        e,
+        stack,
+      );
+      return [];
+    }
+  }
+}
diff --git a/mobile/lib/widgets/common/immich_app_bar.dart b/mobile/lib/widgets/common/immich_app_bar.dart
index 7f97944cd5..7a42606797 100644
--- a/mobile/lib/widgets/common/immich_app_bar.dart
+++ b/mobile/lib/widgets/common/immich_app_bar.dart
@@ -10,7 +10,6 @@ import 'package:immich_mobile/models/backup/backup_state.model.dart';
 import 'package:immich_mobile/models/server_info/server_info.model.dart';
 import 'package:immich_mobile/providers/backup/backup.provider.dart';
 import 'package:immich_mobile/providers/immich_logo_provider.dart';
-import 'package:immich_mobile/providers/infrastructure/sync_stream.provider.dart';
 import 'package:immich_mobile/providers/server_info.provider.dart';
 import 'package:immich_mobile/routing/router.dart';
 import 'package:immich_mobile/widgets/common/app_bar_dialog/app_bar_dialog.dart';
@@ -186,12 +185,6 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
         },
       ),
       actions: [
-        IconButton(
-          onPressed: () {
-            ref.read(syncStreamServiceProvider).syncUsers();
-          },
-          icon: const Icon(Icons.sync),
-        ),
         if (actions != null)
           ...actions!.map(
             (action) => Padding(
diff --git a/mobile/openapi/lib/api/activities_api.dart b/mobile/openapi/lib/api/activities_api.dart
index e5075eee16..5c83ba7db9 100644
--- a/mobile/openapi/lib/api/activities_api.dart
+++ b/mobile/openapi/lib/api/activities_api.dart
@@ -22,7 +22,7 @@ class ActivitiesApi {
   /// * [ActivityCreateDto] activityCreateDto (required):
   Future<Response> createActivityWithHttpInfo(ActivityCreateDto activityCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/activities';
+    final apiPath = r'/activities';
 
     // ignore: prefer_final_locals
     Object? postBody = activityCreateDto;
@@ -35,7 +35,7 @@ class ActivitiesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class ActivitiesApi {
   /// * [String] id (required):
   Future<Response> deleteActivityWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/activities/{id}'
+    final apiPath = r'/activities/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -83,7 +83,7 @@ class ActivitiesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -117,7 +117,7 @@ class ActivitiesApi {
   /// * [String] userId:
   Future<Response> getActivitiesWithHttpInfo(String albumId, { String? assetId, ReactionLevel? level, ReactionType? type, String? userId, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/activities';
+    final apiPath = r'/activities';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -144,7 +144,7 @@ class ActivitiesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -191,7 +191,7 @@ class ActivitiesApi {
   /// * [String] assetId:
   Future<Response> getActivityStatisticsWithHttpInfo(String albumId, { String? assetId, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/activities/statistics';
+    final apiPath = r'/activities/statistics';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -209,7 +209,7 @@ class ActivitiesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/albums_api.dart b/mobile/openapi/lib/api/albums_api.dart
index eb2bb7c0bd..a8c518ace2 100644
--- a/mobile/openapi/lib/api/albums_api.dart
+++ b/mobile/openapi/lib/api/albums_api.dart
@@ -26,7 +26,7 @@ class AlbumsApi {
   /// * [String] key:
   Future<Response> addAssetsToAlbumWithHttpInfo(String id, BulkIdsDto bulkIdsDto, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}/assets'
+    final apiPath = r'/albums/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -44,7 +44,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -87,7 +87,7 @@ class AlbumsApi {
   /// * [AddUsersDto] addUsersDto (required):
   Future<Response> addUsersToAlbumWithHttpInfo(String id, AddUsersDto addUsersDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}/users'
+    final apiPath = r'/albums/{id}/users'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -101,7 +101,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -137,7 +137,7 @@ class AlbumsApi {
   /// * [CreateAlbumDto] createAlbumDto (required):
   Future<Response> createAlbumWithHttpInfo(CreateAlbumDto createAlbumDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums';
+    final apiPath = r'/albums';
 
     // ignore: prefer_final_locals
     Object? postBody = createAlbumDto;
@@ -150,7 +150,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -184,7 +184,7 @@ class AlbumsApi {
   /// * [String] id (required):
   Future<Response> deleteAlbumWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}'
+    final apiPath = r'/albums/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -198,7 +198,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -228,7 +228,7 @@ class AlbumsApi {
   /// * [bool] withoutAssets:
   Future<Response> getAlbumInfoWithHttpInfo(String id, { String? key, bool? withoutAssets, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}'
+    final apiPath = r'/albums/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -249,7 +249,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -284,7 +284,7 @@ class AlbumsApi {
   /// Performs an HTTP 'GET /albums/statistics' operation and returns the [Response].
   Future<Response> getAlbumStatisticsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/statistics';
+    final apiPath = r'/albums/statistics';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -297,7 +297,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -331,7 +331,7 @@ class AlbumsApi {
   /// * [bool] shared:
   Future<Response> getAllAlbumsWithHttpInfo({ String? assetId, bool? shared, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums';
+    final apiPath = r'/albums';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -351,7 +351,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -393,7 +393,7 @@ class AlbumsApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> removeAssetFromAlbumWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}/assets'
+    final apiPath = r'/albums/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -407,7 +407,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -448,7 +448,7 @@ class AlbumsApi {
   /// * [String] userId (required):
   Future<Response> removeUserFromAlbumWithHttpInfo(String id, String userId,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}/user/{userId}'
+    final apiPath = r'/albums/{id}/user/{userId}'
       .replaceAll('{id}', id)
       .replaceAll('{userId}', userId);
 
@@ -463,7 +463,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -493,7 +493,7 @@ class AlbumsApi {
   /// * [UpdateAlbumDto] updateAlbumDto (required):
   Future<Response> updateAlbumInfoWithHttpInfo(String id, UpdateAlbumDto updateAlbumDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}'
+    final apiPath = r'/albums/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -507,7 +507,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PATCH',
       queryParams,
       postBody,
@@ -547,7 +547,7 @@ class AlbumsApi {
   /// * [UpdateAlbumUserDto] updateAlbumUserDto (required):
   Future<Response> updateAlbumUserWithHttpInfo(String id, String userId, UpdateAlbumUserDto updateAlbumUserDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/albums/{id}/user/{userId}'
+    final apiPath = r'/albums/{id}/user/{userId}'
       .replaceAll('{id}', id)
       .replaceAll('{userId}', userId);
 
@@ -562,7 +562,7 @@ class AlbumsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/api_keys_api.dart b/mobile/openapi/lib/api/api_keys_api.dart
index 2e7757f20a..cf54ac5c04 100644
--- a/mobile/openapi/lib/api/api_keys_api.dart
+++ b/mobile/openapi/lib/api/api_keys_api.dart
@@ -22,7 +22,7 @@ class APIKeysApi {
   /// * [APIKeyCreateDto] aPIKeyCreateDto (required):
   Future<Response> createApiKeyWithHttpInfo(APIKeyCreateDto aPIKeyCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/api-keys';
+    final apiPath = r'/api-keys';
 
     // ignore: prefer_final_locals
     Object? postBody = aPIKeyCreateDto;
@@ -35,7 +35,7 @@ class APIKeysApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class APIKeysApi {
   /// * [String] id (required):
   Future<Response> deleteApiKeyWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/api-keys/{id}'
+    final apiPath = r'/api-keys/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -83,7 +83,7 @@ class APIKeysApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -109,7 +109,7 @@ class APIKeysApi {
   /// * [String] id (required):
   Future<Response> getApiKeyWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/api-keys/{id}'
+    final apiPath = r'/api-keys/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -123,7 +123,7 @@ class APIKeysApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -154,7 +154,7 @@ class APIKeysApi {
   /// Performs an HTTP 'GET /api-keys' operation and returns the [Response].
   Future<Response> getApiKeysWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/api-keys';
+    final apiPath = r'/api-keys';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -167,7 +167,7 @@ class APIKeysApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -203,7 +203,7 @@ class APIKeysApi {
   /// * [APIKeyUpdateDto] aPIKeyUpdateDto (required):
   Future<Response> updateApiKeyWithHttpInfo(String id, APIKeyUpdateDto aPIKeyUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/api-keys/{id}'
+    final apiPath = r'/api-keys/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -217,7 +217,7 @@ class APIKeysApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/assets_api.dart b/mobile/openapi/lib/api/assets_api.dart
index e7272d094c..f52c70b37f 100644
--- a/mobile/openapi/lib/api/assets_api.dart
+++ b/mobile/openapi/lib/api/assets_api.dart
@@ -27,7 +27,7 @@ class AssetsApi {
   /// * [AssetBulkUploadCheckDto] assetBulkUploadCheckDto (required):
   Future<Response> checkBulkUploadWithHttpInfo(AssetBulkUploadCheckDto assetBulkUploadCheckDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/bulk-upload-check';
+    final apiPath = r'/assets/bulk-upload-check';
 
     // ignore: prefer_final_locals
     Object? postBody = assetBulkUploadCheckDto;
@@ -40,7 +40,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -83,7 +83,7 @@ class AssetsApi {
   /// * [CheckExistingAssetsDto] checkExistingAssetsDto (required):
   Future<Response> checkExistingAssetsWithHttpInfo(CheckExistingAssetsDto checkExistingAssetsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/exist';
+    final apiPath = r'/assets/exist';
 
     // ignore: prefer_final_locals
     Object? postBody = checkExistingAssetsDto;
@@ -96,7 +96,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -134,7 +134,7 @@ class AssetsApi {
   /// * [AssetBulkDeleteDto] assetBulkDeleteDto (required):
   Future<Response> deleteAssetsWithHttpInfo(AssetBulkDeleteDto assetBulkDeleteDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets';
+    final apiPath = r'/assets';
 
     // ignore: prefer_final_locals
     Object? postBody = assetBulkDeleteDto;
@@ -147,7 +147,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -175,7 +175,7 @@ class AssetsApi {
   /// * [String] key:
   Future<Response> downloadAssetWithHttpInfo(String id, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/{id}/original'
+    final apiPath = r'/assets/{id}/original'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -193,7 +193,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -234,7 +234,7 @@ class AssetsApi {
   /// * [String] deviceId (required):
   Future<Response> getAllUserAssetsByDeviceIdWithHttpInfo(String deviceId,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/device/{deviceId}'
+    final apiPath = r'/assets/device/{deviceId}'
       .replaceAll('{deviceId}', deviceId);
 
     // ignore: prefer_final_locals
@@ -248,7 +248,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -291,7 +291,7 @@ class AssetsApi {
   /// * [String] key:
   Future<Response> getAssetInfoWithHttpInfo(String id, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/{id}'
+    final apiPath = r'/assets/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -309,7 +309,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -349,7 +349,7 @@ class AssetsApi {
   /// * [bool] isTrashed:
   Future<Response> getAssetStatisticsWithHttpInfo({ bool? isArchived, bool? isFavorite, bool? isTrashed, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/statistics';
+    final apiPath = r'/assets/statistics';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -372,7 +372,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -412,7 +412,7 @@ class AssetsApi {
   /// * [int] month (required):
   Future<Response> getMemoryLaneWithHttpInfo(int day, int month,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/memory-lane';
+    final apiPath = r'/assets/memory-lane';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -428,7 +428,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -470,7 +470,7 @@ class AssetsApi {
   /// * [num] count:
   Future<Response> getRandomWithHttpInfo({ num? count, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/random';
+    final apiPath = r'/assets/random';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -487,7 +487,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -528,7 +528,7 @@ class AssetsApi {
   /// * [String] key:
   Future<Response> playAssetVideoWithHttpInfo(String id, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/{id}/video/playback'
+    final apiPath = r'/assets/{id}/video/playback'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -546,7 +546,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -601,7 +601,7 @@ class AssetsApi {
   /// * [String] duration:
   Future<Response> replaceAssetWithHttpInfo(String id, MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? duration, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/{id}/original'
+    final apiPath = r'/assets/{id}/original'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -618,7 +618,7 @@ class AssetsApi {
     const contentTypes = <String>['multipart/form-data'];
 
     bool hasFields = false;
-    final mp = MultipartRequest('PUT', Uri.parse(path));
+    final mp = MultipartRequest('PUT', Uri.parse(apiPath));
     if (assetData != null) {
       hasFields = true;
       mp.fields[r'assetData'] = assetData.field;
@@ -649,7 +649,7 @@ class AssetsApi {
     }
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -701,7 +701,7 @@ class AssetsApi {
   /// * [AssetJobsDto] assetJobsDto (required):
   Future<Response> runAssetJobsWithHttpInfo(AssetJobsDto assetJobsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/jobs';
+    final apiPath = r'/assets/jobs';
 
     // ignore: prefer_final_locals
     Object? postBody = assetJobsDto;
@@ -714,7 +714,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -742,7 +742,7 @@ class AssetsApi {
   /// * [UpdateAssetDto] updateAssetDto (required):
   Future<Response> updateAssetWithHttpInfo(String id, UpdateAssetDto updateAssetDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/{id}'
+    final apiPath = r'/assets/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -756,7 +756,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -792,7 +792,7 @@ class AssetsApi {
   /// * [AssetBulkUpdateDto] assetBulkUpdateDto (required):
   Future<Response> updateAssetsWithHttpInfo(AssetBulkUpdateDto assetBulkUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets';
+    final apiPath = r'/assets';
 
     // ignore: prefer_final_locals
     Object? postBody = assetBulkUpdateDto;
@@ -805,7 +805,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -856,7 +856,7 @@ class AssetsApi {
   /// * [MultipartFile] sidecarData:
   Future<Response> uploadAssetWithHttpInfo(MultipartFile assetData, String deviceAssetId, String deviceId, DateTime fileCreatedAt, DateTime fileModifiedAt, { String? key, String? xImmichChecksum, String? duration, bool? isArchived, bool? isFavorite, bool? isVisible, String? livePhotoVideoId, MultipartFile? sidecarData, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets';
+    final apiPath = r'/assets';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -876,7 +876,7 @@ class AssetsApi {
     const contentTypes = <String>['multipart/form-data'];
 
     bool hasFields = false;
-    final mp = MultipartRequest('POST', Uri.parse(path));
+    final mp = MultipartRequest('POST', Uri.parse(apiPath));
     if (assetData != null) {
       hasFields = true;
       mp.fields[r'assetData'] = assetData.field;
@@ -928,7 +928,7 @@ class AssetsApi {
     }
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -991,7 +991,7 @@ class AssetsApi {
   /// * [AssetMediaSize] size:
   Future<Response> viewAssetWithHttpInfo(String id, { String? key, AssetMediaSize? size, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/{id}/thumbnail'
+    final apiPath = r'/assets/{id}/thumbnail'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -1012,7 +1012,7 @@ class AssetsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/authentication_api.dart b/mobile/openapi/lib/api/authentication_api.dart
index cb81867425..bf987f441e 100644
--- a/mobile/openapi/lib/api/authentication_api.dart
+++ b/mobile/openapi/lib/api/authentication_api.dart
@@ -22,7 +22,7 @@ class AuthenticationApi {
   /// * [ChangePasswordDto] changePasswordDto (required):
   Future<Response> changePasswordWithHttpInfo(ChangePasswordDto changePasswordDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/auth/change-password';
+    final apiPath = r'/auth/change-password';
 
     // ignore: prefer_final_locals
     Object? postBody = changePasswordDto;
@@ -35,7 +35,7 @@ class AuthenticationApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class AuthenticationApi {
   /// * [LoginCredentialDto] loginCredentialDto (required):
   Future<Response> loginWithHttpInfo(LoginCredentialDto loginCredentialDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/auth/login';
+    final apiPath = r'/auth/login';
 
     // ignore: prefer_final_locals
     Object? postBody = loginCredentialDto;
@@ -82,7 +82,7 @@ class AuthenticationApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -113,7 +113,7 @@ class AuthenticationApi {
   /// Performs an HTTP 'POST /auth/logout' operation and returns the [Response].
   Future<Response> logoutWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/auth/logout';
+    final apiPath = r'/auth/logout';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -126,7 +126,7 @@ class AuthenticationApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -157,7 +157,7 @@ class AuthenticationApi {
   /// * [SignUpDto] signUpDto (required):
   Future<Response> signUpAdminWithHttpInfo(SignUpDto signUpDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/auth/admin-sign-up';
+    final apiPath = r'/auth/admin-sign-up';
 
     // ignore: prefer_final_locals
     Object? postBody = signUpDto;
@@ -170,7 +170,7 @@ class AuthenticationApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -201,7 +201,7 @@ class AuthenticationApi {
   /// Performs an HTTP 'POST /auth/validateToken' operation and returns the [Response].
   Future<Response> validateAccessTokenWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/auth/validateToken';
+    final apiPath = r'/auth/validateToken';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -214,7 +214,7 @@ class AuthenticationApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/deprecated_api.dart b/mobile/openapi/lib/api/deprecated_api.dart
index 30e35b451c..7aa9662c23 100644
--- a/mobile/openapi/lib/api/deprecated_api.dart
+++ b/mobile/openapi/lib/api/deprecated_api.dart
@@ -25,7 +25,7 @@ class DeprecatedApi {
   /// * [num] count:
   Future<Response> getRandomWithHttpInfo({ num? count, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/assets/random';
+    final apiPath = r'/assets/random';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -42,7 +42,7 @@ class DeprecatedApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/download_api.dart b/mobile/openapi/lib/api/download_api.dart
index b89f340ec7..3b11c2f630 100644
--- a/mobile/openapi/lib/api/download_api.dart
+++ b/mobile/openapi/lib/api/download_api.dart
@@ -24,7 +24,7 @@ class DownloadApi {
   /// * [String] key:
   Future<Response> downloadArchiveWithHttpInfo(AssetIdsDto assetIdsDto, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/download/archive';
+    final apiPath = r'/download/archive';
 
     // ignore: prefer_final_locals
     Object? postBody = assetIdsDto;
@@ -41,7 +41,7 @@ class DownloadApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -79,7 +79,7 @@ class DownloadApi {
   /// * [String] key:
   Future<Response> getDownloadInfoWithHttpInfo(DownloadInfoDto downloadInfoDto, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/download/info';
+    final apiPath = r'/download/info';
 
     // ignore: prefer_final_locals
     Object? postBody = downloadInfoDto;
@@ -96,7 +96,7 @@ class DownloadApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/duplicates_api.dart b/mobile/openapi/lib/api/duplicates_api.dart
index b82290e47b..715c6d6112 100644
--- a/mobile/openapi/lib/api/duplicates_api.dart
+++ b/mobile/openapi/lib/api/duplicates_api.dart
@@ -19,7 +19,7 @@ class DuplicatesApi {
   /// Performs an HTTP 'GET /duplicates' operation and returns the [Response].
   Future<Response> getAssetDuplicatesWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/duplicates';
+    final apiPath = r'/duplicates';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class DuplicatesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/faces_api.dart b/mobile/openapi/lib/api/faces_api.dart
index e92ee93e42..44e3d53f8e 100644
--- a/mobile/openapi/lib/api/faces_api.dart
+++ b/mobile/openapi/lib/api/faces_api.dart
@@ -22,7 +22,7 @@ class FacesApi {
   /// * [AssetFaceCreateDto] assetFaceCreateDto (required):
   Future<Response> createFaceWithHttpInfo(AssetFaceCreateDto assetFaceCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/faces';
+    final apiPath = r'/faces';
 
     // ignore: prefer_final_locals
     Object? postBody = assetFaceCreateDto;
@@ -35,7 +35,7 @@ class FacesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -63,7 +63,7 @@ class FacesApi {
   /// * [AssetFaceDeleteDto] assetFaceDeleteDto (required):
   Future<Response> deleteFaceWithHttpInfo(String id, AssetFaceDeleteDto assetFaceDeleteDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/faces/{id}'
+    final apiPath = r'/faces/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -77,7 +77,7 @@ class FacesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -105,7 +105,7 @@ class FacesApi {
   /// * [String] id (required):
   Future<Response> getFacesWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/faces';
+    final apiPath = r'/faces';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -120,7 +120,7 @@ class FacesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -159,7 +159,7 @@ class FacesApi {
   /// * [FaceDto] faceDto (required):
   Future<Response> reassignFacesByIdWithHttpInfo(String id, FaceDto faceDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/faces/{id}'
+    final apiPath = r'/faces/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -173,7 +173,7 @@ class FacesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/file_reports_api.dart b/mobile/openapi/lib/api/file_reports_api.dart
index 5eab91576e..73b3feaedb 100644
--- a/mobile/openapi/lib/api/file_reports_api.dart
+++ b/mobile/openapi/lib/api/file_reports_api.dart
@@ -22,7 +22,7 @@ class FileReportsApi {
   /// * [FileReportFixDto] fileReportFixDto (required):
   Future<Response> fixAuditFilesWithHttpInfo(FileReportFixDto fileReportFixDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/reports/fix';
+    final apiPath = r'/reports/fix';
 
     // ignore: prefer_final_locals
     Object? postBody = fileReportFixDto;
@@ -35,7 +35,7 @@ class FileReportsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -58,7 +58,7 @@ class FileReportsApi {
   /// Performs an HTTP 'GET /reports' operation and returns the [Response].
   Future<Response> getAuditFilesWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/reports';
+    final apiPath = r'/reports';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -71,7 +71,7 @@ class FileReportsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -102,7 +102,7 @@ class FileReportsApi {
   /// * [FileChecksumDto] fileChecksumDto (required):
   Future<Response> getFileChecksumsWithHttpInfo(FileChecksumDto fileChecksumDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/reports/checksum';
+    final apiPath = r'/reports/checksum';
 
     // ignore: prefer_final_locals
     Object? postBody = fileChecksumDto;
@@ -115,7 +115,7 @@ class FileReportsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/jobs_api.dart b/mobile/openapi/lib/api/jobs_api.dart
index 78afc15c93..182bb14e4f 100644
--- a/mobile/openapi/lib/api/jobs_api.dart
+++ b/mobile/openapi/lib/api/jobs_api.dart
@@ -22,7 +22,7 @@ class JobsApi {
   /// * [JobCreateDto] jobCreateDto (required):
   Future<Response> createJobWithHttpInfo(JobCreateDto jobCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/jobs';
+    final apiPath = r'/jobs';
 
     // ignore: prefer_final_locals
     Object? postBody = jobCreateDto;
@@ -35,7 +35,7 @@ class JobsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -58,7 +58,7 @@ class JobsApi {
   /// Performs an HTTP 'GET /jobs' operation and returns the [Response].
   Future<Response> getAllJobsStatusWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/jobs';
+    final apiPath = r'/jobs';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -71,7 +71,7 @@ class JobsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -104,7 +104,7 @@ class JobsApi {
   /// * [JobCommandDto] jobCommandDto (required):
   Future<Response> sendJobCommandWithHttpInfo(JobName id, JobCommandDto jobCommandDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/jobs/{id}'
+    final apiPath = r'/jobs/{id}'
       .replaceAll('{id}', id.toString());
 
     // ignore: prefer_final_locals
@@ -118,7 +118,7 @@ class JobsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/libraries_api.dart b/mobile/openapi/lib/api/libraries_api.dart
index 36d98d9a88..86acce76b4 100644
--- a/mobile/openapi/lib/api/libraries_api.dart
+++ b/mobile/openapi/lib/api/libraries_api.dart
@@ -22,7 +22,7 @@ class LibrariesApi {
   /// * [CreateLibraryDto] createLibraryDto (required):
   Future<Response> createLibraryWithHttpInfo(CreateLibraryDto createLibraryDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries';
+    final apiPath = r'/libraries';
 
     // ignore: prefer_final_locals
     Object? postBody = createLibraryDto;
@@ -35,7 +35,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class LibrariesApi {
   /// * [String] id (required):
   Future<Response> deleteLibraryWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries/{id}'
+    final apiPath = r'/libraries/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -83,7 +83,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -106,7 +106,7 @@ class LibrariesApi {
   /// Performs an HTTP 'GET /libraries' operation and returns the [Response].
   Future<Response> getAllLibrariesWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries';
+    final apiPath = r'/libraries';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -119,7 +119,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -153,7 +153,7 @@ class LibrariesApi {
   /// * [String] id (required):
   Future<Response> getLibraryWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries/{id}'
+    final apiPath = r'/libraries/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -167,7 +167,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -201,7 +201,7 @@ class LibrariesApi {
   /// * [String] id (required):
   Future<Response> getLibraryStatisticsWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries/{id}/statistics'
+    final apiPath = r'/libraries/{id}/statistics'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -215,7 +215,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -249,7 +249,7 @@ class LibrariesApi {
   /// * [String] id (required):
   Future<Response> scanLibraryWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries/{id}/scan'
+    final apiPath = r'/libraries/{id}/scan'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -263,7 +263,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -291,7 +291,7 @@ class LibrariesApi {
   /// * [UpdateLibraryDto] updateLibraryDto (required):
   Future<Response> updateLibraryWithHttpInfo(String id, UpdateLibraryDto updateLibraryDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries/{id}'
+    final apiPath = r'/libraries/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -305,7 +305,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -343,7 +343,7 @@ class LibrariesApi {
   /// * [ValidateLibraryDto] validateLibraryDto (required):
   Future<Response> validateWithHttpInfo(String id, ValidateLibraryDto validateLibraryDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/libraries/{id}/validate'
+    final apiPath = r'/libraries/{id}/validate'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -357,7 +357,7 @@ class LibrariesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/map_api.dart b/mobile/openapi/lib/api/map_api.dart
index 9644fbfc5c..ffe72df453 100644
--- a/mobile/openapi/lib/api/map_api.dart
+++ b/mobile/openapi/lib/api/map_api.dart
@@ -32,7 +32,7 @@ class MapApi {
   /// * [bool] withSharedAlbums:
   Future<Response> getMapMarkersWithHttpInfo({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, bool? withSharedAlbums, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/map/markers';
+    final apiPath = r'/map/markers';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -64,7 +64,7 @@ class MapApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -113,7 +113,7 @@ class MapApi {
   /// * [double] lon (required):
   Future<Response> reverseGeocodeWithHttpInfo(double lat, double lon,) async {
     // ignore: prefer_const_declarations
-    final path = r'/map/reverse-geocode';
+    final apiPath = r'/map/reverse-geocode';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -129,7 +129,7 @@ class MapApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/memories_api.dart b/mobile/openapi/lib/api/memories_api.dart
index c5b04a7c7c..88897d3038 100644
--- a/mobile/openapi/lib/api/memories_api.dart
+++ b/mobile/openapi/lib/api/memories_api.dart
@@ -24,7 +24,7 @@ class MemoriesApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> addMemoryAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories/{id}/assets'
+    final apiPath = r'/memories/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -38,7 +38,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -77,7 +77,7 @@ class MemoriesApi {
   /// * [MemoryCreateDto] memoryCreateDto (required):
   Future<Response> createMemoryWithHttpInfo(MemoryCreateDto memoryCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories';
+    final apiPath = r'/memories';
 
     // ignore: prefer_final_locals
     Object? postBody = memoryCreateDto;
@@ -90,7 +90,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -124,7 +124,7 @@ class MemoriesApi {
   /// * [String] id (required):
   Future<Response> deleteMemoryWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories/{id}'
+    final apiPath = r'/memories/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -138,7 +138,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -164,7 +164,7 @@ class MemoriesApi {
   /// * [String] id (required):
   Future<Response> getMemoryWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories/{id}'
+    final apiPath = r'/memories/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -178,7 +178,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -214,7 +214,7 @@ class MemoriesApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> removeMemoryAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories/{id}/assets'
+    final apiPath = r'/memories/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -228,7 +228,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -273,7 +273,7 @@ class MemoriesApi {
   /// * [MemoryType] type:
   Future<Response> searchMemoriesWithHttpInfo({ DateTime? for_, bool? isSaved, bool? isTrashed, MemoryType? type, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories';
+    final apiPath = r'/memories';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -299,7 +299,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -344,7 +344,7 @@ class MemoriesApi {
   /// * [MemoryUpdateDto] memoryUpdateDto (required):
   Future<Response> updateMemoryWithHttpInfo(String id, MemoryUpdateDto memoryUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/memories/{id}'
+    final apiPath = r'/memories/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -358,7 +358,7 @@ class MemoriesApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/notifications_api.dart b/mobile/openapi/lib/api/notifications_api.dart
index 323fbcc3d6..518a1baa4a 100644
--- a/mobile/openapi/lib/api/notifications_api.dart
+++ b/mobile/openapi/lib/api/notifications_api.dart
@@ -24,7 +24,7 @@ class NotificationsApi {
   /// * [TemplateDto] templateDto (required):
   Future<Response> getNotificationTemplateWithHttpInfo(String name, TemplateDto templateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/notifications/templates/{name}'
+    final apiPath = r'/notifications/templates/{name}'
       .replaceAll('{name}', name);
 
     // ignore: prefer_final_locals
@@ -38,7 +38,7 @@ class NotificationsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -74,7 +74,7 @@ class NotificationsApi {
   /// * [SystemConfigSmtpDto] systemConfigSmtpDto (required):
   Future<Response> sendTestEmailWithHttpInfo(SystemConfigSmtpDto systemConfigSmtpDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/notifications/test-email';
+    final apiPath = r'/notifications/test-email';
 
     // ignore: prefer_final_locals
     Object? postBody = systemConfigSmtpDto;
@@ -87,7 +87,7 @@ class NotificationsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/o_auth_api.dart b/mobile/openapi/lib/api/o_auth_api.dart
index aafcb28461..9f16e37c70 100644
--- a/mobile/openapi/lib/api/o_auth_api.dart
+++ b/mobile/openapi/lib/api/o_auth_api.dart
@@ -22,7 +22,7 @@ class OAuthApi {
   /// * [OAuthCallbackDto] oAuthCallbackDto (required):
   Future<Response> finishOAuthWithHttpInfo(OAuthCallbackDto oAuthCallbackDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/oauth/callback';
+    final apiPath = r'/oauth/callback';
 
     // ignore: prefer_final_locals
     Object? postBody = oAuthCallbackDto;
@@ -35,7 +35,7 @@ class OAuthApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class OAuthApi {
   /// * [OAuthCallbackDto] oAuthCallbackDto (required):
   Future<Response> linkOAuthAccountWithHttpInfo(OAuthCallbackDto oAuthCallbackDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/oauth/link';
+    final apiPath = r'/oauth/link';
 
     // ignore: prefer_final_locals
     Object? postBody = oAuthCallbackDto;
@@ -82,7 +82,7 @@ class OAuthApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -113,7 +113,7 @@ class OAuthApi {
   /// Performs an HTTP 'GET /oauth/mobile-redirect' operation and returns the [Response].
   Future<Response> redirectOAuthToMobileWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/oauth/mobile-redirect';
+    final apiPath = r'/oauth/mobile-redirect';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -126,7 +126,7 @@ class OAuthApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -149,7 +149,7 @@ class OAuthApi {
   /// * [OAuthConfigDto] oAuthConfigDto (required):
   Future<Response> startOAuthWithHttpInfo(OAuthConfigDto oAuthConfigDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/oauth/authorize';
+    final apiPath = r'/oauth/authorize';
 
     // ignore: prefer_final_locals
     Object? postBody = oAuthConfigDto;
@@ -162,7 +162,7 @@ class OAuthApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -193,7 +193,7 @@ class OAuthApi {
   /// Performs an HTTP 'POST /oauth/unlink' operation and returns the [Response].
   Future<Response> unlinkOAuthAccountWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/oauth/unlink';
+    final apiPath = r'/oauth/unlink';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -206,7 +206,7 @@ class OAuthApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/partners_api.dart b/mobile/openapi/lib/api/partners_api.dart
index ac0d03054a..9f10ea4d1e 100644
--- a/mobile/openapi/lib/api/partners_api.dart
+++ b/mobile/openapi/lib/api/partners_api.dart
@@ -22,7 +22,7 @@ class PartnersApi {
   /// * [String] id (required):
   Future<Response> createPartnerWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/partners/{id}'
+    final apiPath = r'/partners/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -36,7 +36,7 @@ class PartnersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -70,7 +70,7 @@ class PartnersApi {
   /// * [PartnerDirection] direction (required):
   Future<Response> getPartnersWithHttpInfo(PartnerDirection direction,) async {
     // ignore: prefer_const_declarations
-    final path = r'/partners';
+    final apiPath = r'/partners';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -85,7 +85,7 @@ class PartnersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -122,7 +122,7 @@ class PartnersApi {
   /// * [String] id (required):
   Future<Response> removePartnerWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/partners/{id}'
+    final apiPath = r'/partners/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -136,7 +136,7 @@ class PartnersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -164,7 +164,7 @@ class PartnersApi {
   /// * [UpdatePartnerDto] updatePartnerDto (required):
   Future<Response> updatePartnerWithHttpInfo(String id, UpdatePartnerDto updatePartnerDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/partners/{id}'
+    final apiPath = r'/partners/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -178,7 +178,7 @@ class PartnersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/people_api.dart b/mobile/openapi/lib/api/people_api.dart
index 92bd0fdeea..1cdb878852 100644
--- a/mobile/openapi/lib/api/people_api.dart
+++ b/mobile/openapi/lib/api/people_api.dart
@@ -22,7 +22,7 @@ class PeopleApi {
   /// * [PersonCreateDto] personCreateDto (required):
   Future<Response> createPersonWithHttpInfo(PersonCreateDto personCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people';
+    final apiPath = r'/people';
 
     // ignore: prefer_final_locals
     Object? postBody = personCreateDto;
@@ -35,7 +35,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -79,7 +79,7 @@ class PeopleApi {
   /// * [bool] withHidden:
   Future<Response> getAllPeopleWithHttpInfo({ String? closestAssetId, String? closestPersonId, num? page, num? size, bool? withHidden, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/people';
+    final apiPath = r'/people';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -108,7 +108,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -152,7 +152,7 @@ class PeopleApi {
   /// * [String] id (required):
   Future<Response> getPersonWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people/{id}'
+    final apiPath = r'/people/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -166,7 +166,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -200,7 +200,7 @@ class PeopleApi {
   /// * [String] id (required):
   Future<Response> getPersonStatisticsWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people/{id}/statistics'
+    final apiPath = r'/people/{id}/statistics'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -214,7 +214,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -248,7 +248,7 @@ class PeopleApi {
   /// * [String] id (required):
   Future<Response> getPersonThumbnailWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people/{id}/thumbnail'
+    final apiPath = r'/people/{id}/thumbnail'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -262,7 +262,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -298,7 +298,7 @@ class PeopleApi {
   /// * [MergePersonDto] mergePersonDto (required):
   Future<Response> mergePersonWithHttpInfo(String id, MergePersonDto mergePersonDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people/{id}/merge'
+    final apiPath = r'/people/{id}/merge'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -312,7 +312,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -353,7 +353,7 @@ class PeopleApi {
   /// * [AssetFaceUpdateDto] assetFaceUpdateDto (required):
   Future<Response> reassignFacesWithHttpInfo(String id, AssetFaceUpdateDto assetFaceUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people/{id}/reassign'
+    final apiPath = r'/people/{id}/reassign'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -367,7 +367,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -406,7 +406,7 @@ class PeopleApi {
   /// * [PeopleUpdateDto] peopleUpdateDto (required):
   Future<Response> updatePeopleWithHttpInfo(PeopleUpdateDto peopleUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people';
+    final apiPath = r'/people';
 
     // ignore: prefer_final_locals
     Object? postBody = peopleUpdateDto;
@@ -419,7 +419,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -458,7 +458,7 @@ class PeopleApi {
   /// * [PersonUpdateDto] personUpdateDto (required):
   Future<Response> updatePersonWithHttpInfo(String id, PersonUpdateDto personUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/people/{id}'
+    final apiPath = r'/people/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -472,7 +472,7 @@ class PeopleApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart
index 70af3ab0a3..632107ff79 100644
--- a/mobile/openapi/lib/api/search_api.dart
+++ b/mobile/openapi/lib/api/search_api.dart
@@ -19,7 +19,7 @@ class SearchApi {
   /// Performs an HTTP 'GET /search/cities' operation and returns the [Response].
   Future<Response> getAssetsByCityWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/search/cities';
+    final apiPath = r'/search/cities';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -63,7 +63,7 @@ class SearchApi {
   /// Performs an HTTP 'GET /search/explore' operation and returns the [Response].
   Future<Response> getExploreDataWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/search/explore';
+    final apiPath = r'/search/explore';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -76,7 +76,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -121,7 +121,7 @@ class SearchApi {
   /// * [String] state:
   Future<Response> getSearchSuggestionsWithHttpInfo(SearchSuggestionType type, { String? country, bool? includeNull, String? make, String? model, String? state, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/search/suggestions';
+    final apiPath = r'/search/suggestions';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -151,7 +151,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -199,7 +199,7 @@ class SearchApi {
   /// * [MetadataSearchDto] metadataSearchDto (required):
   Future<Response> searchAssetsWithHttpInfo(MetadataSearchDto metadataSearchDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/search/metadata';
+    final apiPath = r'/search/metadata';
 
     // ignore: prefer_final_locals
     Object? postBody = metadataSearchDto;
@@ -212,7 +212,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -248,7 +248,7 @@ class SearchApi {
   /// * [bool] withHidden:
   Future<Response> searchPersonWithHttpInfo(String name, { bool? withHidden, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/search/person';
+    final apiPath = r'/search/person';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -266,7 +266,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -305,7 +305,7 @@ class SearchApi {
   /// * [String] name (required):
   Future<Response> searchPlacesWithHttpInfo(String name,) async {
     // ignore: prefer_const_declarations
-    final path = r'/search/places';
+    final apiPath = r'/search/places';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -320,7 +320,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -357,7 +357,7 @@ class SearchApi {
   /// * [RandomSearchDto] randomSearchDto (required):
   Future<Response> searchRandomWithHttpInfo(RandomSearchDto randomSearchDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/search/random';
+    final apiPath = r'/search/random';
 
     // ignore: prefer_final_locals
     Object? postBody = randomSearchDto;
@@ -370,7 +370,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -407,7 +407,7 @@ class SearchApi {
   /// * [SmartSearchDto] smartSearchDto (required):
   Future<Response> searchSmartWithHttpInfo(SmartSearchDto smartSearchDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/search/smart';
+    final apiPath = r'/search/smart';
 
     // ignore: prefer_final_locals
     Object? postBody = smartSearchDto;
@@ -420,7 +420,7 @@ class SearchApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/server_api.dart b/mobile/openapi/lib/api/server_api.dart
index 7a832ad61a..629949db32 100644
--- a/mobile/openapi/lib/api/server_api.dart
+++ b/mobile/openapi/lib/api/server_api.dart
@@ -19,7 +19,7 @@ class ServerApi {
   /// Performs an HTTP 'DELETE /server/license' operation and returns the [Response].
   Future<Response> deleteServerLicenseWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/license';
+    final apiPath = r'/server/license';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -52,7 +52,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/about' operation and returns the [Response].
   Future<Response> getAboutInfoWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/about';
+    final apiPath = r'/server/about';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -65,7 +65,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -93,7 +93,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/config' operation and returns the [Response].
   Future<Response> getServerConfigWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/config';
+    final apiPath = r'/server/config';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -106,7 +106,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -134,7 +134,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/features' operation and returns the [Response].
   Future<Response> getServerFeaturesWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/features';
+    final apiPath = r'/server/features';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -147,7 +147,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -175,7 +175,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/license' operation and returns the [Response].
   Future<Response> getServerLicenseWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/license';
+    final apiPath = r'/server/license';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -188,7 +188,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -216,7 +216,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/statistics' operation and returns the [Response].
   Future<Response> getServerStatisticsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/statistics';
+    final apiPath = r'/server/statistics';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -229,7 +229,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -257,7 +257,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/version' operation and returns the [Response].
   Future<Response> getServerVersionWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/version';
+    final apiPath = r'/server/version';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -270,7 +270,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -298,7 +298,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/storage' operation and returns the [Response].
   Future<Response> getStorageWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/storage';
+    final apiPath = r'/server/storage';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -311,7 +311,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -339,7 +339,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/media-types' operation and returns the [Response].
   Future<Response> getSupportedMediaTypesWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/media-types';
+    final apiPath = r'/server/media-types';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -352,7 +352,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -380,7 +380,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/theme' operation and returns the [Response].
   Future<Response> getThemeWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/theme';
+    final apiPath = r'/server/theme';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -393,7 +393,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -421,7 +421,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/version-history' operation and returns the [Response].
   Future<Response> getVersionHistoryWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/version-history';
+    final apiPath = r'/server/version-history';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -434,7 +434,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -465,7 +465,7 @@ class ServerApi {
   /// Performs an HTTP 'GET /server/ping' operation and returns the [Response].
   Future<Response> pingServerWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/server/ping';
+    final apiPath = r'/server/ping';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -478,7 +478,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -509,7 +509,7 @@ class ServerApi {
   /// * [LicenseKeyDto] licenseKeyDto (required):
   Future<Response> setServerLicenseWithHttpInfo(LicenseKeyDto licenseKeyDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/server/license';
+    final apiPath = r'/server/license';
 
     // ignore: prefer_final_locals
     Object? postBody = licenseKeyDto;
@@ -522,7 +522,7 @@ class ServerApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/sessions_api.dart b/mobile/openapi/lib/api/sessions_api.dart
index fcc6cb836f..203f801b72 100644
--- a/mobile/openapi/lib/api/sessions_api.dart
+++ b/mobile/openapi/lib/api/sessions_api.dart
@@ -19,7 +19,7 @@ class SessionsApi {
   /// Performs an HTTP 'DELETE /sessions' operation and returns the [Response].
   Future<Response> deleteAllSessionsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/sessions';
+    final apiPath = r'/sessions';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class SessionsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -55,7 +55,7 @@ class SessionsApi {
   /// * [String] id (required):
   Future<Response> deleteSessionWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/sessions/{id}'
+    final apiPath = r'/sessions/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -69,7 +69,7 @@ class SessionsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -92,7 +92,7 @@ class SessionsApi {
   /// Performs an HTTP 'GET /sessions' operation and returns the [Response].
   Future<Response> getSessionsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/sessions';
+    final apiPath = r'/sessions';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -105,7 +105,7 @@ class SessionsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/shared_links_api.dart b/mobile/openapi/lib/api/shared_links_api.dart
index a6b2978fe2..5bac8988dc 100644
--- a/mobile/openapi/lib/api/shared_links_api.dart
+++ b/mobile/openapi/lib/api/shared_links_api.dart
@@ -26,7 +26,7 @@ class SharedLinksApi {
   /// * [String] key:
   Future<Response> addSharedLinkAssetsWithHttpInfo(String id, AssetIdsDto assetIdsDto, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links/{id}/assets'
+    final apiPath = r'/shared-links/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -44,7 +44,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -85,7 +85,7 @@ class SharedLinksApi {
   /// * [SharedLinkCreateDto] sharedLinkCreateDto (required):
   Future<Response> createSharedLinkWithHttpInfo(SharedLinkCreateDto sharedLinkCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links';
+    final apiPath = r'/shared-links';
 
     // ignore: prefer_final_locals
     Object? postBody = sharedLinkCreateDto;
@@ -98,7 +98,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -132,7 +132,7 @@ class SharedLinksApi {
   /// * [String] albumId:
   Future<Response> getAllSharedLinksWithHttpInfo({ String? albumId, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links';
+    final apiPath = r'/shared-links';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -149,7 +149,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -190,7 +190,7 @@ class SharedLinksApi {
   /// * [String] token:
   Future<Response> getMySharedLinkWithHttpInfo({ String? key, String? password, String? token, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links/me';
+    final apiPath = r'/shared-links/me';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -213,7 +213,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -251,7 +251,7 @@ class SharedLinksApi {
   /// * [String] id (required):
   Future<Response> getSharedLinkByIdWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links/{id}'
+    final apiPath = r'/shared-links/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -265,7 +265,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -299,7 +299,7 @@ class SharedLinksApi {
   /// * [String] id (required):
   Future<Response> removeSharedLinkWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links/{id}'
+    final apiPath = r'/shared-links/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -313,7 +313,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -343,7 +343,7 @@ class SharedLinksApi {
   /// * [String] key:
   Future<Response> removeSharedLinkAssetsWithHttpInfo(String id, AssetIdsDto assetIdsDto, { String? key, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links/{id}/assets'
+    final apiPath = r'/shared-links/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -361,7 +361,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -404,7 +404,7 @@ class SharedLinksApi {
   /// * [SharedLinkEditDto] sharedLinkEditDto (required):
   Future<Response> updateSharedLinkWithHttpInfo(String id, SharedLinkEditDto sharedLinkEditDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/shared-links/{id}'
+    final apiPath = r'/shared-links/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -418,7 +418,7 @@ class SharedLinksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PATCH',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/stacks_api.dart b/mobile/openapi/lib/api/stacks_api.dart
index aa1d9b3416..84f23ec55d 100644
--- a/mobile/openapi/lib/api/stacks_api.dart
+++ b/mobile/openapi/lib/api/stacks_api.dart
@@ -22,7 +22,7 @@ class StacksApi {
   /// * [StackCreateDto] stackCreateDto (required):
   Future<Response> createStackWithHttpInfo(StackCreateDto stackCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/stacks';
+    final apiPath = r'/stacks';
 
     // ignore: prefer_final_locals
     Object? postBody = stackCreateDto;
@@ -35,7 +35,7 @@ class StacksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class StacksApi {
   /// * [String] id (required):
   Future<Response> deleteStackWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/stacks/{id}'
+    final apiPath = r'/stacks/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -83,7 +83,7 @@ class StacksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -109,7 +109,7 @@ class StacksApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> deleteStacksWithHttpInfo(BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/stacks';
+    final apiPath = r'/stacks';
 
     // ignore: prefer_final_locals
     Object? postBody = bulkIdsDto;
@@ -122,7 +122,7 @@ class StacksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -148,7 +148,7 @@ class StacksApi {
   /// * [String] id (required):
   Future<Response> getStackWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/stacks/{id}'
+    final apiPath = r'/stacks/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -162,7 +162,7 @@ class StacksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -196,7 +196,7 @@ class StacksApi {
   /// * [String] primaryAssetId:
   Future<Response> searchStacksWithHttpInfo({ String? primaryAssetId, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/stacks';
+    final apiPath = r'/stacks';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -213,7 +213,7 @@ class StacksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -252,7 +252,7 @@ class StacksApi {
   /// * [StackUpdateDto] stackUpdateDto (required):
   Future<Response> updateStackWithHttpInfo(String id, StackUpdateDto stackUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/stacks/{id}'
+    final apiPath = r'/stacks/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -266,7 +266,7 @@ class StacksApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/sync_api.dart b/mobile/openapi/lib/api/sync_api.dart
index 49a4963bff..fe2876ddd8 100644
--- a/mobile/openapi/lib/api/sync_api.dart
+++ b/mobile/openapi/lib/api/sync_api.dart
@@ -22,7 +22,7 @@ class SyncApi {
   /// * [SyncAckDeleteDto] syncAckDeleteDto (required):
   Future<Response> deleteSyncAckWithHttpInfo(SyncAckDeleteDto syncAckDeleteDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/sync/ack';
+    final apiPath = r'/sync/ack';
 
     // ignore: prefer_final_locals
     Object? postBody = syncAckDeleteDto;
@@ -35,7 +35,7 @@ class SyncApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -61,7 +61,7 @@ class SyncApi {
   /// * [AssetDeltaSyncDto] assetDeltaSyncDto (required):
   Future<Response> getDeltaSyncWithHttpInfo(AssetDeltaSyncDto assetDeltaSyncDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/sync/delta-sync';
+    final apiPath = r'/sync/delta-sync';
 
     // ignore: prefer_final_locals
     Object? postBody = assetDeltaSyncDto;
@@ -74,7 +74,7 @@ class SyncApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -108,7 +108,7 @@ class SyncApi {
   /// * [AssetFullSyncDto] assetFullSyncDto (required):
   Future<Response> getFullSyncForUserWithHttpInfo(AssetFullSyncDto assetFullSyncDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/sync/full-sync';
+    final apiPath = r'/sync/full-sync';
 
     // ignore: prefer_final_locals
     Object? postBody = assetFullSyncDto;
@@ -121,7 +121,7 @@ class SyncApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -155,7 +155,7 @@ class SyncApi {
   /// Performs an HTTP 'GET /sync/ack' operation and returns the [Response].
   Future<Response> getSyncAckWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/sync/ack';
+    final apiPath = r'/sync/ack';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -168,7 +168,7 @@ class SyncApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -202,7 +202,7 @@ class SyncApi {
   /// * [SyncStreamDto] syncStreamDto (required):
   Future<Response> getSyncStreamWithHttpInfo(SyncStreamDto syncStreamDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/sync/stream';
+    final apiPath = r'/sync/stream';
 
     // ignore: prefer_final_locals
     Object? postBody = syncStreamDto;
@@ -215,7 +215,7 @@ class SyncApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -241,7 +241,7 @@ class SyncApi {
   /// * [SyncAckSetDto] syncAckSetDto (required):
   Future<Response> sendSyncAckWithHttpInfo(SyncAckSetDto syncAckSetDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/sync/ack';
+    final apiPath = r'/sync/ack';
 
     // ignore: prefer_final_locals
     Object? postBody = syncAckSetDto;
@@ -254,7 +254,7 @@ class SyncApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/system_config_api.dart b/mobile/openapi/lib/api/system_config_api.dart
index b63b2b70c4..a03b9d3e72 100644
--- a/mobile/openapi/lib/api/system_config_api.dart
+++ b/mobile/openapi/lib/api/system_config_api.dart
@@ -19,7 +19,7 @@ class SystemConfigApi {
   /// Performs an HTTP 'GET /system-config' operation and returns the [Response].
   Future<Response> getConfigWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/system-config';
+    final apiPath = r'/system-config';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class SystemConfigApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -60,7 +60,7 @@ class SystemConfigApi {
   /// Performs an HTTP 'GET /system-config/defaults' operation and returns the [Response].
   Future<Response> getConfigDefaultsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/system-config/defaults';
+    final apiPath = r'/system-config/defaults';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -73,7 +73,7 @@ class SystemConfigApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -101,7 +101,7 @@ class SystemConfigApi {
   /// Performs an HTTP 'GET /system-config/storage-template-options' operation and returns the [Response].
   Future<Response> getStorageTemplateOptionsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/system-config/storage-template-options';
+    final apiPath = r'/system-config/storage-template-options';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -114,7 +114,7 @@ class SystemConfigApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -145,7 +145,7 @@ class SystemConfigApi {
   /// * [SystemConfigDto] systemConfigDto (required):
   Future<Response> updateConfigWithHttpInfo(SystemConfigDto systemConfigDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/system-config';
+    final apiPath = r'/system-config';
 
     // ignore: prefer_final_locals
     Object? postBody = systemConfigDto;
@@ -158,7 +158,7 @@ class SystemConfigApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/system_metadata_api.dart b/mobile/openapi/lib/api/system_metadata_api.dart
index 822a54b14f..3bd8bddcac 100644
--- a/mobile/openapi/lib/api/system_metadata_api.dart
+++ b/mobile/openapi/lib/api/system_metadata_api.dart
@@ -19,7 +19,7 @@ class SystemMetadataApi {
   /// Performs an HTTP 'GET /system-metadata/admin-onboarding' operation and returns the [Response].
   Future<Response> getAdminOnboardingWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/system-metadata/admin-onboarding';
+    final apiPath = r'/system-metadata/admin-onboarding';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class SystemMetadataApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -60,7 +60,7 @@ class SystemMetadataApi {
   /// Performs an HTTP 'GET /system-metadata/reverse-geocoding-state' operation and returns the [Response].
   Future<Response> getReverseGeocodingStateWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/system-metadata/reverse-geocoding-state';
+    final apiPath = r'/system-metadata/reverse-geocoding-state';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -73,7 +73,7 @@ class SystemMetadataApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -104,7 +104,7 @@ class SystemMetadataApi {
   /// * [AdminOnboardingUpdateDto] adminOnboardingUpdateDto (required):
   Future<Response> updateAdminOnboardingWithHttpInfo(AdminOnboardingUpdateDto adminOnboardingUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/system-metadata/admin-onboarding';
+    final apiPath = r'/system-metadata/admin-onboarding';
 
     // ignore: prefer_final_locals
     Object? postBody = adminOnboardingUpdateDto;
@@ -117,7 +117,7 @@ class SystemMetadataApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/tags_api.dart b/mobile/openapi/lib/api/tags_api.dart
index 87c9001a3c..f6cfc8720b 100644
--- a/mobile/openapi/lib/api/tags_api.dart
+++ b/mobile/openapi/lib/api/tags_api.dart
@@ -22,7 +22,7 @@ class TagsApi {
   /// * [TagBulkAssetsDto] tagBulkAssetsDto (required):
   Future<Response> bulkTagAssetsWithHttpInfo(TagBulkAssetsDto tagBulkAssetsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags/assets';
+    final apiPath = r'/tags/assets';
 
     // ignore: prefer_final_locals
     Object? postBody = tagBulkAssetsDto;
@@ -35,7 +35,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -69,7 +69,7 @@ class TagsApi {
   /// * [TagCreateDto] tagCreateDto (required):
   Future<Response> createTagWithHttpInfo(TagCreateDto tagCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags';
+    final apiPath = r'/tags';
 
     // ignore: prefer_final_locals
     Object? postBody = tagCreateDto;
@@ -82,7 +82,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -116,7 +116,7 @@ class TagsApi {
   /// * [String] id (required):
   Future<Response> deleteTagWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags/{id}'
+    final apiPath = r'/tags/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -130,7 +130,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -153,7 +153,7 @@ class TagsApi {
   /// Performs an HTTP 'GET /tags' operation and returns the [Response].
   Future<Response> getAllTagsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/tags';
+    final apiPath = r'/tags';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -166,7 +166,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -200,7 +200,7 @@ class TagsApi {
   /// * [String] id (required):
   Future<Response> getTagByIdWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags/{id}'
+    final apiPath = r'/tags/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -214,7 +214,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -250,7 +250,7 @@ class TagsApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> tagAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags/{id}/assets'
+    final apiPath = r'/tags/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -264,7 +264,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -305,7 +305,7 @@ class TagsApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> untagAssetsWithHttpInfo(String id, BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags/{id}/assets'
+    final apiPath = r'/tags/{id}/assets'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -319,7 +319,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -360,7 +360,7 @@ class TagsApi {
   /// * [TagUpdateDto] tagUpdateDto (required):
   Future<Response> updateTagWithHttpInfo(String id, TagUpdateDto tagUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags/{id}'
+    final apiPath = r'/tags/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -374,7 +374,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -410,7 +410,7 @@ class TagsApi {
   /// * [TagUpsertDto] tagUpsertDto (required):
   Future<Response> upsertTagsWithHttpInfo(TagUpsertDto tagUpsertDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/tags';
+    final apiPath = r'/tags';
 
     // ignore: prefer_final_locals
     Object? postBody = tagUpsertDto;
@@ -423,7 +423,7 @@ class TagsApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/timeline_api.dart b/mobile/openapi/lib/api/timeline_api.dart
index 8c94e09bf5..7ea7189b00 100644
--- a/mobile/openapi/lib/api/timeline_api.dart
+++ b/mobile/openapi/lib/api/timeline_api.dart
@@ -46,7 +46,7 @@ class TimelineApi {
   /// * [bool] withStacked:
   Future<Response> getTimeBucketWithHttpInfo(TimeBucketSize size, String timeBucket, { String? albumId, bool? isArchived, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? tagId, String? userId, bool? withPartners, bool? withStacked, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/timeline/bucket';
+    final apiPath = r'/timeline/bucket';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -95,7 +95,7 @@ class TimelineApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -178,7 +178,7 @@ class TimelineApi {
   /// * [bool] withStacked:
   Future<Response> getTimeBucketsWithHttpInfo(TimeBucketSize size, { String? albumId, bool? isArchived, bool? isFavorite, bool? isTrashed, String? key, AssetOrder? order, String? personId, String? tagId, String? userId, bool? withPartners, bool? withStacked, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/timeline/buckets';
+    final apiPath = r'/timeline/buckets';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -226,7 +226,7 @@ class TimelineApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/trash_api.dart b/mobile/openapi/lib/api/trash_api.dart
index 8f8c6ffb3a..982dbcbeda 100644
--- a/mobile/openapi/lib/api/trash_api.dart
+++ b/mobile/openapi/lib/api/trash_api.dart
@@ -19,7 +19,7 @@ class TrashApi {
   /// Performs an HTTP 'POST /trash/empty' operation and returns the [Response].
   Future<Response> emptyTrashWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/trash/empty';
+    final apiPath = r'/trash/empty';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -32,7 +32,7 @@ class TrashApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -63,7 +63,7 @@ class TrashApi {
   /// * [BulkIdsDto] bulkIdsDto (required):
   Future<Response> restoreAssetsWithHttpInfo(BulkIdsDto bulkIdsDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/trash/restore/assets';
+    final apiPath = r'/trash/restore/assets';
 
     // ignore: prefer_final_locals
     Object? postBody = bulkIdsDto;
@@ -76,7 +76,7 @@ class TrashApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -107,7 +107,7 @@ class TrashApi {
   /// Performs an HTTP 'POST /trash/restore' operation and returns the [Response].
   Future<Response> restoreTrashWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/trash/restore';
+    final apiPath = r'/trash/restore';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -120,7 +120,7 @@ class TrashApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/users_admin_api.dart b/mobile/openapi/lib/api/users_admin_api.dart
index a074645e08..b4508d7dcd 100644
--- a/mobile/openapi/lib/api/users_admin_api.dart
+++ b/mobile/openapi/lib/api/users_admin_api.dart
@@ -22,7 +22,7 @@ class UsersAdminApi {
   /// * [UserAdminCreateDto] userAdminCreateDto (required):
   Future<Response> createUserAdminWithHttpInfo(UserAdminCreateDto userAdminCreateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users';
+    final apiPath = r'/admin/users';
 
     // ignore: prefer_final_locals
     Object? postBody = userAdminCreateDto;
@@ -35,7 +35,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -71,7 +71,7 @@ class UsersAdminApi {
   /// * [UserAdminDeleteDto] userAdminDeleteDto (required):
   Future<Response> deleteUserAdminWithHttpInfo(String id, UserAdminDeleteDto userAdminDeleteDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users/{id}'
+    final apiPath = r'/admin/users/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -85,7 +85,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -121,7 +121,7 @@ class UsersAdminApi {
   /// * [String] id (required):
   Future<Response> getUserAdminWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users/{id}'
+    final apiPath = r'/admin/users/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -135,7 +135,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -169,7 +169,7 @@ class UsersAdminApi {
   /// * [String] id (required):
   Future<Response> getUserPreferencesAdminWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users/{id}/preferences'
+    final apiPath = r'/admin/users/{id}/preferences'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -183,7 +183,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -217,7 +217,7 @@ class UsersAdminApi {
   /// * [String] id (required):
   Future<Response> restoreUserAdminWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users/{id}/restore'
+    final apiPath = r'/admin/users/{id}/restore'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -231,7 +231,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -265,7 +265,7 @@ class UsersAdminApi {
   /// * [bool] withDeleted:
   Future<Response> searchUsersAdminWithHttpInfo({ bool? withDeleted, }) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users';
+    final apiPath = r'/admin/users';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -282,7 +282,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -321,7 +321,7 @@ class UsersAdminApi {
   /// * [UserAdminUpdateDto] userAdminUpdateDto (required):
   Future<Response> updateUserAdminWithHttpInfo(String id, UserAdminUpdateDto userAdminUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users/{id}'
+    final apiPath = r'/admin/users/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -335,7 +335,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -373,7 +373,7 @@ class UsersAdminApi {
   /// * [UserPreferencesUpdateDto] userPreferencesUpdateDto (required):
   Future<Response> updateUserPreferencesAdminWithHttpInfo(String id, UserPreferencesUpdateDto userPreferencesUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/admin/users/{id}/preferences'
+    final apiPath = r'/admin/users/{id}/preferences'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -387,7 +387,7 @@ class UsersAdminApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/users_api.dart b/mobile/openapi/lib/api/users_api.dart
index b2b9fa8826..a48ec54cfe 100644
--- a/mobile/openapi/lib/api/users_api.dart
+++ b/mobile/openapi/lib/api/users_api.dart
@@ -22,7 +22,7 @@ class UsersApi {
   /// * [MultipartFile] file (required):
   Future<Response> createProfileImageWithHttpInfo(MultipartFile file,) async {
     // ignore: prefer_const_declarations
-    final path = r'/users/profile-image';
+    final apiPath = r'/users/profile-image';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -34,7 +34,7 @@ class UsersApi {
     const contentTypes = <String>['multipart/form-data'];
 
     bool hasFields = false;
-    final mp = MultipartRequest('POST', Uri.parse(path));
+    final mp = MultipartRequest('POST', Uri.parse(apiPath));
     if (file != null) {
       hasFields = true;
       mp.fields[r'file'] = file.field;
@@ -45,7 +45,7 @@ class UsersApi {
     }
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'POST',
       queryParams,
       postBody,
@@ -76,7 +76,7 @@ class UsersApi {
   /// Performs an HTTP 'DELETE /users/profile-image' operation and returns the [Response].
   Future<Response> deleteProfileImageWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/users/profile-image';
+    final apiPath = r'/users/profile-image';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -89,7 +89,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -109,7 +109,7 @@ class UsersApi {
   /// Performs an HTTP 'DELETE /users/me/license' operation and returns the [Response].
   Future<Response> deleteUserLicenseWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me/license';
+    final apiPath = r'/users/me/license';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -122,7 +122,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'DELETE',
       queryParams,
       postBody,
@@ -142,7 +142,7 @@ class UsersApi {
   /// Performs an HTTP 'GET /users/me/preferences' operation and returns the [Response].
   Future<Response> getMyPreferencesWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me/preferences';
+    final apiPath = r'/users/me/preferences';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -155,7 +155,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -183,7 +183,7 @@ class UsersApi {
   /// Performs an HTTP 'GET /users/me' operation and returns the [Response].
   Future<Response> getMyUserWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me';
+    final apiPath = r'/users/me';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -196,7 +196,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -227,7 +227,7 @@ class UsersApi {
   /// * [String] id (required):
   Future<Response> getProfileImageWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/users/{id}/profile-image'
+    final apiPath = r'/users/{id}/profile-image'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -241,7 +241,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -275,7 +275,7 @@ class UsersApi {
   /// * [String] id (required):
   Future<Response> getUserWithHttpInfo(String id,) async {
     // ignore: prefer_const_declarations
-    final path = r'/users/{id}'
+    final apiPath = r'/users/{id}'
       .replaceAll('{id}', id);
 
     // ignore: prefer_final_locals
@@ -289,7 +289,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -320,7 +320,7 @@ class UsersApi {
   /// Performs an HTTP 'GET /users/me/license' operation and returns the [Response].
   Future<Response> getUserLicenseWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me/license';
+    final apiPath = r'/users/me/license';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -333,7 +333,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -361,7 +361,7 @@ class UsersApi {
   /// Performs an HTTP 'GET /users' operation and returns the [Response].
   Future<Response> searchUsersWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/users';
+    final apiPath = r'/users';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -374,7 +374,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -408,7 +408,7 @@ class UsersApi {
   /// * [LicenseKeyDto] licenseKeyDto (required):
   Future<Response> setUserLicenseWithHttpInfo(LicenseKeyDto licenseKeyDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me/license';
+    final apiPath = r'/users/me/license';
 
     // ignore: prefer_final_locals
     Object? postBody = licenseKeyDto;
@@ -421,7 +421,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -455,7 +455,7 @@ class UsersApi {
   /// * [UserPreferencesUpdateDto] userPreferencesUpdateDto (required):
   Future<Response> updateMyPreferencesWithHttpInfo(UserPreferencesUpdateDto userPreferencesUpdateDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me/preferences';
+    final apiPath = r'/users/me/preferences';
 
     // ignore: prefer_final_locals
     Object? postBody = userPreferencesUpdateDto;
@@ -468,7 +468,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
@@ -502,7 +502,7 @@ class UsersApi {
   /// * [UserUpdateMeDto] userUpdateMeDto (required):
   Future<Response> updateMyUserWithHttpInfo(UserUpdateMeDto userUpdateMeDto,) async {
     // ignore: prefer_const_declarations
-    final path = r'/users/me';
+    final apiPath = r'/users/me';
 
     // ignore: prefer_final_locals
     Object? postBody = userUpdateMeDto;
@@ -515,7 +515,7 @@ class UsersApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'PUT',
       queryParams,
       postBody,
diff --git a/mobile/openapi/lib/api/view_api.dart b/mobile/openapi/lib/api/view_api.dart
index f4489f2d1a..1fcaec759c 100644
--- a/mobile/openapi/lib/api/view_api.dart
+++ b/mobile/openapi/lib/api/view_api.dart
@@ -22,7 +22,7 @@ class ViewApi {
   /// * [String] path (required):
   Future<Response> getAssetsByOriginalPathWithHttpInfo(String path,) async {
     // ignore: prefer_const_declarations
-    final path = r'/view/folder';
+    final apiPath = r'/view/folder';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -37,7 +37,7 @@ class ViewApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
@@ -71,7 +71,7 @@ class ViewApi {
   /// Performs an HTTP 'GET /view/folder/unique-paths' operation and returns the [Response].
   Future<Response> getUniqueOriginalPathsWithHttpInfo() async {
     // ignore: prefer_const_declarations
-    final path = r'/view/folder/unique-paths';
+    final apiPath = r'/view/folder/unique-paths';
 
     // ignore: prefer_final_locals
     Object? postBody;
@@ -84,7 +84,7 @@ class ViewApi {
 
 
     return apiClient.invokeAPI(
-      path,
+      apiPath,
       'GET',
       queryParams,
       postBody,
diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml
index f5e4b05d49..7bce65e484 100644
--- a/mobile/pubspec.yaml
+++ b/mobile/pubspec.yaml
@@ -83,7 +83,7 @@ dependencies:
 # Taken from https://github.com/Myzel394/locus/blob/445013d22ec1d759027d4303bd65b30c5c8588c8/pubspec.yaml#L105
 dependency_overrides:
   # TODO: remove once Isar is updated
-  analyzer: ^6.3.0
+  analyzer: ^6.0.0
   # TODO: remove once analyzer override is removed
   meta: ^1.11.0
   # TODO: remove once analyzer override is removed
diff --git a/open-api/bin/generate-open-api.sh b/open-api/bin/generate-open-api.sh
index bf8b24b557..e2badc6dff 100755
--- a/open-api/bin/generate-open-api.sh
+++ b/open-api/bin/generate-open-api.sh
@@ -9,7 +9,11 @@ function dart {
   wget -O native_class.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/$OPENAPI_GENERATOR_VERSION/modules/openapi-generator/src/main/resources/dart2/serialization/native/native_class.mustache
   patch --no-backup-if-mismatch -u native_class.mustache <native_class.mustache.patch
 
-  cd ../../../../
+  cd ../../
+  wget -O api.mustache https://raw.githubusercontent.com/OpenAPITools/openapi-generator/$OPENAPI_GENERATOR_VERSION/modules/openapi-generator/src/main/resources/dart2/api.mustache
+  patch --no-backup-if-mismatch -u api.mustache <api.mustache.patch
+
+  cd ../../
   npx --yes @openapitools/openapi-generator-cli generate -g dart -i ./immich-openapi-specs.json -o ../mobile/openapi -t ./templates/mobile
 
   # Post generate patches
diff --git a/open-api/templates/mobile/api.mustache b/open-api/templates/mobile/api.mustache
new file mode 100644
index 0000000000..ac32571123
--- /dev/null
+++ b/open-api/templates/mobile/api.mustache
@@ -0,0 +1,194 @@
+{{>header}}
+{{>part_of}}
+{{#operations}}
+
+class {{{classname}}} {
+  {{{classname}}}([ApiClient? apiClient]) : apiClient = apiClient ?? defaultApiClient;
+
+  final ApiClient apiClient;
+  {{#operation}}
+
+  {{#summary}}
+  /// {{{.}}}
+  {{/summary}}
+  {{#notes}}
+    {{#summary}}
+  ///
+    {{/summary}}
+  /// {{{notes}}}
+  ///
+  /// Note: This method returns the HTTP [Response].
+  {{/notes}}
+  {{^notes}}
+    {{#summary}}
+  ///
+  /// Note: This method returns the HTTP [Response].
+    {{/summary}}
+    {{^summary}}
+  /// Performs an HTTP '{{{httpMethod}}} {{{path}}}' operation and returns the [Response].
+    {{/summary}}
+  {{/notes}}
+  {{#hasParams}}
+    {{#summary}}
+  ///
+    {{/summary}}
+    {{^summary}}
+      {{#notes}}
+  ///
+      {{/notes}}
+    {{/summary}}
+  /// Parameters:
+  ///
+  {{/hasParams}}
+  {{#allParams}}
+  /// * [{{{dataType}}}] {{{paramName}}}{{#required}} (required){{/required}}{{#optional}} (optional){{/optional}}:
+    {{#description}}
+  ///   {{{.}}}
+    {{/description}}
+    {{^-last}}
+  ///
+    {{/-last}}
+  {{/allParams}}
+  Future<Response> {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
+    // ignore: prefer_const_declarations
+    final apiPath = r'{{{path}}}'{{#pathParams}}
+      .replaceAll({{=<% %>=}}'{<% baseName %>}'<%={{ }}=%>, {{{paramName}}}{{^isString}}.toString(){{/isString}}){{/pathParams}};
+
+    // ignore: prefer_final_locals
+    Object? postBody{{#bodyParam}} = {{{paramName}}}{{/bodyParam}};
+
+    final queryParams = <QueryParam>[];
+    final headerParams = <String, String>{};
+    final formParams = <String, String>{};
+    {{#hasQueryParams}}
+
+      {{#queryParams}}
+        {{^required}}
+    if ({{{paramName}}} != null) {
+          {{/required}}
+      queryParams.addAll(_queryParams('{{{collectionFormat}}}', '{{{baseName}}}', {{{paramName}}}));
+          {{^required}}
+    }
+        {{/required}}
+      {{/queryParams}}
+    {{/hasQueryParams}}
+    {{#hasHeaderParams}}
+
+      {{#headerParams}}
+        {{#required}}
+    headerParams[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
+        {{/required}}
+        {{^required}}
+    if ({{{paramName}}} != null) {
+      headerParams[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
+    }
+        {{/required}}
+      {{/headerParams}}
+    {{/hasHeaderParams}}
+
+    const contentTypes = <String>[{{#prioritizedContentTypes}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/prioritizedContentTypes}}];
+
+    {{#isMultipart}}
+    bool hasFields = false;
+    final mp = MultipartRequest('{{{httpMethod}}}', Uri.parse(apiPath));
+    {{#formParams}}
+    {{^isFile}}
+    if ({{{paramName}}} != null) {
+      hasFields = true;
+      mp.fields[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
+    }
+    {{/isFile}}
+    {{#isFile}}
+    if ({{{paramName}}} != null) {
+      hasFields = true;
+      mp.fields[r'{{{baseName}}}'] = {{{paramName}}}.field;
+      mp.files.add({{{paramName}}});
+    }
+    {{/isFile}}
+    {{/formParams}}
+    if (hasFields) {
+      postBody = mp;
+    }
+    {{/isMultipart}}
+    {{^isMultipart}}
+    {{#formParams}}
+    {{^isFile}}
+    if ({{{paramName}}} != null) {
+      formParams[r'{{{baseName}}}'] = parameterToString({{{paramName}}});
+    }
+    {{/isFile}}
+    {{/formParams}}
+    {{/isMultipart}}
+
+    return apiClient.invokeAPI(
+      apiPath,
+      '{{{httpMethod}}}',
+      queryParams,
+      postBody,
+      headerParams,
+      formParams,
+      contentTypes.isEmpty ? null : contentTypes.first,
+    );
+  }
+
+  {{#summary}}
+  /// {{{.}}}
+  {{/summary}}
+  {{#notes}}
+  {{#summary}}
+  ///
+  {{/summary}}
+  /// {{{notes}}}
+  {{/notes}}
+  {{#hasParams}}
+    {{#summary}}
+  ///
+    {{/summary}}
+    {{^summary}}
+      {{#notes}}
+  ///
+      {{/notes}}
+    {{/summary}}
+  /// Parameters:
+  ///
+  {{/hasParams}}
+  {{#allParams}}
+  /// * [{{{dataType}}}] {{{paramName}}}{{#required}} (required){{/required}}{{#optional}} (optional){{/optional}}:
+    {{#description}}
+  ///   {{{.}}}
+    {{/description}}
+    {{^-last}}
+  ///
+    {{/-last}}
+  {{/allParams}}
+  Future<{{#returnType}}{{{.}}}?{{/returnType}}{{^returnType}}void{{/returnType}}> {{{nickname}}}({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
+    final response = await {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}} {{#allParams}}{{^required}}{{{paramName}}}: {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} {{/hasOptionalParams}});
+    if (response.statusCode >= HttpStatus.badRequest) {
+      throw ApiException(response.statusCode, await _decodeBodyBytes(response));
+    }
+    {{#returnType}}
+    // When a remote server returns no body with a status of 204, we shall not decode it.
+    // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+    // FormatException when trying to decode an empty string.
+    if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+    {{#native_serialization}}
+    {{#isArray}}
+      final responseBody = await _decodeBodyBytes(response);
+      return (await apiClient.deserializeAsync(responseBody, '{{{returnType}}}') as List)
+        .cast<{{{returnBaseType}}}>()
+        .{{#uniqueItems}}toSet(){{/uniqueItems}}{{^uniqueItems}}toList(growable: false){{/uniqueItems}};
+    {{/isArray}}
+    {{^isArray}}
+    {{#isMap}}
+      return {{{returnType}}}.from(await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}'),);
+    {{/isMap}}
+    {{^isMap}}
+      return await apiClient.deserializeAsync(await _decodeBodyBytes(response), '{{{returnType}}}',) as {{{returnType}}};
+    {{/isMap}}{{/isArray}}{{/native_serialization}}
+    }
+    return null;
+    {{/returnType}}
+  }
+  {{/operation}}
+}
+{{/operations}}
diff --git a/open-api/templates/mobile/api.mustache.patch b/open-api/templates/mobile/api.mustache.patch
new file mode 100644
index 0000000000..e3f888d6d7
--- /dev/null
+++ b/open-api/templates/mobile/api.mustache.patch
@@ -0,0 +1,29 @@
+--- api.mustache	2025-01-22 05:50:25
++++ api.mustache.modified	2025-01-22 05:52:23
+@@ -51,7 +51,7 @@
+   {{/allParams}}
+   Future<Response> {{{nickname}}}WithHttpInfo({{#allParams}}{{#required}}{{{dataType}}} {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}}{{#hasOptionalParams}}{ {{#allParams}}{{^required}}{{{dataType}}}? {{{paramName}}},{{^-last}} {{/-last}}{{/required}}{{/allParams}} }{{/hasOptionalParams}}) async {
+     // ignore: prefer_const_declarations
+-    final path = r'{{{path}}}'{{#pathParams}}
++    final apiPath = r'{{{path}}}'{{#pathParams}}
+       .replaceAll({{=<% %>=}}'{<% baseName %>}'<%={{ }}=%>, {{{paramName}}}{{^isString}}.toString(){{/isString}}){{/pathParams}};
+ 
+     // ignore: prefer_final_locals
+@@ -90,7 +90,7 @@
+ 
+     {{#isMultipart}}
+     bool hasFields = false;
+-    final mp = MultipartRequest('{{{httpMethod}}}', Uri.parse(path));
++    final mp = MultipartRequest('{{{httpMethod}}}', Uri.parse(apiPath));
+     {{#formParams}}
+     {{^isFile}}
+     if ({{{paramName}}} != null) {
+@@ -121,7 +121,7 @@
+     {{/isMultipart}}
+ 
+     return apiClient.invokeAPI(
+-      path,
++      apiPath,
+       '{{{httpMethod}}}',
+       queryParams,
+       postBody,