diff --git a/src/conversationlistmodel.cpp b/src/conversationlistmodel.cpp
index 4f896bcaf7e377c1f03725bafd5514e93f62a107..fd0b16c0a83452abdaf7aa89c0e5ce2c745f9e97 100644
--- a/src/conversationlistmodel.cpp
+++ b/src/conversationlistmodel.cpp
@@ -102,20 +102,39 @@ ConversationListProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s
         flags |= URI::Section::SCHEME;
     }
     rx.setPattern(uriStripper.format(flags));
-    auto uri = index.data(ConversationList::Role::URI).toString();
-    auto alias = index.data(ConversationList::Role::Alias).toString();
-    auto registeredName = index.data(ConversationList::Role::RegisteredName).toString();
-    auto itemProfileType = index.data(ConversationList::Role::ContactType).toInt();
-    auto typeFilter = static_cast<profile::Type>(itemProfileType) == currentTypeFilter_;
+
+    using namespace ConversationList;
+
+    // name/id
+    auto uri = index.data(Role::URI).toString();
+    auto alias = index.data(Role::Alias).toString();
+    auto registeredName = index.data(Role::RegisteredName).toString();
+
+    // account type
+    auto itemProfileType = static_cast<profile::Type>(index.data(Role::ContactType).toInt());
+    // this is workaround for profile::Type including both account types and extended types
+    // - PENDING is implicitly also JAMI
+    // - TEMPORARY should never be in this list
+    if (itemProfileType == profile::Type::PENDING)
+        itemProfileType = profile::Type::JAMI;
+    auto typeFilter = itemProfileType == profileTypeFilter_;
+
+    // requests
+    auto isRequest = index.data(Role::IsRequest).toBool();
+    bool requestFilter = filterRequests_ ? isRequest : !isRequest;
+
     bool match {false};
-    if (index.data(ConversationList::Role::IsBanned).toBool()) {
+
+    // banned contacts require exact match
+    if (index.data(Role::IsBanned).toBool()) {
         match = !rx.isEmpty()
                 && (rx.exactMatch(uri) || rx.exactMatch(alias) || rx.exactMatch(registeredName));
     } else {
         match = (rx.indexIn(uri) != -1 || rx.indexIn(alias) != -1
                  || rx.indexIn(registeredName) != -1);
     }
-    return typeFilter && match;
+
+    return typeFilter && requestFilter && match;
 }
 
 bool
@@ -128,10 +147,24 @@ ConversationListProxyModel::lessThan(const QModelIndex& left, const QModelIndex&
 }
 
 void
-ConversationListProxyModel::setTypeFilter(const profile::Type& typeFilter)
+ConversationListProxyModel::setProfileTypeFilter(const profile::Type& profileTypeFilter)
+{
+    if (profileTypeFilter != lrc::api::profile::Type::JAMI
+        && profileTypeFilter != lrc::api::profile::Type::SIP) {
+        qWarning() << "Profile filter parameter must be an account type";
+        return;
+    }
+    beginResetModel();
+    profileTypeFilter_ = profileTypeFilter;
+    endResetModel();
+    updateSelection();
+};
+
+void
+ConversationListProxyModel::setFilterRequests(bool filterRequests)
 {
     beginResetModel();
-    currentTypeFilter_ = typeFilter;
+    filterRequests_ = filterRequests;
     endResetModel();
     updateSelection();
 };
diff --git a/src/conversationlistmodel.h b/src/conversationlistmodel.h
index 3e143d740fb79b7e71c9f35081accc2bb44d7901..b41dad1fe898d04e01ff714e95bb8870dba93078 100644
--- a/src/conversationlistmodel.h
+++ b/src/conversationlistmodel.h
@@ -48,8 +48,16 @@ public:
     bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
     bool lessThan(const QModelIndex& left, const QModelIndex& right) const override;
 
-    Q_INVOKABLE void setTypeFilter(const profile::Type& typeFilter);
+    Q_INVOKABLE void setProfileTypeFilter(const profile::Type& profileTypeFilter);
+    Q_INVOKABLE void setFilterRequests(bool filterRequests);
 
 private:
-    profile::Type currentTypeFilter_;
+    // With swarm in place, this filter should only ever be set to profile::Type::JAMI
+    // and profile::Type::SIP as profile::Type::PENDING should no longer be used to
+    // filter for invites, and instead use the isRequest property of a conversation.
+    profile::Type profileTypeFilter_;
+
+    // This flag can be toggled when switching tabs to show the current account's
+    // conversation invites.
+    bool filterRequests_ {false};
 };
