diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
index b67172a908..1a9165ade4 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt
@@ -245,7 +245,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
     fun createFakeMegolmBackupCreationInfo(): MegolmBackupCreationInfo {
         return MegolmBackupCreationInfo(
                 algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
-                authData = createFakeMegolmBackupAuthData()
+                authData = createFakeMegolmBackupAuthData(),
+                recoveryKey = "fake"
         )
     }
 
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
index ca8993fb00..8148d91e9c 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt
@@ -115,9 +115,8 @@ class KeysBackupTest : InstrumentedTest {
         }
 
         assertEquals(MXCRYPTO_ALGORITHM_MEGOLM_BACKUP, megolmBackupCreationInfo.algorithm)
-        assertNotNull(megolmBackupCreationInfo.authData)
-        assertNotNull(megolmBackupCreationInfo.authData!!.publicKey)
-        assertNotNull(megolmBackupCreationInfo.authData!!.signatures)
+        assertNotNull(megolmBackupCreationInfo.authData.publicKey)
+        assertNotNull(megolmBackupCreationInfo.authData.signatures)
         assertNotNull(megolmBackupCreationInfo.recoveryKey)
 
         stateObserver.stopAndCheckStates(null)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt
index 9f560bce2b..aaa6a1d4ca 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt
@@ -30,7 +30,6 @@ import org.matrix.android.sdk.api.listeners.StepProgressListener
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
-import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
 import org.matrix.android.sdk.internal.crypto.MXOlmDevice
 import org.matrix.android.sdk.internal.crypto.MegolmSessionData
@@ -85,6 +84,7 @@ import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
+import org.matrix.android.sdk.internal.crypto.keysbackup.model.SignalableMegolmBackupAuthData
 import org.matrix.olm.OlmException
 import org.matrix.olm.OlmPkDecryption
 import org.matrix.olm.OlmPkEncryption
