diff --git a/lib/actions/message-report-actions.js b/lib/actions/message-report-actions.js
new file mode 100644
--- /dev/null
+++ b/lib/actions/message-report-actions.js
@@ -0,0 +1,19 @@
+// @flow
+
+import type { MessageReportCreationRequest } from '../types/message-report-types';
+import type { FetchJSON } from '../utils/fetch-json';
+
+const sendMessageReportActionTypes = Object.freeze({
+  started: 'SEND_MESSAGE_REPORT_STARTED',
+  success: 'SEND_MESSAGE_REPORT_SUCCESS',
+  failed: 'SEND_MESSAGE_REPORT_FAILED',
+});
+const sendMessageReport = (
+  fetchJSON: FetchJSON,
+): ((
+  request: MessageReportCreationRequest,
+) => Promise<void>) => async request => {
+  await fetchJSON('create_message_report', request);
+};
+
+export { sendMessageReportActionTypes, sendMessageReport };
diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js
--- a/lib/types/redux-types.js
+++ b/lib/types/redux-types.js
@@ -801,6 +801,18 @@
       +type: 'SET_USER_SETTINGS_FAILED',
       +payload: Error,
       +loadingInfo: LoadingInfo,
+    }
+  | {
+      +type: 'SEND_MESSAGE_REPORT_STARTED',
+      +payload?: void,
+    }
+  | {
+      +type: 'SEND_MESSAGE_REPORT_SUCCESS',
+      +payload?: void,
+    }
+  | {
+      +type: 'SEND_MESSAGE_REPORT_FAILED',
+      +payload?: void,
     };
 
 export type ActionPayload = ?(Object | Array<*> | $ReadOnlyArray<*> | string);
diff --git a/native/chat/message-report-utils.js b/native/chat/message-report-utils.js
new file mode 100644
--- /dev/null
+++ b/native/chat/message-report-utils.js
@@ -0,0 +1,44 @@
+// @flow
+
+import Alert from 'react-native/Libraries/Alert/Alert';
+
+import {
+  sendMessageReport,
+  sendMessageReportActionTypes,
+} from 'lib/actions/message-report-actions';
+import type { ActionFunc, DispatchFunctions } from 'lib/utils/action-utils';
+
+import { displayActionResultModal } from '../navigation/action-result-modal';
+
+const confirmReport = () => displayActionResultModal('reported to admin');
+
+function handleMessageReport(
+  request: string,
+  dispatchFunctions: DispatchFunctions,
+  bindServerCall: <F>(serverCall: ActionFunc<F>) => F,
+) {
+  const callSendMessageReport = bindServerCall(sendMessageReport);
+  const messageReportPromise = async function () {
+    try {
+      await callSendMessageReport({ messageID: request });
+    } catch (e) {
+      Alert.alert(
+        'Couldn’t send the report',
+        'Uhh... try again?',
+        [{ text: 'OK' }],
+        {
+          cancelable: false,
+        },
+      );
+      throw e;
+    }
+    confirmReport();
+  };
+
+  dispatchFunctions.dispatchActionPromise(
+    sendMessageReportActionTypes,
+    messageReportPromise(),
+  );
+}
+
+export { handleMessageReport };
diff --git a/native/chat/multimedia-message-tooltip-modal.react.js b/native/chat/multimedia-message-tooltip-modal.react.js
--- a/native/chat/multimedia-message-tooltip-modal.react.js
+++ b/native/chat/multimedia-message-tooltip-modal.react.js
@@ -2,15 +2,18 @@
 
 import * as React from 'react';
 
-import { displayActionResultModal } from '../navigation/action-result-modal';
+import type { DispatchFunctions, ActionFunc } from 'lib/utils/action-utils';
+
 import {
   createTooltip,
   tooltipHeight,
   type TooltipParams,
   type BaseTooltipProps,
 } from '../navigation/tooltip.react';
+import type { TooltipRoute } from '../navigation/tooltip.react';
 import type { ChatMultimediaMessageInfoItem } from '../types/chat-types';
 import type { VerticalBounds } from '../types/layout-types';
+import { handleMessageReport } from './message-report-utils';
 import MultimediaMessageTooltipButton from './multimedia-message-tooltip-button.react';
 import { navigateToSidebar } from './sidebar-navigation';
 
@@ -19,7 +22,15 @@
   +verticalBounds: VerticalBounds,
 }>;
 
-const confirmReport = () => displayActionResultModal('reported to admin');
+function onPressReport(
+  route: TooltipRoute<'MultimediaMessageTooltipModal'>,
+  dispatchFunctions: DispatchFunctions,
+  bindServerCall: <F>(serverCall: ActionFunc<F>) => F,
+) {
+  const request = route.params.item.messageInfo.id ?? 'null';
+  handleMessageReport(request, dispatchFunctions, bindServerCall);
+}
+
 const spec = {
   entries: [
     {
@@ -35,7 +46,7 @@
     {
       id: 'report',
       text: 'Report',
-      onPress: confirmReport,
+      onPress: onPressReport,
     },
   ],
 };
diff --git a/native/chat/text-message-tooltip-modal.react.js b/native/chat/text-message-tooltip-modal.react.js
--- a/native/chat/text-message-tooltip-modal.react.js
+++ b/native/chat/text-message-tooltip-modal.react.js
@@ -17,6 +17,7 @@
   type BaseTooltipProps,
 } from '../navigation/tooltip.react';
 import type { ChatTextMessageInfoItemWithHeight } from '../types/chat-types';
+import { handleMessageReport } from './message-report-utils';
 import { navigateToSidebar } from './sidebar-navigation';
 import TextMessageTooltipButton from './text-message-tooltip-button.react';
 
@@ -25,7 +26,6 @@
 }>;
 
 const confirmCopy = () => displayActionResultModal('copied!');
-const confirmReport = () => displayActionResultModal('reported to admin');
 
 function onPressCopy(route: TooltipRoute<'TextMessageTooltipModal'>) {
   Clipboard.setString(route.params.item.messageInfo.text);
@@ -45,6 +45,15 @@
   inputState.addReply(createMessageReply(route.params.item.messageInfo.text));
 }
 
+function onPressReport(
+  route: TooltipRoute<'TextMessageTooltipModal'>,
+  dispatchFunctions: DispatchFunctions,
+  bindServerCall: <F>(serverCall: ActionFunc<F>) => F,
+) {
+  const request = route.params.item.messageInfo.id ?? 'null';
+  handleMessageReport(request, dispatchFunctions, bindServerCall);
+}
+
 const spec = {
   entries: [
     { id: 'copy', text: 'Copy', onPress: onPressCopy },
@@ -52,7 +61,7 @@
     {
       id: 'report',
       text: 'Report',
-      onPress: confirmReport,
+      onPress: onPressReport,
     },
     {
       id: 'create_sidebar',