diff --git a/android/gradle.properties b/android/gradle.properties
index 2aa2a7ba9299223d13e7b0c4ff3bd3f735ebca5e..d786ccb6f687d13ef64ab84562938745769f4ae6 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=1.0.25
-app.versionCode=26
+app.versionName=1.0.26
+app.versionCode=27
diff --git a/assets/translations/en.json b/assets/translations/en.json
index 5159cadefc7c57a7695a4fab93ebd84beb1b7edb..c042445a0b6721bbd268a51ec551919311858151 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -3,8 +3,14 @@
 
   "bottom_nav_sample": "Sample",
   "bottom_nav_chart": "Graph",
+  "bottom_nav_settings": "Settings",
   "bottom_nav_about": "About",
 
+  "settings_title": "Settings",
+  "settings_label_api_url": "API URL:",
+  "settings_label_security_token": "Security token:",
+  "settings_button_save": "Save",
+
   "about_title": "About",
   "about_content": "A random application, for testing purpose only.",
 
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 9f395345b7abc7a81f441f08ad5f1287d03e556b..484f9137b72e42d572192acba9ba0deaf686e78a 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -3,8 +3,14 @@
 
   "bottom_nav_sample": "Démo",
   "bottom_nav_chart": "Graph",
+  "bottom_nav_settings": "Paramètres",
   "bottom_nav_about": "À propos",
 
+  "settings_title": "Paramètres",
+  "settings_label_api_url": "URL de l'API :",
+  "settings_label_security_token": "Jeton de sécurité :",
+  "settings_button_save": "Enregistrer",
+
   "about_title": "À propos",
   "about_content": "Application fourre-tout, à des fins de tests uniquement.",
 
diff --git a/lib/activities/ActivityDemoPage.dart b/lib/activities/ActivityDemoPage.dart
index 24cf707073e59dea7e6b774598cfd77034d8df82..18e0e0f65473302bcc72fa99f46d7fa2597e8a55 100644
--- a/lib/activities/ActivityDemoPage.dart
+++ b/lib/activities/ActivityDemoPage.dart
@@ -2,8 +2,10 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:ionicons/ionicons.dart';
+
 import 'package:random/config/theme.dart';
 import 'package:random/cubit/data_cubit.dart';
+import 'package:random/cubit/settings_cubit.dart';
 
 class ActivityDemoPage extends StatelessWidget {
   const ActivityDemoPage({super.key});
@@ -28,6 +30,8 @@ class ActivityDemoPage extends StatelessWidget {
                   SizedBox(height: 20),
                   persistedCounterBlock(),
                   SizedBox(height: 20),
+                  fakeApiCall(),
+                  SizedBox(height: 20),
                   Text('BOTTOM').tr(),
                 ],
               ),
@@ -73,4 +77,25 @@ class ActivityDemoPage extends StatelessWidget {
       ),
     );
   }
