diff --git a/lib/main.dart b/lib/main.dart
index ff0130d..870e3c7 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -12,6 +12,7 @@ import 'package:okane/ui/pages/budgets/budget_details.dart';
 import 'package:okane/ui/pages/transaction_details.dart';
 import 'package:okane/ui/state/core.dart';
 import 'package:okane/ui/state/settings.dart';
+import 'package:sentry_flutter/sentry_flutter.dart';
 
 import 'ui/pages/loans/loan_details.dart';
 
@@ -21,11 +22,20 @@ Future<void> main() async {
 
   final settings = SettingsCubit();
   await settings.loadSettings();
+
   GetIt.I.registerSingleton<SettingsCubit>(settings);
   GetIt.I.registerSingleton<CoreCubit>(CoreCubit());
   GetIt.I.registerSingleton<OkaneDatabase>(OkaneDatabase());
 
-  runApp(const MyApp());
+  final appRunner = () => runApp(const MyApp());
+  if (settings.sentryDsn != null) {
+    print("Setting up Sentry!");
+    await SentryFlutter.init((options) {
+      options.dsn = settings.sentryDsn!;
+    }, appRunner: appRunner);
+  } else {
+    appRunner();
+  }
 }
 
 class MyApp extends StatelessWidget {
diff --git a/lib/ui/pages/settings.dart b/lib/ui/pages/settings.dart
index b0f2a1f..d4f0321 100644
--- a/lib/ui/pages/settings.dart
+++ b/lib/ui/pages/settings.dart
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:get_it/get_it.dart';
 import 'package:okane/i18n/strings.g.dart';
+import 'package:okane/ui/pages/account/breakdown_card.dart';
 import 'package:okane/ui/state/settings.dart';
 import 'package:okane/ui/utils.dart';
 
@@ -67,6 +68,74 @@ class SettingsPage extends StatelessWidget {
                 },
               ),
         ),
+
+        BlocBuilder<SettingsCubit, SettingsWrapper>(
+          builder:
+              (context, state) => ListTile(
+                title: Text("Sentry"),
+                subtitle: Text(
+                  "When enabled sends errors to the configured Sentry DSN.",
+                ),
+                trailing: IconButton(
+                  icon: Icon(Icons.clear),
+                  onPressed:
+                      state.settings.sentryDsn == null
+                          ? null
+                          : () async {
+                            final result = await confirm(
+                              context,
+                              "Clear Sentry DSN",
+                              "Are you sure you want to clear the Sentry DSN?",
+                            );
+                            if (!result) {
+                              return;
+                            }
+
+                            await GetIt.I.get<SettingsCubit>().setSettings(
+                              state.settings.copyWith(sentryDsn: null),
+                            );
+                          },
+                ),
+                onTap: () async {
+                  final controller = TextEditingController(
+                    text: state.settings.sentryDsn ?? '',
+                  );
+                  final result = await showDialogOrModal<String>(
+                    context: context,
+                    builder: (context) {
+                      return Column(
+                        mainAxisSize: MainAxisSize.min,
+                        children: [
+                          TextField(
+                            controller: controller,
+                            decoration: InputDecoration(hintText: "Sentry DSN"),
+                          ),
+                          Row(
+                            mainAxisSize: MainAxisSize.min,
+                            mainAxisAlignment: MainAxisAlignment.end,
+                            children: [
+                              OutlinedButton(
+                                child: Text("Apply"),
+                                onPressed: () {
+                                  Navigator.of(context).pop(controller.text);
+                                },
+                              ),
+                            ],
+                          ),
+                        ],
+                      );
+                    },
+                  );
+                  if (result == null) {
+                    return;
+                  }
+
+                  await GetIt.I.get<SettingsCubit>().setSettings(
+                    state.settings.copyWith(sentryDsn: result),
+                  );
+                },
+              ),
+        ),
       ],
     );
   }
diff --git a/lib/ui/state/settings.dart b/lib/ui/state/settings.dart
index 538541e..fbcac98 100644
--- a/lib/ui/state/settings.dart
+++ b/lib/ui/state/settings.dart
@@ -13,6 +13,7 @@ enum ColorSchemeSettings { light, dark, system }
 abstract class Settings with _$Settings {
   const factory Settings({
     @Default(ColorSchemeSettings.system) ColorSchemeSettings colorScheme,
+    @Default(null) String? sentryDsn,
   }) = _Settings;
 
   factory Settings.fromJson(Map<String, Object?> json) =>
@@ -45,4 +46,6 @@ class SettingsCubit extends Cubit<SettingsWrapper> {
 
     await _prefs.setString("settings", jsonEncode(settings.toJson()));
   }
+
+  String? get sentryDsn => state.settings.sentryDsn;
 }