diff --git a/src/conversationlistmodelbase.cpp b/src/conversationlistmodelbase.cpp
index b896f8db1a3a79bd6921f31d485e07c25903bef9..7a05374091c33911e752cc99f37dce43514a35f5 100644
--- a/src/conversationlistmodelbase.cpp
+++ b/src/conversationlistmodelbase.cpp
@@ -165,6 +165,9 @@ ConversationListModelBase::dataForItem(item_t item, int role) const
         }
         return QVariant("");
     }
+    case Role::IsRequest: {
+        return QVariant(item.isRequest);
+    }
     }
     return QVariant();
 }
diff --git a/src/conversationlistmodelbase.h b/src/conversationlistmodelbase.h
index 8940b81214f4642af118fb12a63925687a84047b..45ef4c912b63e9bbd5575ced9567c74e139f082b 100644
--- a/src/conversationlistmodelbase.h
+++ b/src/conversationlistmodelbase.h
@@ -44,7 +44,8 @@
     X(SectionName) \
     X(AccountId) \
     X(PictureUid) \
-    X(Draft)
+    X(Draft) \
+    X(IsRequest)
 
 namespace ConversationList {
 Q_NAMESPACE
diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp
index 263a172411ca218c181bab4a9aa7084f48cc3c5c..bddfb44979be7f3ef995fb291e1c9fa316820e16 100644
--- a/src/conversationsadapter.cpp
+++ b/src/conversationsadapter.cpp
@@ -33,7 +33,6 @@ ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
                                            LRCInstance* instance,
                                            QObject* parent)
     : QmlAdapterBase(instance, parent)
-    , currentTypeFilter_(profile::Type::JAMI)
     , systemTray_(systemTray)
     , convSrcModel_(new ConversationListModel(lrcInstance_))
     , convModel_(new ConversationListProxyModel(convSrcModel_.get()))
@@ -45,9 +44,16 @@ ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
 
     new SelectableListProxyGroupModel({convModel_.data(), searchModel_.data()}, this);
 
-    setTypeFilter(currentTypeFilter_);
-    connect(this, &ConversationsAdapter::currentTypeFilterChanged, [this]() {
-        setTypeFilter(currentTypeFilter_);
+    // this will trigger when the conversations filter tab is selected
+    connect(this, &ConversationsAdapter::profileTypeFilterChanged, [this]() {
+        convModel_->setProfileTypeFilter(profileTypeFilter_);
+    });
+    set_profileTypeFilter(profile::Type::JAMI);
+
+    // this will trigger when the invite filter tab is selected
+    connect(this, &ConversationsAdapter::filterRequestsChanged, [this]() {
+        // it is assumed that profileTypeFilter is profile::Type::JAMI here
+        convModel_->setFilterRequests(filterRequests_);
     });
 
     connect(lrcInstance_, &LRCInstance::selectedConvUidChanged, [this]() {
@@ -73,7 +79,7 @@ ConversationsAdapter::ConversationsAdapter(SystemTray* systemTray,
                 auto& contact = accInfo.contactModel->getContact(convInfo.participants.front());
                 if (contact.profileInfo.type != profile::Type::INVALID
                     && contact.profileInfo.type != profile::Type::TEMPORARY)
-                    set_currentTypeFilter(contact.profileInfo.type);
+                    set_profileTypeFilter(contact.profileInfo.type);
             } catch (const std::out_of_range& e) {
                 qWarning() << e.what();
             }
@@ -167,7 +173,7 @@ ConversationsAdapter::safeInit()
 
     connectConversationModel();
 
-    set_currentTypeFilter(lrcInstance_->getCurrentAccountInfo().profileInfo.type);
+    set_profileTypeFilter(lrcInstance_->getCurrentAccountInfo().profileInfo.type);
 }
 
 void
@@ -177,7 +183,7 @@ ConversationsAdapter::onCurrentAccountIdChanged()
 
     connectConversationModel();
 
-    set_currentTypeFilter(lrcInstance_->getCurrentAccountInfo().profileInfo.type);
+    set_profileTypeFilter(lrcInstance_->getCurrentAccountInfo().profileInfo.type);
 }
 
 void
@@ -346,8 +352,8 @@ ConversationsAdapter::updateConversationFilterData()
     }
     set_totalUnreadMessageCount(totalUnreadMessages);
     set_pendingRequestCount(accountInfo.conversationModel->pendingRequestCount());
-    if (pendingRequestCount_ == 0 && currentTypeFilter_ == profile::Type::PENDING) {
-        set_currentTypeFilter(profile::Type::JAMI);
+    if (pendingRequestCount_ == 0 && profileTypeFilter_ == profile::Type::PENDING) {
+        set_profileTypeFilter(profile::Type::JAMI);
     }
 }
 
@@ -358,12 +364,6 @@ ConversationsAdapter::setFilter(const QString& filterString)
     searchSrcModel_->setFilter(filterString);
 }
 
