diff --git a/android/gradle.properties b/android/gradle.properties
index 7aef769d163302288fe58ec83e6b4f3d21afd030..8f1cf62360192199ae6a5e17a062114475c411bc 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.36
-app.versionCode=37
+app.versionName=1.0.37
+app.versionCode=38
diff --git a/assets/translations/en.json b/assets/translations/en.json
index d90a462d962ae53f8ef610e33ab4bc347b0a5909..e57ee8a1085d69a27cfce73eaa027ae8bdb146ab 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -2,10 +2,13 @@
   "app_name": "Sandbox App",
 
   "bottom_nav_sample": "Sample",
+  "bottom_nav_api": "API",
   "bottom_nav_chart": "Graph",
   "bottom_nav_settings": "Settings",
   "bottom_nav_about": "About",
 
+  "api_page_title": "API",
+
   "settings_title": "Settings",
   "settings_label_api_url": "API URL:",
   "settings_label_security_token": "Security token:",
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 67575f68dbb45583075ae61204c3a66c79a1fba2..ef1e45bbdd2bdd2d787f6838a3ee09a145086988 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -2,10 +2,13 @@
   "app_name": "App de test",
 
   "bottom_nav_sample": "Démo",
+  "bottom_nav_api": "API",
   "bottom_nav_chart": "Graph",
   "bottom_nav_settings": "Paramètres",
   "bottom_nav_about": "À propos",
 
+  "api_page_title": "API",
+
   "settings_title": "Paramètres",
   "settings_label_api_url": "URL de l'API :",
   "settings_label_security_token": "Jeton de sécurité :",