+
+  Widget fakeApiCall() {
+    return BlocProvider<SettingsCubit>(
+      create: (BuildContext context) => SettingsCubit(),
+      child: BlocBuilder<SettingsCubit, SettingsState>(
+        builder: (BuildContext context, SettingsState state) {
+          SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
+
+          return Column(
+            mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              Text('apiUrl: ' + settings.getSetting('apiUrl')),
+              Text('securityToken: ' + settings.getSetting('securityToken')),
+              Text('unknown: ' + settings.getSetting('unknown', 'undefined')),
+            ],
+          );
+        },
+      ),
+    );
+  }
 }
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
index eb54062a9da27c975b07df38df69f1cdf1d9b776..cc714ed3e4cbf29cecd0ae0e200f72181c51a9ab 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/bottom_nav_cubit.dart
@@ -7,7 +7,8 @@ class BottomNavCubit extends HydratedCubit<int> {
 
   void getDemoPage() => emit(0);
   void getGraphPage() => emit(1);
-  void getAboutPage() => emit(2);
+  void getSettingsPage() => emit(2);
+  void getAboutPage() => emit(3);
 
   @override
   int? fromJson(Map<String, dynamic> json) {
diff --git a/lib/cubit/settings_cubit.dart b/lib/cubit/settings_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8d13db05cfcb2ee127aa6cf6188f15982a8d7c0d
--- /dev/null
+++ b/lib/cubit/settings_cubit.dart
@@ -0,0 +1,46 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+part 'settings_state.dart';
+
+class SettingsCubit extends HydratedCubit<SettingsState> {
+  SettingsCubit() : super(const SettingsState());
+
+  String getSetting(String key, [String? defaultValue]) {
+    if (state.values.keys.contains(key)) {
+      return state.values[key] ?? defaultValue ?? '';
+    }
+
+    return defaultValue ?? '';
+  }
+
+  void setValues({
+    String? apiUrl,
+    String? securityToken,
+  }) {
+    emit(SettingsState(
+      apiUrl: apiUrl != null ? apiUrl : state.apiUrl,
+      securityToken: securityToken != null ? securityToken : state.securityToken,
+    ));
+  }
+
+  @override
+  SettingsState? fromJson(Map<String, dynamic> json) {
+    String apiUrl = json['apiUrl'] as String;
+    String securityToken = json['securityToken'] as String;
+
+    return SettingsState(
+      apiUrl: apiUrl,
+      securityToken: securityToken,
+    );
+  }
+
+  @override
+  Map<String, String>? toJson(SettingsState state) {
+    return <String, String>{
+      'apiUrl': state.apiUrl ?? '',
+      'securityToken': state.securityToken ?? '',
+    };
+  }
+}
diff --git a/lib/cubit/settings_state.dart b/lib/cubit/settings_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..f435ed3db87719dc5d3fe3452fb440c27da62fc0
--- /dev/null
+++ b/lib/cubit/settings_state.dart
@@ -0,0 +1,23 @@
+part of 'settings_cubit.dart';
+
+@immutable
+class SettingsState extends Equatable {
+  const SettingsState({
+    this.apiUrl,
+    this.securityToken,
+  });
+
+  final String? apiUrl;
+  final String? securityToken;
+
+  @override
+  List<String?> get props => <String?>[
+        apiUrl,
+        securityToken,
+      ];
+
+  Map<String, String?> get values => <String, String?>{
+        'apiUrl': apiUrl,
+        'securityToken': securityToken,
+      };
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/settings_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..133372a54a9659f2508508a381e3addf4beb2ea0
--- /dev/null
+++ b/lib/ui/screens/settings_page.dart
@@ -0,0 +1,27 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+import 'package:random/ui/widgets/settings_form.dart';
+
+class SettingsPage extends StatelessWidget {
+  const SettingsPage({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        SizedBox(height: 50),
+        Text(
+          'settings_title',
+          textAlign: TextAlign.start,
+          style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
+        ).tr(),
+        SizedBox(height: 8),
+        SettingsForm(),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/screens/skeleton_screen.dart b/lib/ui/screens/skeleton_screen.dart
index 4c43b9b17d9a55c530deaa4a85c921fc00fdd7c0..412847e212f29e1505cd30eb7204ab2087b01ba2 100644
--- a/lib/ui/screens/skeleton_screen.dart
+++ b/lib/ui/screens/skeleton_screen.dart
@@ -4,7 +4,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:random/activities/ActivityDemoPage.dart';
 import 'package:random/activities/ActivityGraphPage.dart';
 import 'package:random/cubit/bottom_nav_cubit.dart';
+import 'package:random/cubit/settings_cubit.dart';
 import 'package:random/ui/screens/about_page.dart';
+import 'package:random/ui/screens/settings_page.dart';
 import 'package:random/ui/widgets/custom_app_bar.dart';
 import 'package:random/ui/widgets/bottom_nav_bar.dart';
 
@@ -16,23 +18,27 @@ class SkeletonScreen extends StatelessWidget {
     const List<Widget> pageNavigation = <Widget>[
       ActivityDemoPage(),
       ActivityGraphPage(),
+      SettingsPage(),
       AboutPage(),
     ];
 
-    return BlocProvider<BottomNavCubit>(
-      create: (BuildContext context) => BottomNavCubit(),
-      child: Scaffold(
-        extendBodyBehindAppBar: true,
-        appBar: const CustomAppBarGone(),
-        body: BlocBuilder<BottomNavCubit, int>(
-          builder: (BuildContext context, int state) {
-            return AnimatedSwitcher(
-                duration: const Duration(milliseconds: 300),
-                child: pageNavigation.elementAt(state));
-          },
+    return BlocProvider<SettingsCubit>(
+      create: (BuildContext context) => SettingsCubit(),
+      child: BlocProvider<BottomNavCubit>(
+        create: (BuildContext context) => BottomNavCubit(),
+        child: Scaffold(
+          extendBodyBehindAppBar: true,
+          appBar: const CustomAppBarGone(),
+          body: BlocBuilder<BottomNavCubit, int>(
+            builder: (BuildContext context, int state) {
+              return AnimatedSwitcher(
+                  duration: const Duration(milliseconds: 300),
+                  child: pageNavigation.elementAt(state));
+            },
+          ),
+          bottomNavigationBar: const BottomNavBar(),
+          backgroundColor: Theme.of(context).colorScheme.background,
         ),
-        bottomNavigationBar: const BottomNavBar(),
-        backgroundColor: Theme.of(context).colorScheme.background,
       ),
     );
   }
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
index 5e6f7106eaa7c68a2b9b85440ae307b3abd8c855..445b4f5ad9bc945bbf2b5a1fd1e02c8a09e24f6d 100644
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ b/lib/ui/widgets/bottom_nav_bar.dart
@@ -39,6 +39,10 @@ class BottomNavBar extends StatelessWidget {
               icon: const Icon(Ionicons.pencil_outline),
               label: tr('bottom_nav_chart'),
             ),
+            BottomNavigationBarItem(
+              icon: const Icon(Ionicons.settings_outline),
+              label: tr('bottom_nav_settings'),
+            ),
             BottomNavigationBarItem(
               icon: const Icon(Ionicons.information_circle),
               label: tr('bottom_nav_about'),
diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart
new file mode 100644
index 0000000000000000000000000000000000000000..e0a6e853c0968c178fa14e797e59809ff91d81fc
--- /dev/null
+++ b/lib/ui/widgets/settings_form.dart
@@ -0,0 +1,79 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:random/cubit/bottom_nav_cubit.dart';
+import 'package:random/cubit/settings_cubit.dart';
+
+class SettingsForm extends StatefulWidget {
+  const SettingsForm({super.key});
+
+  @override
+  State<SettingsForm> createState() => _SettingsFormState();
+}
+
+class _SettingsFormState extends State<SettingsForm> {
+  final apiUrlController = TextEditingController();
+  final securityTokenController = TextEditingController();
+
+  @override
+  void dispose() {
+    apiUrlController.dispose();
+    securityTokenController.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
+
+    apiUrlController.text = settings.getSetting('apiUrl');
+    securityTokenController.text = settings.getSetting('securityToken');
+
+    void saveSettings() {
+      BlocProvider.of<SettingsCubit>(context).setValues(
+        apiUrl: apiUrlController.text,
+        securityToken: securityTokenController.text,
+      );
+
+      BlocProvider.of<BottomNavCubit>(context).getDemoPage();
+    }
+
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        Text('settings_label_api_url').tr(),
+        TextFormField(
+          controller: apiUrlController,
+          decoration: InputDecoration(
+            border: UnderlineInputBorder(),
+          ),
+        ),
+        SizedBox(height: 16),
+        Text('settings_label_security_token').tr(),
+        TextFormField(
+          controller: securityTokenController,
+          decoration: InputDecoration(
+            border: UnderlineInputBorder(),
+          ),
+        ),
+        SizedBox(height: 16),
+        ElevatedButton(
+          child: Row(
+            mainAxisAlignment: MainAxisAlignment.center,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              Icon(UniconsLine.save),
+              SizedBox(width: 8),
+              Text('settings_button_save').tr(),
+            ],
+          ),
+          onPressed: () => saveSettings(),
+        ),
+      ],
+    );
+  }
+}
diff --git a/pubspec.lock b/pubspec.lock
index 814ae8dc78a2e43816019f755a174bd6a6549363..f09ef341ba589f2539fb9e183e59ffe49fff7809 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -325,6 +325,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.2"
+  unicons:
+    dependency: "direct main"
+    description:
+      name: unicons
+      sha256: dbfcf93ff4d4ea19b324113857e358e4882115ab85db04417a4ba1c72b17a670
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.1.1"
   vector_math:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 8afde1c436f9b90abf159446c23b4d562ad1f333..dfa6e18b1cab9270697726fc6c0da22fc3fc7eb1 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: A random application, for testing purpose only.
 
 publish_to: 'none'
 
-version: 1.0.25+26
+version: 1.0.26+27
 
 environment:
   sdk: '^3.0.0'
@@ -18,6 +18,7 @@ dependencies:
   path_provider: ^2.0.11
   hydrated_bloc: ^9.0.0
   ionicons: ^0.2.2
+  unicons: ^2.1.1
 
 flutter:
   uses-material-design: false