-void
-ConversationsAdapter::setTypeFilter(const profile::Type& typeFilter)
-{
-    convModel_->setTypeFilter(typeFilter);
-}
-
 QVariantMap
 ConversationsAdapter::getConvInfoMap(const QString& convId)
 {
@@ -414,7 +414,7 @@ ConversationsAdapter::getConvInfoMap(const QString& convId)
 }
 
 bool
-ConversationsAdapter::connectConversationModel(bool updateFilter)
+ConversationsAdapter::connectConversationModel()
 {
     // Signal connections
     auto currentConversationModel = lrcInstance_->getCurrentConversationModel();
@@ -467,10 +467,6 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
                      &ConversationsAdapter::onSearchResultUpdated,
                      Qt::UniqueConnection);
 
-    if (updateFilter) {
-        currentTypeFilter_ = profile::Type::INVALID;
-    }
-
     convSrcModel_.reset(new ConversationListModel(lrcInstance_));
     convModel_->bindSourceModel(convSrcModel_.get());
     searchSrcModel_.reset(new SearchResultsListModel(lrcInstance_));
diff --git a/src/conversationsadapter.h b/src/conversationsadapter.h
index 4641022c579694c48d0c6973214aa22debd69566..eac72404dea42b0c378f761880b1acbf6f1de5e1 100644
--- a/src/conversationsadapter.h
+++ b/src/conversationsadapter.h
@@ -33,7 +33,8 @@ class SystemTray;
 class ConversationsAdapter final : public QmlAdapterBase
 {
     Q_OBJECT
-    QML_PROPERTY(lrc::api::profile::Type, currentTypeFilter)
+    QML_PROPERTY(lrc::api::profile::Type, profileTypeFilter)
+    QML_PROPERTY(bool, filterRequests)
     QML_PROPERTY(int, totalUnreadMessageCount)
     QML_PROPERTY(int, pendingRequestCount)
 
@@ -47,9 +48,8 @@ protected:
     void safeInit() override;
 
 public:
-    Q_INVOKABLE bool connectConversationModel(bool updateFilter = true);
+    Q_INVOKABLE bool connectConversationModel();
     Q_INVOKABLE void setFilter(const QString& filterString);
-    Q_INVOKABLE void setTypeFilter(const profile::Type& typeFilter);
     Q_INVOKABLE QVariantMap getConvInfoMap(const QString& convId);
 
 Q_SIGNALS:
diff --git a/src/mainview/components/SidePanelTabBar.qml b/src/mainview/components/SidePanelTabBar.qml
index a7f9abd5b7432ad7ad56a7334aa3532af03a2003..1e5141c91179d31705c35346966e9eb5fcf3eae8 100644
--- a/src/mainview/components/SidePanelTabBar.qml
+++ b/src/mainview/components/SidePanelTabBar.qml
@@ -31,8 +31,6 @@ import "../../commoncomponents"
 TabBar {
     id: tabBar
 
-    property int currentTypeFilter: ConversationsAdapter.currentTypeFilter
-
     currentIndex: 0
 
     enum TabIndex {
@@ -40,17 +38,15 @@ TabBar {
         Requests
     }
 
-    function selectTab(tabIndex) {
-        ConversationsAdapter.currentTypeFilter =
-                (tabIndex === SidePanelTabBar.Conversations) ?
-                    LRCInstance.currentAccountType :
-                    Profile.Type.PENDING
+    function selectTab(idx) {
+        ConversationsAdapter.profileTypeFilter = LRCInstance.currentAccountType
+        ConversationsAdapter.filterRequests = (idx === SidePanelTabBar.Requests)
     }
 
     FilterTabButton {
         id: conversationsTabButton
 
-        down: currentTypeFilter !==  Profile.Type.PENDING
+        down: !ConversationsAdapter.filterRequests
         tabBar: parent
         labelText: JamiStrings.conversations
         onSelected: selectTab(SidePanelTabBar.Conversations)