diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt
index 11638837cc..96e52469c3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt
@@ -75,6 +75,11 @@ data class HomeServerCapabilities(
          * True if the home server supports remote toggle of Pusher for a given device.
          */
         val canRemotelyTogglePushNotificationsOfDevices: Boolean = false,
+
+        /**
+         * True if the home server supports event redaction with relations.
+         */
+        var canRedactEventWithRelations: Boolean = false,
 ) {
 
     enum class RoomCapabilitySupport {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt
index f4de6a9ae9..4d8e90cf35 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/version/Versions.kt
@@ -58,6 +58,8 @@ private const val FEATURE_QR_CODE_LOGIN = "org.matrix.msc3882"
 private const val FEATURE_THREADS_MSC3771 = "org.matrix.msc3771"
 private const val FEATURE_THREADS_MSC3773 = "org.matrix.msc3773"
 private const val FEATURE_REMOTE_TOGGLE_PUSH_NOTIFICATIONS_MSC3881 = "org.matrix.msc3881"
+private const val FEATURE_EVENT_REDACTION_WITH_RELATIONS = "org.matrix.msc3912"
+private const val FEATURE_EVENT_REDACTION_WITH_RELATIONS_STABLE = "org.matrix.msc3912.stable"
 
 /**
  * Return true if the SDK supports this homeserver version.
@@ -153,3 +155,13 @@ private fun Versions.getMaxVersion(): HomeServerVersion {
 internal fun Versions.doesServerSupportRemoteToggleOfPushNotifications(): Boolean {
     return unstableFeatures?.get(FEATURE_REMOTE_TOGGLE_PUSH_NOTIFICATIONS_MSC3881).orFalse()
 }
+
+/**
+ * Indicate if the server supports MSC3912: https://github.com/matrix-org/matrix-spec-proposals/pull/3912.
+ *
+ * @return true if event redaction with relations is supported
+ */
+internal fun Versions.doesServerSupportRedactEventWithRelations(): Boolean {
+    return unstableFeatures?.get(FEATURE_EVENT_REDACTION_WITH_RELATIONS).orFalse() ||
+            unstableFeatures?.get(FEATURE_EVENT_REDACTION_WITH_RELATIONS_STABLE).orFalse()
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt
index 56bdc8cae8..5f645c4880 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/RedactEventTask.kt
@@ -15,8 +15,10 @@
  */
 package org.matrix.android.sdk.internal.crypto.tasks
 
+import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
 import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
 import org.matrix.android.sdk.internal.network.executeRequest
+import org.matrix.android.sdk.internal.session.room.EventRedactBody
 import org.matrix.android.sdk.internal.session.room.RoomAPI
 import org.matrix.android.sdk.internal.task.Task
 import javax.inject.Inject
@@ -26,22 +28,31 @@ internal interface RedactEventTask : Task<RedactEventTask.Params, String> {
             val txID: String,
             val roomId: String,
             val eventId: String,
-            val reason: String?
+            val reason: String?,
+            val withRelations: List<String>?
     )
 }
 
 internal class DefaultRedactEventTask @Inject constructor(
         private val roomAPI: RoomAPI,
-        private val globalErrorReceiver: GlobalErrorReceiver
+        private val globalErrorReceiver: GlobalErrorReceiver,
+        private val homeServerCapabilitiesService: HomeServerCapabilitiesService,
 ) : RedactEventTask {
 
     override suspend fun execute(params: RedactEventTask.Params): String {
+        val withRelations = if (homeServerCapabilitiesService.getHomeServerCapabilities().canRedactEventWithRelations &&
+                !params.withRelations.isNullOrEmpty()) {
+            params.withRelations
+        } else {
+            null
+        }
+
         val response = executeRequest(globalErrorReceiver) {
             roomAPI.redactEvent(
                     txId = params.txID,
                     roomId = params.roomId,
                     eventId = params.eventId,
-                    reason = if (params.reason == null) emptyMap() else mapOf("reason" to params.reason)
+                    body = EventRedactBody(params.reason, withRelations)
             )
         }
         return response.eventId
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt
index 89657ad882..83f3e87d05 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/HomeServerCapabilitiesMapper.kt
@@ -47,6 +47,7 @@ internal object HomeServerCapabilitiesMapper {
                 canLoginWithQrCode = entity.canLoginWithQrCode,
                 canUseThreadReadReceiptsAndNotifications = entity.canUseThreadReadReceiptsAndNotifications,
                 canRemotelyTogglePushNotificationsOfDevices = entity.canRemotelyTogglePushNotificationsOfDevices,
+                canRedactEventWithRelations = entity.canRedactEventWithRelations,
         )
     }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt
index 2b60f7723c..9acdcde7e5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/HomeServerCapabilitiesEntity.kt
@@ -34,6 +34,7 @@ internal open class HomeServerCapabilitiesEntity(
         var canLoginWithQrCode: Boolean = false,
         var canUseThreadReadReceiptsAndNotifications: Boolean = false,
         var canRemotelyTogglePushNotificationsOfDevices: Boolean = false,
+        var canRedactEventWithRelations: Boolean = false,
 ) : RealmObject() {
 
     companion object
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt
index 11e86a5c51..5a6107821d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/homeserver/GetHomeServerCapabilitiesTask.kt
@@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilities
 import org.matrix.android.sdk.internal.auth.version.Versions
 import org.matrix.android.sdk.internal.auth.version.doesServerSupportLogoutDevices
 import org.matrix.android.sdk.internal.auth.version.doesServerSupportQrCodeLogin
+import org.matrix.android.sdk.internal.auth.version.doesServerSupportRedactEventWithRelations
 import org.matrix.android.sdk.internal.auth.version.doesServerSupportRemoteToggleOfPushNotifications
 import org.matrix.android.sdk.internal.auth.version.doesServerSupportThreadUnreadNotifications
 import org.matrix.android.sdk.internal.auth.version.doesServerSupportThreads
@@ -154,6 +155,8 @@ internal class DefaultGetHomeServerCapabilitiesTask @Inject constructor(
                         getVersionResult.doesServerSupportQrCodeLogin()
                 homeServerCapabilitiesEntity.canRemotelyTogglePushNotificationsOfDevices =
                         getVersionResult.doesServerSupportRemoteToggleOfPushNotifications()
+                homeServerCapabilitiesEntity.canRedactEventWithRelations =
+                        getVersionResult.doesServerSupportRedactEventWithRelations()
             }
 
             if (getWellknownResult != null && getWellknownResult is WellknownResult.Prompt) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRedactBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRedactBody.kt
new file mode 100644
index 0000000000..00778754e6
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRedactBody.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.room
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+internal data class EventRedactBody(
+        @Json(name = "reason")
+        val reason: String? = null,
+
+        @Json(name = "with_relations")
+        val withRelations: List<String>? = null
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
index 34b6ee525d..c76ee4537d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/RoomAPI.kt
@@ -350,14 +350,14 @@ internal interface RoomAPI {
      * @param txId the transaction Id
      * @param roomId the room id
      * @param eventId the event to delete
-     * @param reason json containing reason key {"reason": "Indecent material"}
+     * @param body body containing reason key {"reason": "Indecent material"} and with_relations
      */
     @PUT(NetworkConstants.URI_API_PREFIX_PATH_R0 + "rooms/{roomId}/redact/{eventId}/{txnId}")
     suspend fun redactEvent(
             @Path("txnId") txId: String,
             @Path("roomId") roomId: String,
             @Path("eventId") eventId: String,
-            @Body reason: Map<String, String>
+            @Body body: EventRedactBody
     ): SendResponse
 
     /**
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt
index 050e321b9c..b1a37d9824 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessor.kt
@@ -26,9 +26,9 @@ internal interface EventSenderProcessor : SessionLifecycleObserver {
 
     fun postEvent(event: Event, encrypt: Boolean): Cancelable
 
-    fun postRedaction(redactionLocalEcho: Event, reason: String?): Cancelable
+    fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List<String>?): Cancelable
 
-    fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?): Cancelable
+    fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelations: List<String>?): Cancelable
 
     fun postTask(task: QueuedTask): Cancelable
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt
index 2c7eea1e54..e72fcd8b1e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/EventSenderProcessorCoroutine.kt
@@ -101,12 +101,12 @@ internal class EventSenderProcessorCoroutine @Inject constructor(
         return postTask(task)
     }
 
-    override fun postRedaction(redactionLocalEcho: Event, reason: String?): Cancelable {
-        return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason)
+    override fun postRedaction(redactionLocalEcho: Event, reason: String?, withRelations: List<String>?): Cancelable {
+        return postRedaction(redactionLocalEcho.eventId!!, redactionLocalEcho.redacts!!, redactionLocalEcho.roomId!!, reason, withRelations)
     }
 
-    override fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?): Cancelable {
-        val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason)
+    override fun postRedaction(redactionLocalEchoId: String, eventToRedactId: String, roomId: String, reason: String?, withRelations: List<String>?): Cancelable {
+        val task = queuedTaskFactory.createRedactTask(redactionLocalEchoId, eventToRedactId, roomId, reason, withRelations)
         return postTask(task)
     }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt
index 90bb47c435..973f70cdcf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/QueuedTaskFactory.kt
@@ -43,12 +43,13 @@ internal class QueuedTaskFactory @Inject constructor(
         )
     }
 
-    fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?): QueuedTask {
+    fun createRedactTask(redactionLocalEcho: String, eventId: String, roomId: String, reason: String?, withRelations: List<String>?): QueuedTask {
         return RedactQueuedTask(
                 redactionLocalEchoId = redactionLocalEcho,
                 toRedactEventId = eventId,
                 roomId = roomId,
                 reason = reason,
+                withRelations = withRelations,
                 redactEventTask = redactEventTask,
                 localEchoRepository = localEchoRepository,
                 cancelSendTracker = cancelSendTracker
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt
index 0e3d88aa79..f484c24aae 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/queue/RedactQueuedTask.kt
@@ -26,13 +26,14 @@ internal class RedactQueuedTask(
         val redactionLocalEchoId: String,
         private val roomId: String,
         private val reason: String?,
+        private val withRelations: List<String>?,
         private val redactEventTask: RedactEventTask,
         private val localEchoRepository: LocalEchoRepository,
         private val cancelSendTracker: CancelSendTracker
 ) : QueuedTask(queueIdentifier = roomId, taskIdentifier = redactionLocalEchoId) {
 
     override suspend fun doExecute() {
-        redactEventTask.execute(RedactEventTask.Params(redactionLocalEchoId, roomId, toRedactEventId, reason))
+        redactEventTask.execute(RedactEventTask.Params(redactionLocalEchoId, roomId, toRedactEventId, reason, withRelations))
     }
 
     override fun onTaskFailed() {