diff --git a/src/data_transfer.cpp b/src/data_transfer.cpp
index 10f75811c370da9495db1e761971540cdfb117e0..4d0371a7e5980ce00c9b45709044fae7e209f0fd 100644
--- a/src/data_transfer.cpp
+++ b/src/data_transfer.cpp
@@ -203,13 +203,13 @@ IncomingFile::process()
         auto shared = w.lock();
         if (!shared)
             return;
-        auto correct = shared->sha3Sum_.empty();
         auto isEOF = shared->info_.bytesProgress == shared->info_.totalSize;
         if (shared->stream_ && shared->stream_.is_open()) {
             isEOF |= shared->stream_.eof();
             shared->stream_.close();
         }
-        if (!correct) {
+        auto correct = isEOF && shared->sha3Sum_.empty();
+        if (!correct && !shared->sha3Sum_.empty()) {
             // Verify shaSum
             auto sha3Sum = fileutils::sha3File(shared->info_.path);
             if (shared->sha3Sum_ == sha3Sum) {
@@ -306,7 +306,8 @@ TransferManager::transferFile(const std::shared_ptr<ChannelSocket>& channel,
                               const std::string& interactionId,
                               const std::string& path,
                               size_t start,
-                              size_t end)
+                              size_t end,
+                              OnFinishedCb onFinished)
 {
     std::lock_guard<std::mutex> lk {pimpl_->mapMutex_};
     if (pimpl_->outgoings_.find(channel) != pimpl_->outgoings_.end())
@@ -316,7 +317,10 @@ TransferManager::transferFile(const std::shared_ptr<ChannelSocket>& channel,
     info.conversationId = pimpl_->to_;
     info.path = path;
     auto f = std::make_shared<OutgoingFile>(channel, fileId, interactionId, info, start, end);
-    f->onFinished([w = weak(), channel](uint32_t) {
+    f->onFinished([w = weak(), channel, onFinished = std::move(onFinished)](uint32_t code) {
+        if (code == uint32_t(libjami::DataTransferEventCode::finished) && onFinished) {
+            onFinished();
+        }
         // schedule destroy outgoing transfer as not needed
         dht::ThreadPool().computation().run([w, channel] {
             if (auto sthis_ = w.lock()) {
diff --git a/src/data_transfer.h b/src/data_transfer.h
index 17aabe28f6ab34ead1ee724be051c4f7ffd4b408..ffb84d360fd939767b498dc627634f4f01839ed8 100644
--- a/src/data_transfer.h
+++ b/src/data_transfer.h
@@ -24,10 +24,11 @@
 #include "connectivity/multiplexed_socket.h"
 #include "noncopyable.h"
 
-#include <memory>
-#include <string>
 #include <fstream>
+#include <functional>
+#include <memory>
 #include <optional>
+#include <string>
 
 namespace jami {
 
@@ -52,6 +53,7 @@ struct WaitingRequest
 };
 
 typedef std::function<void(const std::string&)> InternalCompletionCb;
+typedef std::function<void()> OnFinishedCb;
 
 class FileInfo
 {
@@ -137,7 +139,8 @@ public:
                       const std::string& interactionId,
                       const std::string& path,
                       size_t start = 0,
-                      size_t end = 0);
+                      size_t end = 0,
+                      OnFinishedCb onFinished = {});
 
     /**
      * Refuse a transfer
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index cc910d6b34179e930c38ccaeb14d20788b644ffd..11ff5685891f1788da88505cc0cb5b87ba6e54d8 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -3684,18 +3684,19 @@ JamiAccount::sendProfile(const std::string& convId, const std::string& peerUri,
         return;
     }
     // We need a new channel
-    transferFile(convId, profilePath(), deviceId, "profile.vcf", "");
-    // Mark the VCard as sent
-    auto sendDir = fmt::format("{}/{}/vcard/{}",
-                                fileutils::get_cache_dir(),
-                                getAccountID(),
-                                peerUri);
-    auto path = fmt::format("{}/{}", sendDir, deviceId);
-    fileutils::recursive_mkdir(sendDir);
-    std::lock_guard<std::mutex> lock(fileutils::getFileLock(path));
-    if (fileutils::isFile(path))
-        return;
-    fileutils::ofstream(path);
+    transferFile(convId, profilePath(), deviceId, "profile.vcf", "", 0, 0, std::move([accId = getAccountID(), peerUri, deviceId]() {
+        // Mark the VCard as sent
+        auto sendDir = fmt::format("{}/{}/vcard/{}",
+                                    fileutils::get_cache_dir(),
+                                    accId,
+                                    peerUri);
+        auto path = fmt::format("{}/{}", sendDir, deviceId);
+        fileutils::recursive_mkdir(sendDir);
+        std::lock_guard<std::mutex> lock(fileutils::getFileLock(path));
+        if (fileutils::isFile(path))
+            return;
+        fileutils::ofstream(path);
+    }));
 }
 
 bool
@@ -3998,7 +3999,8 @@ JamiAccount::transferFile(const std::string& conversationId,
                           const std::string& fileId,
                           const std::string& interactionId,
                           size_t start,
-                          size_t end)
+                          size_t end,
+                          std::function<void()> onFinished)
 {
     auto channelName = conversationId.empty() ? fmt::format("{}profile.vcf", DATA_TRANSFER_URI)
                         : fmt::format("{}{}/{}/{}",
@@ -4012,7 +4014,7 @@ JamiAccount::transferFile(const std::string& conversationId,
     connectionManager_->connectDevice(
         DeviceId(deviceId),
         channelName,
-        [this, conversationId, path = std::move(path), fileId, interactionId, start, end](
+        [this, conversationId, path = std::move(path), fileId, interactionId, start, end, onFinished = std::move(onFinished)](
             std::shared_ptr<ChannelSocket> socket, const DeviceId&) {
             if (!socket)
                 return;
@@ -4023,10 +4025,11 @@ JamiAccount::transferFile(const std::string& conversationId,
                                        fileId,
                                        interactionId,
                                        start,
-                                       end] {
+                                       end,
+                                       onFinished = std::move(onFinished)] {
                 if (auto shared = w.lock())
                     if (auto dt = shared->dataTransfer(conversationId))
-                        dt->transferFile(socket, fileId, interactionId, path, start, end);
+                        dt->transferFile(socket, fileId, interactionId, path, start, end, std::move(onFinished));
             });
         });
 }
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index a62442919384d2181e0a46a827d661fc58b5be6c..d3dda1f04a92bb90bd55ccc6cf88d4bb5d7be3ce 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -58,6 +58,7 @@
 #include <pjsip/sip_types.h>
 
 #include <chrono>
+#include <functional>
 #include <future>
 #include <json/json.h>
 #include <list>
@@ -518,7 +519,8 @@ public:
                       const std::string& fileId,
                       const std::string& interactionId,
                       size_t start = 0,
-                      size_t end = 0);
+                      size_t end = 0,
+                      std::function<void()> onFinished = {});
 
     void askForFileChannel(const std::string& conversationId,
                            const std::string& deviceId,