diff --git a/lib/cubit/api_cubit.dart b/lib/cubit/api_cubit.dart
new file mode 100644
index 0000000000000000000000000000000000000000..27b9f29f23600566ae274aaf16bc9b5a002e319f
--- /dev/null
+++ b/lib/cubit/api_cubit.dart
@@ -0,0 +1,62 @@
+import 'package:equatable/equatable.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:random/models/api_failure.dart';
+import 'package:random/models/api_data.dart';
+import 'package:random/repository/api.dart';
+
+part 'api_state.dart';
+
+class ApiDataCubit extends HydratedCubit<ApiDataState> {
+  final ApiRepository apiRepository;
+
+  ApiDataCubit({required this.apiRepository}) : super(ApiDataFetchInitial());
+
+  void customEmit(ApiDataState state) {
+    String stateAsString = '';
+    if (state is ApiDataFetchLoaded) {
+      stateAsString = 'ApiDataFetchLoaded';
+    } else {
+      if (state is ApiDataFetchLoading) {
+        stateAsString = 'ApiDataFetchLoading';
+      } else {
+        if (state is ApiDataFetchError) {
+          stateAsString = 'ApiDataFetchError';
+        } else {
+          stateAsString = 'unknown';
+        }
+      }
+    }
+    print('emit new state: ' + stateAsString);
+
+    emit(state);
+  }
+
+  Future<ApiData> fetchApiData() async {
+    customEmit(ApiDataFetchLoading());
+    try {
+      final ApiData apiData = await apiRepository.getApiData();
+      customEmit(ApiDataFetchLoaded(data: apiData));
+      return apiData;
+    } on ApiFailure catch (err) {
+      customEmit(ApiDataFetchError(failure: err));
+    } catch (err) {
+      print("Error (fetchApiData): $err");
+    }
+    return ApiData.fromJson({});
+  }
+
+  @override
+  ApiDataState? fromJson(Map<String, dynamic> json) {
+    return ApiDataState(
+      data: ApiData.fromJson(json['api-data']),
+    );
+  }
+
+  @override
+  Map<String, Object?>? toJson(ApiDataState state) {
+    return <String, Object?>{
+      'api-data': state.data?.toJson(),
+    };
+  }
+}
diff --git a/lib/cubit/api_state.dart b/lib/cubit/api_state.dart
new file mode 100644
index 0000000000000000000000000000000000000000..a930be04aa0c3a19f072e8155bbba47cc2363107
--- /dev/null
+++ b/lib/cubit/api_state.dart
@@ -0,0 +1,38 @@
+part of 'api_cubit.dart';
+
+class ApiDataState extends Equatable {
+  final ApiData? data;
+
+  const ApiDataState({
+    this.data,
+  });
+
+  @override
+  List<Object> get props => [];
+}
+
+class ApiDataFetchInitial extends ApiDataState {}
+
+class ApiDataFetchLoading extends ApiDataState {}
+
+class ApiDataFetchLoaded extends ApiDataState {
+  final ApiData data;
+
+  const ApiDataFetchLoaded({
+    required this.data,
+  });
+
+  @override
+  List<Object> get props => [data];
+}
+
+class ApiDataFetchError extends ApiDataState {
+  final ApiFailure failure;
+
+  const ApiDataFetchError({
+    required this.failure,
+  });
+
+  @override
+  List<Object> get props => [failure];
+}
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/bottom_nav_cubit.dart
index 177572b02aa306afe9bd9c25242001e02ba684b1..98ff898e6e0e4bc0e5f7784b40462ccb1cf1e8d3 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/bottom_nav_cubit.dart
@@ -3,7 +3,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
 class BottomNavCubit extends HydratedCubit<int> {
   BottomNavCubit() : super(0);
 
-  int pagesCount = 4;
+  int pagesCount = 5;
 
   void updateIndex(int index) {
     if (isIndexAllowed(index)) {
@@ -20,8 +20,8 @@ class BottomNavCubit extends HydratedCubit<int> {
   void goToHomePage() => emit(0);
 
   @override
-  int? fromJson(Map<String, dynamic> json) {
-    return json['pageIndex'] as int?;
+  int fromJson(Map<String, dynamic> json) {
+    return 0;
   }
 
   @override
diff --git a/lib/main.dart b/lib/main.dart
index 1a3b173e360e25bcfe6b0e4d852092df8cfe0154..765b84c7b8b3c00e7e4489d11ab5d77670453128 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -11,6 +11,9 @@ import 'package:random/config/theme.dart';
 import 'package:random/cubit/bottom_nav_cubit.dart';
 import 'package:random/cubit/data_cubit.dart';
 import 'package:random/cubit/settings_cubit.dart';
+import 'package:random/cubit/api_cubit.dart';
+import 'package:random/repository/api.dart';
+import 'package:random/network/api.dart';
 import 'package:random/ui/skeleton.dart';
 
 void main() async {
@@ -47,6 +50,13 @@ class MyApp extends StatelessWidget {
         BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
         BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
         BlocProvider<DataCubit>(create: (context) => DataCubit()),
+        BlocProvider<ApiDataCubit>(
+          create: (context) => ApiDataCubit(
+            apiRepository: ApiRepository(
+              apiService: ApiService(),
+            ),
+          )..fetchApiData(),
+        ),
       ],
       child: MaterialApp(
         title: 'Random application',
diff --git a/lib/models/api_data.dart b/lib/models/api_data.dart
new file mode 100644
index 0000000000000000000000000000000000000000..8124108688a3ea77eaa5167d6dae2f52938730ca
--- /dev/null
+++ b/lib/models/api_data.dart
@@ -0,0 +1,33 @@
+import 'dart:convert';
+
+class ApiData {
+  final int? number;
+  final String? md5;
+  final DateTime? updatedAt;
+
+  const ApiData({
+    required this.number,
+    required this.md5,
+    required this.updatedAt,
+  });
+
+  factory ApiData.fromJson(Map<String, dynamic>? json) {
+    return ApiData(
+      number: (json?['number'] != null) ? (json?['number'] as int) : null,
+      md5: (json?['md5'] != null) ? (json?['md5'] as String) : null,
+      updatedAt: (json?['now'] != null) ? DateTime.parse(json?['now']) : null,
+    );
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'number': this.number ?? 0,
+      'md5': this.md5 ?? '',
+      'updatedAt': this.updatedAt?.toString(),
+    };
+  }
+
+  String toString() {
+    return jsonEncode(this.toJson());
+  }
+}
diff --git a/lib/models/api_failure.dart b/lib/models/api_failure.dart
new file mode 100644
index 0000000000000000000000000000000000000000..3ee6a8079c991b0cb159d52a1d03b278fcdf9d39
--- /dev/null
+++ b/lib/models/api_failure.dart
@@ -0,0 +1,9 @@
+class ApiFailure {
+  final String message;
+  final String code;
+
+  const ApiFailure({
+    this.message = '',
+    this.code = '',
+  });
+}
diff --git a/lib/models/api_status.dart b/lib/models/api_status.dart
new file mode 100644
index 0000000000000000000000000000000000000000..04933cac42c5687e38d10134abdf8a1ee1eb5080
--- /dev/null
+++ b/lib/models/api_status.dart
@@ -0,0 +1,5 @@
+enum ApiStatus {
+  loading,
+  loaded,
+  failed,
+}
diff --git a/lib/network/api.dart b/lib/network/api.dart
new file mode 100644
index 0000000000000000000000000000000000000000..23a620791df9af6319e2ac65bfac230a008e87ad
--- /dev/null
+++ b/lib/network/api.dart
@@ -0,0 +1,27 @@
+import 'dart:io';
+
+import 'package:dio/dio.dart';
+
+import 'package:random/models/api_failure.dart';
+
+class ApiService {
+  final Dio _dio = Dio();
+
+  final String baseUrl = 'https://tools.harrault.fr/tools/api';
+
+  Future<Response?> getData() async {
+    String url = baseUrl + '/get.php';
+    try {
+      print('fetching api data... ' + url);
+      final Response? response = await _dio.get(url);
+      print('ok got api response.');
+      print(response);
+      return response;
+    } on SocketException {
+      throw const ApiFailure(message: 'Failed to reach API endpoint.');
+    } catch (err) {
+      print("Error (getData): $err");
+      throw ApiFailure(message: "$err");
+    }
+  }
+}
diff --git a/lib/repository/api.dart b/lib/repository/api.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ce3a0ef9c2f4a65f93a6b0b7074351ce5da54d9e
--- /dev/null
+++ b/lib/repository/api.dart
@@ -0,0 +1,21 @@
+import 'package:random/models/api_data.dart';
+import 'package:random/network/api.dart';
+
+class ApiRepository {
+  const ApiRepository({required this.apiService});
+
+  final ApiService apiService;
+
+  Future<ApiData> getApiData() async {
+    print('(getApiData) delayed API call...');
+    final response = await Future.delayed(Duration(milliseconds: 1000))
+        .then((value) => apiService.getData());
+    if (response != null) {
+      print('(getApiData) got api response');
+      print(response.data);
+      return ApiData.fromJson(response.data);
+    }
+    print('(getApiData) failed');
+    return ApiData.fromJson({});
+  }
+}
diff --git a/lib/ui/screens/api_page.dart b/lib/ui/screens/api_page.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9b0253243a8513084a058be2fbcb056650d8927c
--- /dev/null
+++ b/lib/ui/screens/api_page.dart
@@ -0,0 +1,39 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:random/cubit/api_cubit.dart';
+import 'package:random/models/api_status.dart';
+import 'package:random/ui/widgets/api_data.dart';
+import 'package:random/ui/widgets/header_app.dart';
+
+class ApiPage extends StatelessWidget {
+  const ApiPage({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Material(
+      color: Theme.of(context).colorScheme.background,
+      child: ListView(
+        padding: const EdgeInsets.symmetric(horizontal: 4),
+        physics: const BouncingScrollPhysics(),
+        children: <Widget>[
+          SizedBox(height: 8),
+          AppHeader(text: 'api_page_title'),
+          SizedBox(height: 20),
+          BlocBuilder<ApiDataCubit, ApiDataState>(
+            builder: (BuildContext context, ApiDataState apiDataState) {
+              return ApiDataWidget(
+                data: apiDataState.data,
+                status: (apiDataState is ApiDataFetchLoading)
+                    ? ApiStatus.loading
+                    : (apiDataState is ApiDataFetchLoaded)
+                        ? ApiStatus.loaded
+                        : ApiStatus.failed,
+              );
+            },
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index 6492f6af94936851d4b0168ff4aa1b441c091872..f44393db9c3aee06006e962728fe4e521d7d5d8d 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -4,6 +4,7 @@ import 'package:flutter_swipe/flutter_swipe.dart';
 
 import 'package:random/cubit/bottom_nav_cubit.dart';
 import 'package:random/ui/screens/about_page.dart';
+import 'package:random/ui/screens/api_page.dart';
 import 'package:random/ui/screens/demo_page.dart';
 import 'package:random/ui/screens/graph_page.dart';
 import 'package:random/ui/screens/settings_page.dart';
@@ -22,6 +23,7 @@ class _SkeletonScreenState extends State<SkeletonScreen> {
   Widget build(BuildContext context) {
     const List<Widget> pageNavigation = <Widget>[
       DemoPage(),
+      ApiPage(),
       GraphPage(),
       SettingsPage(),
       AboutPage(),
diff --git a/lib/ui/widgets/api_data.dart b/lib/ui/widgets/api_data.dart
new file mode 100644
index 0000000000000000000000000000000000000000..36907922be8c5867e1d59bb1a91dc859eb885633
--- /dev/null
+++ b/lib/ui/widgets/api_data.dart
@@ -0,0 +1,39 @@
+import 'package:flutter/material.dart';
+import 'package:random/models/api_data.dart';
+import 'package:random/models/api_status.dart';
+import 'package:random/ui/widgets/error.dart';
+
+class ApiDataWidget extends StatelessWidget {
+  const ApiDataWidget({
+    super.key,
+    required this.status,
+    required this.data,
+  });
+
+  final ApiStatus status;
+  final ApiData? data;
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.center,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        Text('status: ' + status.toString()),
+        Text('number: ' + (this.data?.number.toString() ?? '')),
+        Text('md5: ' + (this.data?.md5.toString() ?? '')),
+        Text('updatedAt: ' + (this.data?.updatedAt.toString() ?? '')),
+        status == ApiStatus.loading
+            ? Container(
+                width: 12,
+                height: 12,
+                child: const CircularProgressIndicator(),
+              )
+            : const SizedBox.shrink(),
+        status == ApiStatus.failed
+            ? ShowErrorWidget(message: 'state.failure.message')
+            : const SizedBox.shrink(),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
index 1349c7ec91661e5dd28e79c1d5a61ad72d3d27af..9ab56ea6333ba956d3e362b20bf75c9586cbacd8 100644
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ b/lib/ui/widgets/bottom_nav_bar.dart
@@ -46,6 +46,10 @@ class BottomNavBar extends StatelessWidget {
                 icon: const Icon(UniconsLine.image),
                 label: tr('bottom_nav_sample'),
               ),
+              BottomNavigationBarItem(
+                icon: const Icon(UniconsLine.globe),
+                label: tr('bottom_nav_api'),
+              ),
               BottomNavigationBarItem(
                 icon: const Icon(UniconsLine.pen),
                 label: tr('bottom_nav_chart'),
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/header_app.dart
index af80150eeac8fa18482af7b2bbeefe37fb54326d..b19ad444d879c83bb8b8bf3982a27d5bdcf1e16a 100644
--- a/lib/ui/widgets/header_app.dart
+++ b/lib/ui/widgets/header_app.dart
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:random/cubit/data_cubit.dart';
+import 'package:random/cubit/api_cubit.dart';
 import 'package:random/cubit/settings_cubit.dart';
 import 'package:random/models/interface_type.dart';
 
@@ -26,6 +27,8 @@ class AppHeader extends StatelessWidget {
         expertInterfaceIndicator(),
         SizedBox(width: 2),
         dataCounterIndicator(),
+        SizedBox(width: 2),
+        apiLoadingIndicator(),
       ],
     );
   }
@@ -47,4 +50,16 @@ class AppHeader extends StatelessWidget {
       },
     );
   }
+
+  Widget apiLoadingIndicator() {
+    return BlocBuilder<ApiDataCubit, ApiDataState>(
+      builder: (context, apiDataState) {
+        return (apiDataState is ApiDataFetchLoading)
+            ? Text('⏳')
+            : (apiDataState is ApiDataFetchLoaded)
+                ? Text('✅')
+                : Text('⚠️');
+      },
+    );
+  }
 }
diff --git a/pubspec.lock b/pubspec.lock
index 131944004fd3d998e236c23c8eb60b8884508340..1b5533c24d0cf46bcaad81baa383d40e50b29b70 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -57,6 +57,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "3.0.3"
+  dio:
+    dependency: "direct main"
+    description:
+      name: dio
+      sha256: "417e2a6f9d83ab396ec38ff4ea5da6c254da71e4db765ad737a42af6930140b7"
+      url: "https://pub.dev"
+    source: hosted
+    version: "5.3.3"
   easy_localization:
     dependency: "direct main"
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 4e20996dfc1f224bada21a6f3daa4fd1f52aeae5..614ad4a20d09270ad2000c910371483f6c373fef 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.36+37
+version: 1.0.37+38
 
 environment:
   sdk: '^3.0.0'
@@ -20,6 +20,7 @@ dependencies:
   unicons: ^2.1.1
   package_info_plus: ^5.0.1
   flutter_swipe: ^1.0.1
+  dio: ^5.3.3
 
 flutter:
   uses-material-design: false