diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index f294671524213c97ec934c2cb074baaf65a172ff..ab3ad8e823e576d9100f789b3153ee0715827523 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -41,6 +41,7 @@
 #include "dring/media_const.h"
 #include "client/ring_signal.h"
 #include "ice_transport.h"
+#include "pjsip-ua/sip_inv.h"
 
 #ifdef ENABLE_PLUGIN
 #include "plugin/jamipluginmanager.h"
@@ -1485,17 +1486,18 @@ SIPCall::onIceNegoSucceed()
     startAllMedia();
 }
 
-void
-SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer)
+int
+SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* rdata)
 {
     if (!sdp_)
-        return;
+        return !PJ_SUCCESS;
     sdp_->clearIce();
     auto acc = getSIPAccount();
     if (!acc) {
         JAMI_ERR("No account detected");
-        return;
+        return !PJ_SUCCESS;
     }
+
     sdp_->receiveOffer(offer,
                        acc->getActiveAccountCodecInfoList(MEDIA_AUDIO),
                        acc->getActiveAccountCodecInfoList(acc->isVideoEnabled() ? MEDIA_VIDEO
@@ -1504,8 +1506,41 @@ SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer)
                        getState() == CallState::HOLD);
     setRemoteSdp(offer);
     sdp_->startNegotiation();
-    pjsip_inv_set_sdp_answer(inviteSession_.get(), sdp_->getLocalSdpSession());
+
+    pjsip_tx_data* tdata = nullptr;
+
+    if (pjsip_inv_initial_answer(inviteSession_.get(),
+                                 const_cast<pjsip_rx_data*>(rdata),
+                                 PJSIP_SC_OK,
+                                 NULL,
+                                 NULL,
+                                 &tdata)
+        != PJ_SUCCESS) {
+        JAMI_ERR("Could not create initial answer OK");
+        return !PJ_SUCCESS;
+    }
+
+    // Add user-agent header
+    sip_utils::addUserAgentHeader(getSIPAccount()->getUserAgentName(), tdata);
+
+    if (pjsip_inv_answer(inviteSession_.get(), PJSIP_SC_OK, NULL, sdp_->getLocalSdpSession(), &tdata)
+        != PJ_SUCCESS) {
+        JAMI_ERR("Could not create answer OK");
+        return !PJ_SUCCESS;
+    }
+
+    // ContactStr must stay in scope as long as tdata
+    const pj_str_t contactStr(getSIPAccount()->getContactHeader(getTransport()->get()));
+    sip_utils::addContactHeader(&contactStr, tdata);
+
+    if (pjsip_inv_send_msg(inviteSession_.get(), tdata) != PJ_SUCCESS) {
+        JAMI_ERR("Could not send msg OK");
+        return !PJ_SUCCESS;
+    }
+
     openPortsUPnP();
+
+    return PJ_SUCCESS;
 }
 
 void
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index d41676304e32135223052e0bcc01c2a6267f9027..f71ceb1a97efdc40a47cc881867a9a56913e077f 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -51,6 +51,7 @@ struct pjsip_evsub;
 struct pjsip_inv_session;
 struct pjmedia_sdp_session;
 struct pj_ice_sess_cand;
+struct pjsip_rx_data;
 }
 
 namespace jami {
@@ -167,7 +168,7 @@ public:
      */
     void onClosed();
 
-    void onReceiveOffer(const pjmedia_sdp_session* offer);
+    int onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* rdata);
 
     void onMediaUpdate();
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index f3fd9f6092e400f800d2bda19b157cd4c202f998..a5ef89708a6386cee47a6af940c6a51af76cba6f 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -75,8 +75,10 @@ static pjsip_endpoint* endpt_;
 static pjsip_module mod_ua_;
 
 static void sdp_media_update_cb(pjsip_inv_session* inv, pj_status_t status);
-static void sdp_request_offer_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer);
 static void sdp_create_offer_cb(pjsip_inv_session* inv, pjmedia_sdp_session** p_offer);
+static pj_status_t reinvite_received_cb(pjsip_inv_session* inv,
+                                        const pjmedia_sdp_session* offer,
+                                        pjsip_rx_data* rdata);
 static void invite_session_state_changed_cb(pjsip_inv_session* inv, pjsip_event* e);
 static void outgoing_request_forked_cb(pjsip_inv_session* inv, pjsip_event* e);
 static void transaction_state_changed_cb(pjsip_inv_session* inv,
@@ -665,12 +667,12 @@ SIPVoIPLink::SIPVoIPLink()
         = { invite_session_state_changed_cb,
             outgoing_request_forked_cb,
             transaction_state_changed_cb,
-            sdp_request_offer_cb,
+            nullptr /* on_rx_offer */,
 #if PJ_VERSION_NUM >= (2 << 24 | 7 << 16)
             nullptr /* on_rx_offer2 */,
 #endif
 #if PJ_VERSION_NUM > (2 << 24 | 1 << 16)
-            nullptr /* on_rx_reinvite */,
+            reinvite_received_cb,
 #endif
             sdp_create_offer_cb,
             sdp_media_update_cb,
@@ -921,11 +923,13 @@ invite_session_state_changed_cb(pjsip_inv_session* inv, pjsip_event* ev)
     }
 }
 
-static void
-sdp_request_offer_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer)
+static pj_status_t
+reinvite_received_cb(pjsip_inv_session* inv, const pjmedia_sdp_session* offer, pjsip_rx_data* rdata)
 {
-    if (auto call = getCallFromInvite(inv))
-        call->onReceiveOffer(offer);
+    if (auto call = getCallFromInvite(inv)) {
+        return call->onReceiveOffer(offer, rdata);
+    }
+    return !PJ_SUCCESS;
 }
 
 static void