diff --git a/lib/actions/message-actions.js b/lib/actions/message-actions.js
--- a/lib/actions/message-actions.js
+++ b/lib/actions/message-actions.js
@@ -5,6 +5,8 @@
 import type {
   FetchMessageInfosPayload,
   SendMessageResult,
+  SendReactionMessageRequest,
+  SendReactionMessageResult,
   SimpleMessagesPayload,
 } from '../types/message-types';
 import type { MediaMessageServerDBContent } from '../types/messages/media.js';
@@ -201,6 +203,22 @@
   success: 'SEND_REACTION_MESSAGE_SUCCESS',
   failed: 'SEND_REACTION_MESSAGE_FAILED',
 });
+const sendReactionMessage = (
+  callServerEndpoint: CallServerEndpoint,
+): ((
+  request: SendReactionMessageRequest,
+) => Promise<SendReactionMessageResult>) => async request => {
+  const response = await callServerEndpoint('create_reaction_message', {
+    threadID: request.threadID,
+    targetMessageID: request.targetMessageID,
+    reaction: request.reaction,
+    action: request.action,
+  });
+  return {
+    id: response.newMessageInfo.id,
+    newMessageInfo: response.newMessageInfo,
+  };
+};
 
 const saveMessagesActionType = 'SAVE_MESSAGES';
 const processMessagesActionType = 'PROCESS_MESSAGES';
@@ -220,6 +238,7 @@
   sendMultimediaMessage,
   legacySendMultimediaMessage,
   sendReactionMessageActionTypes,
+  sendReactionMessage,
   saveMessagesActionType,
   processMessagesActionType,
   messageStorePruneActionType,
diff --git a/lib/types/message-types.js b/lib/types/message-types.js
--- a/lib/types/message-types.js
+++ b/lib/types/message-types.js
@@ -532,6 +532,12 @@
   +time: number,
   +interface: CallServerEndpointResultInfoInterface,
 };
+
+export type SendReactionMessageResult = {
+  +id: string,
+  +newMessageInfo: RawMessageInfo,
+};
+
 export type SendMessagePayload = {
   +localID: string,
   +serverID: string,