@@ -170,7 +170,7 @@ internal class DefaultKeysBackupService @Inject constructor(
             runCatching {
                 withContext(coroutineDispatchers.crypto) {
                     val olmPkDecryption = OlmPkDecryption()
-                    val megolmBackupAuthData = if (password != null) {
+                    val signalableMegolmBackupAuthData = if (password != null) {
                         // Generate a private key from the password
                         val backgroundProgressListener = if (progressListener == null) {
                             null
@@ -189,7 +189,7 @@ internal class DefaultKeysBackupService @Inject constructor(
                         }
 
                         val generatePrivateKeyResult = generatePrivateKeyWithPassword(password, backgroundProgressListener)
-                        MegolmBackupAuthData(
+                        SignalableMegolmBackupAuthData(
                                 publicKey = olmPkDecryption.setPrivateKey(generatePrivateKeyResult.privateKey),
                                 privateKeySalt = generatePrivateKeyResult.salt,
                                 privateKeyIterations = generatePrivateKeyResult.iterations
@@ -197,14 +197,17 @@ internal class DefaultKeysBackupService @Inject constructor(
                     } else {
                         val publicKey = olmPkDecryption.generateKey()
 
-                        MegolmBackupAuthData(
+                        SignalableMegolmBackupAuthData(
                                 publicKey = publicKey
                         )
                     }
 
-                    val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, megolmBackupAuthData.signalableJSONDictionary())
+                    val canonicalJson = JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableMegolmBackupAuthData.signalableJSONDictionary())
 
-                    val signedMegolmBackupAuthData = megolmBackupAuthData.copy(
+                    val signedMegolmBackupAuthData = MegolmBackupAuthData(
+                            publicKey = signalableMegolmBackupAuthData.publicKey,
+                            privateKeySalt = signalableMegolmBackupAuthData.privateKeySalt,
+                            privateKeyIterations = signalableMegolmBackupAuthData.privateKeyIterations,
                             signatures = objectSigner.signObject(canonicalJson)
                     )
 
@@ -223,8 +226,7 @@ internal class DefaultKeysBackupService @Inject constructor(
         @Suppress("UNCHECKED_CAST")
         val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
                 algorithm = keysBackupCreationInfo.algorithm,
-                authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
-                        .fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
+                authData = keysBackupCreationInfo.authData.toJsonDict()
         )
 
         keysBackupStateManager.state = KeysBackupState.Enabling
@@ -245,7 +247,7 @@ internal class DefaultKeysBackupService @Inject constructor(
                                     version = data.version,
                                     // We can consider that the server does not have keys yet
                                     count = 0,
-                                    hash = null
+                                    hash = ""
                             )
 
                             enableKeysBackup(keyBackupVersion)
@@ -267,7 +269,7 @@ internal class DefaultKeysBackupService @Inject constructor(
             withContext(coroutineDispatchers.crypto) {
                 // If we're currently backing up to this backup... stop.
                 // (We start using it automatically in createKeysBackupVersion so this is symmetrical).
-                if (keysBackupVersion != null && version == keysBackupVersion!!.version) {
+                if (keysBackupVersion != null && version == keysBackupVersion?.version) {
                     resetKeysBackupData()
                     keysBackupVersion = null
                     keysBackupStateManager.state = KeysBackupState.Unknown
@@ -408,10 +410,7 @@ internal class DefaultKeysBackupService @Inject constructor(
         val keysBackupVersionTrust = KeysBackupVersionTrust()
         val authData = keysBackupVersion.getAuthDataAsMegolmBackupAuthData()
 
-        if (keysBackupVersion.algorithm == null
-                || authData == null
-                || authData.publicKey.isEmpty()
-                || authData.signatures.isNullOrEmpty()) {
+        if (authData == null || authData.publicKey.isEmpty() || authData.signatures.isEmpty()) {
             Timber.v("getKeysBackupTrust: Key backup is absent or missing required data")
             return keysBackupVersionTrust
         }
@@ -479,7 +478,7 @@ internal class DefaultKeysBackupService @Inject constructor(
             cryptoCoroutineScope.launch(coroutineDispatchers.main) {
                 val updateKeysBackupVersionBody = withContext(coroutineDispatchers.crypto) {
                     // Get current signatures, or create an empty set
-                    val myUserSignatures = authData.signatures?.get(userId)?.toMutableMap() ?: HashMap()
+                    val myUserSignatures = authData.signatures[userId].orEmpty().toMutableMap()
 
                     if (trust) {
                         // Add current device signature
@@ -498,26 +497,23 @@ internal class DefaultKeysBackupService @Inject constructor(
                     // Create an updated version of KeysVersionResult
                     val newMegolmBackupAuthData = authData.copy()
 
-                    val newSignatures = newMegolmBackupAuthData.signatures!!.toMutableMap()
+                    val newSignatures = newMegolmBackupAuthData.signatures.toMutableMap()
                     newSignatures[userId] = myUserSignatures
 
                     val newMegolmBackupAuthDataWithNewSignature = newMegolmBackupAuthData.copy(
                             signatures = newSignatures
                     )
 
-                    val moshi = MoshiProvider.providesMoshi()
-                    val adapter = moshi.adapter(Map::class.java)
-
                     @Suppress("UNCHECKED_CAST")
                     UpdateKeysBackupVersionBody(
                             algorithm = keysBackupVersion.algorithm,
-                            authData = adapter.fromJson(newMegolmBackupAuthDataWithNewSignature.toJsonString()) as Map<String, Any>?,
-                            version = keysBackupVersion.version!!)
+                            authData = newMegolmBackupAuthDataWithNewSignature.toJsonDict(),
+                            version = keysBackupVersion.version)
                 }
 
                 // And send it to the homeserver
                 updateKeysBackupVersionTask
-                        .configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version!!, updateKeysBackupVersionBody)) {
+                        .configureWith(UpdateKeysBackupVersionTask.Params(keysBackupVersion.version, updateKeysBackupVersionBody)) {
                             this.callback = object : MatrixCallback<Unit> {
                                 override fun onSuccess(data: Unit) {
                                     // Relaunch the state machine on this updated backup version
@@ -688,7 +684,7 @@ internal class DefaultKeysBackupService @Inject constructor(
                 stepProgressListener?.onStepProgress(StepProgressListener.Step.DownloadingKey)
 
                 // Get backed up keys from the homeserver
-                val data = getKeys(sessionId, roomId, keysVersionResult.version!!)
+                val data = getKeys(sessionId, roomId, keysVersionResult.version)
 
                 withContext(coroutineDispatchers.computation) {
                     val sessionsData = ArrayList<MegolmSessionData>()
@@ -1023,19 +1019,10 @@ internal class DefaultKeysBackupService @Inject constructor(
      * @return the authentication if found and valid, null in other case
      */
     private fun getMegolmBackupAuthData(keysBackupData: KeysVersionResult): MegolmBackupAuthData? {
-        if (keysBackupData.version.isNullOrBlank()
-                || keysBackupData.algorithm != MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
-                || keysBackupData.authData == null) {
-            return null
-        }
-
-        val authData = keysBackupData.getAuthDataAsMegolmBackupAuthData()
-
-        if (authData?.signatures == null || authData.publicKey.isBlank()) {
-            return null
-        }
-
-        return authData
+        return keysBackupData
+                .takeIf { it.version.isNotEmpty() && it.algorithm == MXCRYPTO_ALGORITHM_MEGOLM_BACKUP }
+                ?.getAuthDataAsMegolmBackupAuthData()
+                ?.takeIf { it.publicKey.isNotEmpty() }
     }
 
     /**
@@ -1123,34 +1110,29 @@ internal class DefaultKeysBackupService @Inject constructor(
      * @param keysVersionResult backup information object as returned by [getCurrentVersion].
      */
     private fun enableKeysBackup(keysVersionResult: KeysVersionResult) {
-        if (keysVersionResult.authData != null) {
-            val retrievedMegolmBackupAuthData = keysVersionResult.getAuthDataAsMegolmBackupAuthData()
+        val retrievedMegolmBackupAuthData = keysVersionResult.getAuthDataAsMegolmBackupAuthData()
 
-            if (retrievedMegolmBackupAuthData != null) {
-                keysBackupVersion = keysVersionResult
-                cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
-                    cryptoStore.setKeyBackupVersion(keysVersionResult.version)
-                }
-
-                onServerDataRetrieved(keysVersionResult.count, keysVersionResult.hash)
-
-                try {
-                    backupOlmPkEncryption = OlmPkEncryption().apply {
-                        setRecipientKey(retrievedMegolmBackupAuthData.publicKey)
-                    }
-                } catch (e: OlmException) {
-                    Timber.e(e, "OlmException")
-                    keysBackupStateManager.state = KeysBackupState.Disabled
-                    return
-                }
-
-                keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
-
-                maybeBackupKeys()
-            } else {
-                Timber.e("Invalid authentication data")
-                keysBackupStateManager.state = KeysBackupState.Disabled
+        if (retrievedMegolmBackupAuthData != null) {
+            keysBackupVersion = keysVersionResult
+            cryptoCoroutineScope.launch(coroutineDispatchers.crypto) {
+                cryptoStore.setKeyBackupVersion(keysVersionResult.version)
             }
+
+            onServerDataRetrieved(keysVersionResult.count, keysVersionResult.hash)
+
+            try {
+                backupOlmPkEncryption = OlmPkEncryption().apply {
+                    setRecipientKey(retrievedMegolmBackupAuthData.publicKey)
+                }
+            } catch (e: OlmException) {
+                Timber.e(e, "OlmException")
+                keysBackupStateManager.state = KeysBackupState.Disabled
+                return
+            }
+
+            keysBackupStateManager.state = KeysBackupState.ReadyToBackUp
+
+            maybeBackupKeys()
         } else {
             Timber.e("Invalid authentication data")
             keysBackupStateManager.state = KeysBackupState.Disabled
@@ -1160,11 +1142,11 @@ internal class DefaultKeysBackupService @Inject constructor(
     /**
      * Update the DB with data fetch from the server
      */
-    private fun onServerDataRetrieved(count: Int?, hash: String?) {
+    private fun onServerDataRetrieved(count: Int?, etag: String?) {
         cryptoStore.setKeysBackupData(KeysBackupDataEntity()
                 .apply {
                     backupLastServerNumberOfKeys = count
-                    backupLastServerHash = hash
+                    backupLastServerHash = etag
                 }
         )
     }
@@ -1316,7 +1298,7 @@ internal class DefaultKeysBackupService @Inject constructor(
 
                 // Make the request
                 storeSessionDataTask
-                        .configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version!!, keysBackupData)) {
+                        .configureWith(StoreSessionsDataTask.Params(keysBackupVersion!!.version, keysBackupData)) {
                             this.callback = sendingRequestCallback
                         }
                         .executeBy(taskExecutor)
@@ -1337,8 +1319,7 @@ internal class DefaultKeysBackupService @Inject constructor(
                 "algorithm" to sessionData!!.algorithm,
                 "sender_key" to sessionData.senderKey,
                 "sender_claimed_keys" to sessionData.senderClaimedKeys,
-                "forwarding_curve25519_key_chain" to (sessionData.forwardingCurve25519KeyChain
-                        ?: ArrayList<Any>()),
+                "forwarding_curve25519_key_chain" to (sessionData.forwardingCurve25519KeyChain.orEmpty()),
                 "session_key" to sessionData.sessionKey)
 
         var encryptedSessionBackupData: OlmPkMessage? = null
@@ -1379,9 +1360,9 @@ internal class DefaultKeysBackupService @Inject constructor(
 
         val jsonObject = keyBackupData.sessionData
 
-        val ciphertext = jsonObject?.get("ciphertext")?.toString()
-        val mac = jsonObject?.get("mac")?.toString()
-        val ephemeralKey = jsonObject?.get("ephemeral")?.toString()
+        val ciphertext = jsonObject["ciphertext"]?.toString()
+        val mac = jsonObject["mac"]?.toString()
+        val ephemeralKey = jsonObject["ephemeral"]?.toString()
 
         if (ciphertext != null && mac != null && ephemeralKey != null) {
             val encrypted = OlmPkMessage()
@@ -1426,8 +1407,7 @@ internal class DefaultKeysBackupService @Inject constructor(
         @Suppress("UNCHECKED_CAST")
         val createKeysBackupVersionBody = CreateKeysBackupVersionBody(
                 algorithm = keysBackupCreationInfo.algorithm,
-                authData = MoshiProvider.providesMoshi().adapter(Map::class.java)
-                        .fromJson(keysBackupCreationInfo.authData?.toJsonString() ?: "") as JsonDict?
+                authData = keysBackupCreationInfo.authData.toJsonDict()
         )
 
         createKeysBackupVersionTask
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt
index ed5383d6eb..3f8333528f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt
@@ -35,7 +35,7 @@ import retrofit2.http.Path
 import retrofit2.http.Query
 
 /**
- * Ref: https://github.com/uhoreg/matrix-doc/blob/e2e_backup/proposals/1219-storing-megolm-keys-serverside.md
+ * Ref: https://matrix.org/docs/spec/client_server/unstable#server-side-key-backups
  */
 internal interface RoomKeysApi {
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt
index 9df5f29294..54b92546e9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.model
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
+import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.internal.di.MoshiProvider
 
 /**
@@ -30,7 +31,7 @@ data class MegolmBackupAuthData(
          * The curve25519 public key used to encrypt the backups.
          */
         @Json(name = "public_key")
-        val publicKey: String = "",
+        val publicKey: String,
 
         /**
          * In case of a backup created from a password, the salt associated with the backup
@@ -50,20 +51,38 @@ data class MegolmBackupAuthData(
          * userId -> (deviceSignKeyId -> signature)
          */
         @Json(name = "signatures")
-        val signatures: Map<String, Map<String, String>>? = null
+        val signatures: Map<String, Map<String, String>>
 ) {
 
-    fun toJsonString(): String {
-        return MoshiProvider.providesMoshi()
+    fun toJsonDict(): JsonDict {
+        val moshi = MoshiProvider.providesMoshi()
+        val adapter = moshi.adapter(Map::class.java)
+
+        return moshi
                 .adapter(MegolmBackupAuthData::class.java)
                 .toJson(this)
+                .let {
+                    @Suppress("UNCHECKED_CAST")
+                    adapter.fromJson(it) as JsonDict
+                }
     }
 
-    /**
-     * Same as the parent [MXJSONModel JSONDictionary] but return only
-     * data that must be signed.
-     */
-    fun signalableJSONDictionary(): Map<String, Any> = HashMap<String, Any>().apply {
+    fun signalableJSONDictionary(): JsonDict {
+        return SignalableMegolmBackupAuthData(
+                publicKey = publicKey,
+                privateKeySalt = privateKeySalt,
+                privateKeyIterations = privateKeyIterations
+        )
+                .signalableJSONDictionary()
+    }
+}
+
+internal data class SignalableMegolmBackupAuthData(
+        val publicKey: String,
+        val privateKeySalt: String? = null,
+        val privateKeyIterations: Int? = null
+) {
+    fun signalableJSONDictionary(): JsonDict = HashMap<String, Any>().apply {
         put("public_key", publicKey)
 
         privateKeySalt?.let {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt
index 1414d0e0d7..c668e78a9e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt
@@ -23,15 +23,15 @@ data class MegolmBackupCreationInfo(
         /**
          * The algorithm used for storing backups [org.matrix.androidsdk.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP].
          */
-        val algorithm: String = "",
+        val algorithm: String,
 
         /**
          * Authentication data.
          */
-        val authData: MegolmBackupAuthData? = null,
+        val authData: MegolmBackupAuthData,
 
         /**
          * The Base58 recovery key.
          */
-        val recoveryKey: String = ""
+        val recoveryKey: String
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/BackupKeysResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/BackupKeysResult.kt
index a84ba7427b..3710a2d7d9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/BackupKeysResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/BackupKeysResult.kt
@@ -16,15 +16,16 @@
 
 package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest
 
+import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
-data class BackupKeysResult(
-
+internal data class BackupKeysResult(
         // The hash value which is an opaque string representing stored keys in the backup
-        var hash: String? = null,
+        @Json(name = "etag")
+        val hash: String,
 
         // The number of keys stored in the backup.
-        var count: Int? = null
-
+        @Json(name = "count")
+        val count: Int
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt
index a7831b38f1..a6bd8f8aaa 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/CreateKeysBackupVersionBody.kt
@@ -21,17 +21,17 @@ import com.squareup.moshi.JsonClass
 import org.matrix.android.sdk.api.util.JsonDict
 
 @JsonClass(generateAdapter = true)
-data class CreateKeysBackupVersionBody(
+internal data class CreateKeysBackupVersionBody(
         /**
          * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
          */
         @Json(name = "algorithm")
-        override val algorithm: String? = null,
+        override val algorithm: String,
 
         /**
          * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2"
          * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
          */
         @Json(name = "auth_data")
-        override val authData: JsonDict? = null
+        override val authData: JsonDict
 ) : KeysAlgorithmAndData
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt
index 46eaa586a7..3f8129b8f6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt
@@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
-import org.matrix.android.sdk.internal.di.MoshiProvider
+import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.internal.network.parsing.ForceToBoolean
 
 /**
@@ -30,13 +30,13 @@ data class KeyBackupData(
          * Required. The index of the first message in the session that the key can decrypt.
          */
         @Json(name = "first_message_index")
-        val firstMessageIndex: Long = 0,
+        val firstMessageIndex: Long,
 
         /**
          * Required. The number of times this key has been forwarded.
          */
         @Json(name = "forwarded_count")
-        val forwardedCount: Int = 0,
+        val forwardedCount: Int,
 
         /**
          * Whether the device backing up the key has verified the device that the key is from.
@@ -44,16 +44,11 @@ data class KeyBackupData(
          */
         @ForceToBoolean
         @Json(name = "is_verified")
-        val isVerified: Boolean = false,
+        val isVerified: Boolean,
 
         /**
          * Algorithm-dependent data.
          */
         @Json(name = "session_data")
-        val sessionData: Map<String, Any>? = null
-) {
-
-    fun toJsonString(): String {
-        return MoshiProvider.providesMoshi().adapter(KeyBackupData::class.java).toJson(this)
-    }
-}
+        val sessionData: JsonDict
+)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt
index 117d4dce70..e098aa0440 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt
@@ -17,6 +17,7 @@
 package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest
 
 import org.matrix.android.sdk.api.util.JsonDict
+import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
 import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupAuthData
 import org.matrix.android.sdk.internal.di.MoshiProvider
 
@@ -37,24 +38,25 @@ import org.matrix.android.sdk.internal.di.MoshiProvider
  *     }
  * </pre>
  */
-interface KeysAlgorithmAndData {
+internal interface KeysAlgorithmAndData {
 
     /**
      * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
      */
-    val algorithm: String?
+    val algorithm: String
 
     /**
      * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2" see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
      */
-    val authData: JsonDict?
+    val authData: JsonDict
 
     /**
      * Facility method to convert authData to a MegolmBackupAuthData object
      */
     fun getAuthDataAsMegolmBackupAuthData(): MegolmBackupAuthData? {
         return MoshiProvider.providesMoshi()
-                .adapter(MegolmBackupAuthData::class.java)
-                .fromJsonValue(authData)
+                .takeIf { algorithm == MXCRYPTO_ALGORITHM_MEGOLM_BACKUP }
+                ?.adapter(MegolmBackupAuthData::class.java)
+                ?.fromJsonValue(authData)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt
index 146c98b017..7a4c3415fc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt
@@ -23,5 +23,5 @@ import com.squareup.moshi.JsonClass
 data class KeysVersion(
         // the keys backup version
         @Json(name = "version")
-        val version: String? = null
+        val version: String
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt
index 0844c58d2e..485fd48a8c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt
@@ -26,24 +26,24 @@ data class KeysVersionResult(
          * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
          */
         @Json(name = "algorithm")
-        override val algorithm: String? = null,
+        override val algorithm: String,
 
         /**
          * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2"
          * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
          */
         @Json(name = "auth_data")
-        override val authData: JsonDict? = null,
+        override val authData: JsonDict,
 
         // the backup version
         @Json(name = "version")
-        val version: String? = null,
+        val version: String,
 
         // The hash value which is an opaque string representing stored keys in the backup
-        @Json(name = "hash")
-        val hash: String? = null,
+        @Json(name = "etag")
+        val hash: String,
 
         // The number of keys stored in the backup.
         @Json(name = "count")
-        val count: Int? = null
+        val count: Int
 ) : KeysAlgorithmAndData
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt
index 65f0c1a845..4512ed7a55 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt
@@ -26,16 +26,16 @@ data class UpdateKeysBackupVersionBody(
          * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined
          */
         @Json(name = "algorithm")
-        override val algorithm: String? = null,
+        override val algorithm: String,
 
         /**
          * algorithm-dependent data, for "m.megolm_backup.v1.curve25519-aes-sha2"
          * see [org.matrix.android.sdk.internal.crypto.keysbackup.MegolmBackupAuthData]
          */
         @Json(name = "auth_data")
-        override val authData: JsonDict? = null,
+        override val authData: JsonDict,
 
-        // the backup version, mandatory
+        // Optional. The backup version. If present, must be the same as the path parameter.
         @Json(name = "version")
-        val version: String
+        val version: String? = null
 ) : KeysAlgorithmAndData
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt
index 72b767e12f..2e5097fdb7 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt
@@ -103,7 +103,7 @@ class BootstrapSharedViewModel @AssistedInject constructor(
                     } else {
                         // we need to get existing backup passphrase/key and convert to SSSS
                         val keyVersion = awaitCallback<KeysVersionResult?> {
-                            session.cryptoService().keysBackupService().getVersion(version.version ?: "", it)
+                            session.cryptoService().keysBackupService().getVersion(version.version, it)
                         }
                         if (keyVersion == null) {
                             // strange case... just finish?