diff --git a/lib/ui/state/settings.freezed.dart b/lib/ui/state/settings.freezed.dart
index f5cf9a2..8ca248a 100644
--- a/lib/ui/state/settings.freezed.dart
+++ b/lib/ui/state/settings.freezed.dart
@@ -22,6 +22,7 @@ Settings _$SettingsFromJson(Map<String, dynamic> json) {
 /// @nodoc
 mixin _$Settings {
   ColorSchemeSettings get colorScheme => throw _privateConstructorUsedError;
+  String? get sentryDsn => throw _privateConstructorUsedError;
 
   Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
   @JsonKey(ignore: true)
@@ -34,7 +35,7 @@ abstract class $SettingsCopyWith<$Res> {
   factory $SettingsCopyWith(Settings value, $Res Function(Settings) then) =
       _$SettingsCopyWithImpl<$Res, Settings>;
   @useResult
-  $Res call({ColorSchemeSettings colorScheme});
+  $Res call({ColorSchemeSettings colorScheme, String? sentryDsn});
 }
 
 /// @nodoc
@@ -49,7 +50,7 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
 
   @pragma('vm:prefer-inline')
   @override
-  $Res call({Object? colorScheme = null}) {
+  $Res call({Object? colorScheme = null, Object? sentryDsn = freezed}) {
     return _then(
       _value.copyWith(
             colorScheme:
@@ -57,6 +58,11 @@ class _$SettingsCopyWithImpl<$Res, $Val extends Settings>
                     ? _value.colorScheme
                     : colorScheme // ignore: cast_nullable_to_non_nullable
                         as ColorSchemeSettings,
+            sentryDsn:
+                freezed == sentryDsn
+                    ? _value.sentryDsn
+                    : sentryDsn // ignore: cast_nullable_to_non_nullable
+                        as String?,
           )
           as $Val,
     );
@@ -72,7 +78,7 @@ abstract class _$$SettingsImplCopyWith<$Res>
   ) = __$$SettingsImplCopyWithImpl<$Res>;
   @override
   @useResult
-  $Res call({ColorSchemeSettings colorScheme});
+  $Res call({ColorSchemeSettings colorScheme, String? sentryDsn});
 }
 
 /// @nodoc
@@ -86,7 +92,7 @@ class __$$SettingsImplCopyWithImpl<$Res>
 
   @pragma('vm:prefer-inline')
   @override
-  $Res call({Object? colorScheme = null}) {
+  $Res call({Object? colorScheme = null, Object? sentryDsn = freezed}) {
     return _then(
       _$SettingsImpl(
         colorScheme:
@@ -94,6 +100,11 @@ class __$$SettingsImplCopyWithImpl<$Res>
                 ? _value.colorScheme
                 : colorScheme // ignore: cast_nullable_to_non_nullable
                     as ColorSchemeSettings,
+        sentryDsn:
+            freezed == sentryDsn
+                ? _value.sentryDsn
+                : sentryDsn // ignore: cast_nullable_to_non_nullable
+                    as String?,
       ),
     );
   }
@@ -102,7 +113,10 @@ class __$$SettingsImplCopyWithImpl<$Res>
 /// @nodoc
 @JsonSerializable()
 class _$SettingsImpl implements _Settings {
-  const _$SettingsImpl({this.colorScheme = ColorSchemeSettings.system});
+  const _$SettingsImpl({
+    this.colorScheme = ColorSchemeSettings.system,
+    this.sentryDsn = null,
+  });
 
   factory _$SettingsImpl.fromJson(Map<String, dynamic> json) =>
       _$$SettingsImplFromJson(json);
@@ -110,10 +124,13 @@ class _$SettingsImpl implements _Settings {
   @override
   @JsonKey()
   final ColorSchemeSettings colorScheme;
+  @override
+  @JsonKey()
+  final String? sentryDsn;
 
   @override
   String toString() {
-    return 'Settings(colorScheme: $colorScheme)';
+    return 'Settings(colorScheme: $colorScheme, sentryDsn: $sentryDsn)';
   }
 
   @override
@@ -122,12 +139,14 @@ class _$SettingsImpl implements _Settings {
         (other.runtimeType == runtimeType &&
             other is _$SettingsImpl &&
             (identical(other.colorScheme, colorScheme) ||
-                other.colorScheme == colorScheme));
+                other.colorScheme == colorScheme) &&
+            (identical(other.sentryDsn, sentryDsn) ||
+                other.sentryDsn == sentryDsn));
   }
 
   @JsonKey(ignore: true)
   @override
-  int get hashCode => Object.hash(runtimeType, colorScheme);
+  int get hashCode => Object.hash(runtimeType, colorScheme, sentryDsn);
 
   @JsonKey(ignore: true)
   @override
@@ -142,8 +161,10 @@ class _$SettingsImpl implements _Settings {
 }
 
 abstract class _Settings implements Settings {
-  const factory _Settings({final ColorSchemeSettings colorScheme}) =
-      _$SettingsImpl;
+  const factory _Settings({
+    final ColorSchemeSettings colorScheme,
+    final String? sentryDsn,
+  }) = _$SettingsImpl;
 
   factory _Settings.fromJson(Map<String, dynamic> json) =
       _$SettingsImpl.fromJson;
@@ -151,6 +172,8 @@ abstract class _Settings implements Settings {
   @override
   ColorSchemeSettings get colorScheme;
   @override
+  String? get sentryDsn;
+  @override
   @JsonKey(ignore: true)
   _$$SettingsImplCopyWith<_$SettingsImpl> get copyWith =>
       throw _privateConstructorUsedError;
diff --git a/lib/ui/state/settings.g.dart b/lib/ui/state/settings.g.dart
index 4e07945..6c10b5a 100644
--- a/lib/ui/state/settings.g.dart
+++ b/lib/ui/state/settings.g.dart
@@ -14,11 +14,13 @@ _$SettingsImpl _$$SettingsImplFromJson(Map<String, dynamic> json) =>
             json['colorScheme'],
           ) ??
           ColorSchemeSettings.system,
+      sentryDsn: json['sentryDsn'] as String? ?? null,
     );
 
 Map<String, dynamic> _$$SettingsImplToJson(_$SettingsImpl instance) =>
     <String, dynamic>{
       'colorScheme': _$ColorSchemeSettingsEnumMap[instance.colorScheme]!,
+      'sentryDsn': instance.sentryDsn,
     };
 
 const _$ColorSchemeSettingsEnumMap = {
diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc
index 2c1ec4f..a758551 100644
--- a/linux/flutter/generated_plugin_registrant.cc
+++ b/linux/flutter/generated_plugin_registrant.cc
@@ -6,9 +6,13 @@
 
 #include "generated_plugin_registrant.h"
 
+#include <sentry_flutter/sentry_flutter_plugin.h>
 #include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
 
 void fl_register_plugins(FlPluginRegistry* registry) {
+  g_autoptr(FlPluginRegistrar) sentry_flutter_registrar =
+      fl_plugin_registry_get_registrar_for_plugin(registry, "SentryFlutterPlugin");
+  sentry_flutter_plugin_register_with_registrar(sentry_flutter_registrar);
   g_autoptr(FlPluginRegistrar) sqlite3_flutter_libs_registrar =
       fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin");
   sqlite3_flutter_libs_plugin_register_with_registrar(sqlite3_flutter_libs_registrar);
diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake
index 7ea2a80..19abbf2 100644
--- a/linux/flutter/generated_plugins.cmake
+++ b/linux/flutter/generated_plugins.cmake
@@ -3,6 +3,7 @@
 #
 
 list(APPEND FLUTTER_PLUGIN_LIST
+  sentry_flutter
   sqlite3_flutter_libs
 )
 
diff --git a/pubspec.lock b/pubspec.lock
index d751cfe..9dbd556 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -405,6 +405,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "6.0.0"
+  http:
+    dependency: transitive
+    description:
+      name: http
+      sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
+      url: "https://pub.dev"
+    source: hosted
+    version: "1.4.0"
   http_multi_server:
     dependency: transitive
     description:
@@ -565,6 +573,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.2.0"
+  package_info_plus:
+    dependency: transitive
+    description:
+      name: package_info_plus
+      sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.3.0"
+  package_info_plus_platform_interface:
+    dependency: transitive
+    description:
+      name: package_info_plus_platform_interface
+      sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.2.0"
   path:
     dependency: "direct main"
     description:
@@ -685,6 +709,22 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.2.9"
+  sentry:
+    dependency: transitive
+    description:
+      name: sentry
+      sha256: "599701ca0693a74da361bc780b0752e1abc98226cf5095f6b069648116c896bb"
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.14.2"
+  sentry_flutter:
+    dependency: "direct main"
+    description:
+      name: sentry_flutter
+      sha256: "5ba2cf40646a77d113b37a07bd69f61bb3ec8a73cbabe5537b05a7c89d2656f8"
+      url: "https://pub.dev"
+    source: hosted
+    version: "8.14.2"
   shared_preferences:
     dependency: "direct main"
     description:
@@ -810,6 +850,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.10.1"
+  sprintf:
+    dependency: transitive
+    description:
+      name: sprintf
+      sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
+      url: "https://pub.dev"
+    source: hosted
+    version: "7.0.0"
   sqlite3:
     dependency: transitive
     description:
@@ -898,6 +946,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.4.0"
+  uuid:
+    dependency: transitive
+    description:
+      name: uuid
+      sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
+      url: "https://pub.dev"
+    source: hosted
+    version: "4.5.1"
   vector_math:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 3c64c58..ed53377 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -29,6 +29,9 @@ dependencies:
   drift: ^2.26.1
   drift_flutter: ^0.2.4
 
+  # For optional error tracking
+  sentry_flutter: ^8.14.2
+
 dev_dependencies:
   flutter_test:
     sdk: flutter