diff --git a/src/Admin/Controllers/ToolsController.cs b/src/Admin/Controllers/ToolsController.cs
index 9bd6189b3e..b18864d371 100644
--- a/src/Admin/Controllers/ToolsController.cs
+++ b/src/Admin/Controllers/ToolsController.cs
@@ -3,6 +3,7 @@ using System.Text.Json;
 using Bit.Admin.Models;
 using Bit.Core.Entities;
 using Bit.Core.Models.BitStripe;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
 using Bit.Core.Repositories;
 using Bit.Core.Services;
 using Bit.Core.Settings;
@@ -18,7 +19,7 @@ public class ToolsController : Controller
 {
     private readonly GlobalSettings _globalSettings;
     private readonly IOrganizationRepository _organizationRepository;
-    private readonly IOrganizationService _organizationService;
+    private readonly ICloudGetOrganizationLicenseQuery _cloudGetOrganizationLicenseQuery;
     private readonly IUserService _userService;
     private readonly ITransactionRepository _transactionRepository;
     private readonly IInstallationRepository _installationRepository;
@@ -30,7 +31,7 @@ public class ToolsController : Controller
     public ToolsController(
         GlobalSettings globalSettings,
         IOrganizationRepository organizationRepository,
-        IOrganizationService organizationService,
+        ICloudGetOrganizationLicenseQuery cloudGetOrganizationLicenseQuery,
         IUserService userService,
         ITransactionRepository transactionRepository,
         IInstallationRepository installationRepository,
@@ -41,7 +42,7 @@ public class ToolsController : Controller
     {
         _globalSettings = globalSettings;
         _organizationRepository = organizationRepository;
-        _organizationService = organizationService;
+        _cloudGetOrganizationLicenseQuery = cloudGetOrganizationLicenseQuery;
         _userService = userService;
         _transactionRepository = transactionRepository;
         _installationRepository = installationRepository;
@@ -259,7 +260,7 @@ public class ToolsController : Controller
 
         if (organization != null)
         {
-            var license = await _organizationService.GenerateLicenseAsync(organization,
+            var license = await _cloudGetOrganizationLicenseQuery.GetLicenseAsync(organization,
                 model.InstallationId.Value, model.Version);
             var ms = new MemoryStream();
             await JsonSerializer.SerializeAsync(ms, license, JsonHelpers.Indented);
diff --git a/src/Api/Controllers/LicensesController.cs b/src/Api/Controllers/LicensesController.cs
index 63ed824795..f5391fddc2 100644
--- a/src/Api/Controllers/LicensesController.cs
+++ b/src/Api/Controllers/LicensesController.cs
@@ -1,6 +1,9 @@
 using Bit.Core.Context;
 using Bit.Core.Exceptions;
+using Bit.Core.Models.Api.OrganizationLicenses;
 using Bit.Core.Models.Business;
+using Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
 using Bit.Core.Repositories;
 using Bit.Core.Services;
 using Bit.Core.Utilities;
@@ -14,26 +17,26 @@ namespace Bit.Api.Controllers;
 [SelfHosted(NotSelfHostedOnly = true)]
 public class LicensesController : Controller
 {
-    private readonly ILicensingService _licensingService;
     private readonly IUserRepository _userRepository;
     private readonly IUserService _userService;
     private readonly IOrganizationRepository _organizationRepository;
-    private readonly IOrganizationService _organizationService;
+    private readonly ICloudGetOrganizationLicenseQuery _cloudGetOrganizationLicenseQuery;
+    private readonly IValidateBillingSyncKeyCommand _validateBillingSyncKeyCommand;
     private readonly ICurrentContext _currentContext;
 
     public LicensesController(
-        ILicensingService licensingService,
         IUserRepository userRepository,
         IUserService userService,
         IOrganizationRepository organizationRepository,
-        IOrganizationService organizationService,
+        ICloudGetOrganizationLicenseQuery cloudGetOrganizationLicenseQuery,
+        IValidateBillingSyncKeyCommand validateBillingSyncKeyCommand,
         ICurrentContext currentContext)
     {
-        _licensingService = licensingService;
         _userRepository = userRepository;
         _userService = userService;
         _organizationRepository = organizationRepository;
-        _organizationService = organizationService;
+        _cloudGetOrganizationLicenseQuery = cloudGetOrganizationLicenseQuery;
+        _validateBillingSyncKeyCommand = validateBillingSyncKeyCommand;
         _currentContext = currentContext;
     }
 
@@ -55,21 +58,30 @@ public class LicensesController : Controller
         return license;
     }
 
+    /// <summary>
+    /// Used by self-hosted installations to get an updated license file
+    /// </summary>
     [HttpGet("organization/{id}")]
-    public async Task<OrganizationLicense> GetOrganization(string id, [FromQuery] string key)
+    public async Task<OrganizationLicense> OrganizationSync(string id, [FromBody] SelfHostedOrganizationLicenseRequestModel model)
     {
-        var org = await _organizationRepository.GetByIdAsync(new Guid(id));
-        if (org == null)
+        var organization = await _organizationRepository.GetByIdAsync(new Guid(id));
+        if (organization == null)
         {
-            return null;
+            throw new NotFoundException("Organization not found.");
         }
-        else if (!org.LicenseKey.Equals(key))
+
+        if (!organization.LicenseKey.Equals(model.LicenseKey))
         {
             await Task.Delay(2000);
             throw new BadRequestException("Invalid license key.");
         }
 
-        var license = await _organizationService.GenerateLicenseAsync(org, _currentContext.InstallationId.Value);
+        if (!await _validateBillingSyncKeyCommand.ValidateBillingSyncKeyAsync(organization, model.BillingSyncKey))
+        {
+            throw new BadRequestException("Invalid Billing Sync Key");
+        }
+
+        var license = await _cloudGetOrganizationLicenseQuery.GetLicenseAsync(organization, _currentContext.InstallationId.Value);
         return license;
     }
 }
diff --git a/src/Api/Controllers/OrganizationConnectionsController.cs b/src/Api/Controllers/OrganizationConnectionsController.cs
index 13260b7cca..b7329a14fa 100644
--- a/src/Api/Controllers/OrganizationConnectionsController.cs
+++ b/src/Api/Controllers/OrganizationConnectionsController.cs
@@ -191,7 +191,7 @@ public class OrganizationConnectionsController : Controller
         Guid? organizationConnectionId,
         OrganizationConnectionRequestModel model,
         Func<OrganizationConnectionRequestModel<T>, Task> validateAction = null)
-        where T : new()
+        where T : IConnectionConfig
     {
         var typedModel = new OrganizationConnectionRequestModel<T>(model);
         if (validateAction != null)
diff --git a/src/Api/Controllers/OrganizationSponsorshipsController.cs b/src/Api/Controllers/OrganizationSponsorshipsController.cs
index fc5d38db1c..d9715d07c3 100644
--- a/src/Api/Controllers/OrganizationSponsorshipsController.cs
+++ b/src/Api/Controllers/OrganizationSponsorshipsController.cs
@@ -5,6 +5,7 @@ using Bit.Core.Entities;
 using Bit.Core.Exceptions;
 using Bit.Core.Models.Api.Request.OrganizationSponsorships;
 using Bit.Core.Models.Api.Response.OrganizationSponsorships;
+using Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
 using Bit.Core.Repositories;
 using Bit.Core.Services;
diff --git a/src/Api/Controllers/OrganizationsController.cs b/src/Api/Controllers/OrganizationsController.cs
index bb7c3a63a2..baf0dbfaaf 100644
--- a/src/Api/Controllers/OrganizationsController.cs
+++ b/src/Api/Controllers/OrganizationsController.cs
@@ -11,6 +11,7 @@ using Bit.Core.Exceptions;
 using Bit.Core.Models.Business;
 using Bit.Core.Models.Data.Organizations.Policies;
 using Bit.Core.OrganizationFeatures.OrganizationApiKeys.Interfaces;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
 using Bit.Core.Repositories;
 using Bit.Core.Services;
 using Bit.Core.Settings;
@@ -37,6 +38,7 @@ public class OrganizationsController : Controller
     private readonly IRotateOrganizationApiKeyCommand _rotateOrganizationApiKeyCommand;
     private readonly ICreateOrganizationApiKeyCommand _createOrganizationApiKeyCommand;
     private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository;
+    private readonly ICloudGetOrganizationLicenseQuery _cloudGetOrganizationLicenseQuery;
     private readonly GlobalSettings _globalSettings;
 
     public OrganizationsController(
@@ -53,6 +55,7 @@ public class OrganizationsController : Controller
         IRotateOrganizationApiKeyCommand rotateOrganizationApiKeyCommand,
         ICreateOrganizationApiKeyCommand createOrganizationApiKeyCommand,
         IOrganizationApiKeyRepository organizationApiKeyRepository,
+        ICloudGetOrganizationLicenseQuery cloudGetOrganizationLicenseQuery,
         GlobalSettings globalSettings)
     {
         _organizationRepository = organizationRepository;
@@ -68,6 +71,7 @@ public class OrganizationsController : Controller
         _rotateOrganizationApiKeyCommand = rotateOrganizationApiKeyCommand;
         _createOrganizationApiKeyCommand = createOrganizationApiKeyCommand;
         _organizationApiKeyRepository = organizationApiKeyRepository;
+        _cloudGetOrganizationLicenseQuery = cloudGetOrganizationLicenseQuery;
         _globalSettings = globalSettings;
     }
 
@@ -149,7 +153,8 @@ public class OrganizationsController : Controller
             throw new NotFoundException();
         }
 
-        var license = await _organizationService.GenerateLicenseAsync(orgIdGuid, installationId);
+        var org = await _organizationRepository.GetByIdAsync(new Guid(id));
+        var license = await _cloudGetOrganizationLicenseQuery.GetLicenseAsync(org, installationId);
         if (license == null)
         {
             throw new NotFoundException();
@@ -215,6 +220,7 @@ public class OrganizationsController : Controller
         return new OrganizationResponseModel(result.Item1);
     }
 
+    [Obsolete("2022-12-7 Moved to SelfHostedOrganizationLicensesController, to be removed in EC-815")]
     [HttpPost("license")]
     [SelfHosted(SelfHostedOnly = true)]
     public async Task<OrganizationResponseModel> PostLicense(OrganizationCreateLicenseRequestModel model)
@@ -448,6 +454,7 @@ public class OrganizationsController : Controller
         }
     }
 
+    [Obsolete("2022-12-7 Moved to SelfHostedOrganizationLicensesController, to be removed in EC-815")]
     [HttpPost("{id}/license")]
     [SelfHosted(SelfHostedOnly = true)]
     public async Task PostLicense(string id, LicenseRequestModel model)
diff --git a/src/Api/Controllers/SelfHosted/SelfHostedOrganizationLicensesController.cs b/src/Api/Controllers/SelfHosted/SelfHostedOrganizationLicensesController.cs
new file mode 100644
index 0000000000..92cf50ae41
--- /dev/null
+++ b/src/Api/Controllers/SelfHosted/SelfHostedOrganizationLicensesController.cs
@@ -0,0 +1,117 @@
+using Bit.Api.Models.Request;
+using Bit.Api.Models.Request.Organizations;
+using Bit.Api.Models.Response.Organizations;
+using Bit.Api.Utilities;
+using Bit.Core.Context;
+using Bit.Core.Enums;
+using Bit.Core.Exceptions;
+using Bit.Core.Models.Business;
+using Bit.Core.Models.OrganizationConnectionConfigs;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
+using Bit.Core.Repositories;
+using Bit.Core.Services;
+using Bit.Core.Utilities;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Bit.Api.Controllers.SelfHosted;
+
+[Route("organizations/licenses/self-hosted")]
+[Authorize("Application")]
+[SelfHosted(SelfHostedOnly = true)]
+public class SelfHostedOrganizationLicensesController : Controller
+{
+    private readonly ICurrentContext _currentContext;
+    private readonly ISelfHostedGetOrganizationLicenseQuery _selfHostedGetOrganizationLicenseQuery;
+    private readonly IOrganizationConnectionRepository _organizationConnectionRepository;
+    private readonly IOrganizationService _organizationService;
+    private readonly IOrganizationRepository _organizationRepository;
+    private readonly IUserService _userService;
+
+    public SelfHostedOrganizationLicensesController(
+        ICurrentContext currentContext,
+        ISelfHostedGetOrganizationLicenseQuery selfHostedGetOrganizationLicenseQuery,
+        IOrganizationConnectionRepository organizationConnectionRepository,
+        IOrganizationService organizationService,
+        IOrganizationRepository organizationRepository,
+        IUserService userService)
+    {
+        _currentContext = currentContext;
+        _selfHostedGetOrganizationLicenseQuery = selfHostedGetOrganizationLicenseQuery;
+        _organizationConnectionRepository = organizationConnectionRepository;
+        _organizationService = organizationService;
+        _organizationRepository = organizationRepository;
+        _userService = userService;
+    }
+
+    [HttpPost("")]
+    public async Task<OrganizationResponseModel> PostLicenseAsync(OrganizationCreateLicenseRequestModel model)
+    {
+        var user = await _userService.GetUserByPrincipalAsync(User);
+        if (user == null)
+        {
+            throw new UnauthorizedAccessException();
+        }
+
+        var license = await ApiHelpers.ReadJsonFileFromBody<OrganizationLicense>(HttpContext, model.License);
+        if (license == null)
+        {
+            throw new BadRequestException("Invalid license");
+        }
+
+        var result = await _organizationService.SignUpAsync(license, user, model.Key,
+            model.CollectionName, model.Keys?.PublicKey, model.Keys?.EncryptedPrivateKey);
+        return new OrganizationResponseModel(result.Item1);
+    }
+
+    [HttpPost("{id}")]
+    public async Task PostLicenseAsync(string id, LicenseRequestModel model)
+    {
+        var orgIdGuid = new Guid(id);
+        if (!await _currentContext.OrganizationOwner(orgIdGuid))
+        {
+            throw new NotFoundException();
+        }
+
+        var license = await ApiHelpers.ReadJsonFileFromBody<OrganizationLicense>(HttpContext, model.License);
+        if (license == null)
+        {
+            throw new BadRequestException("Invalid license");
+        }
+
+        await _organizationService.UpdateLicenseAsync(new Guid(id), license);
+    }
+
+    [HttpPost("{id}/sync")]
+    public async Task SyncLicenseAsync(string id)
+    {
+        var organization = await _organizationRepository.GetByIdAsync(new Guid(id));
+        if (organization == null)
+        {
+            throw new NotFoundException();
+        }
+
+        if (!await _currentContext.OrganizationOwner(organization.Id))
+        {
+            throw new NotFoundException();
+        }
+
+        var billingSyncConnection =
+            (await _organizationConnectionRepository.GetByOrganizationIdTypeAsync(organization.Id,
+                OrganizationConnectionType.CloudBillingSync)).FirstOrDefault();
+        if (billingSyncConnection == null)
+        {
+            throw new NotFoundException("Unable to get Cloud Billing Sync connection");
+        }
+
+        var license =
+            await _selfHostedGetOrganizationLicenseQuery.GetLicenseAsync(organization, billingSyncConnection);
+
+        await _organizationService.UpdateLicenseAsync(organization.Id, license);
+
+        var config = billingSyncConnection.GetConfig<BillingSyncConfig>();
+        config.LastLicenseSync = DateTime.Now;
+        billingSyncConnection.SetConfig(config);
+        await _organizationConnectionRepository.ReplaceAsync(billingSyncConnection);
+    }
+}
diff --git a/src/Api/Models/Request/Organizations/OrganizationConnectionRequestModel.cs b/src/Api/Models/Request/Organizations/OrganizationConnectionRequestModel.cs
index 9dbc9ca0a0..96a444c27a 100644
--- a/src/Api/Models/Request/Organizations/OrganizationConnectionRequestModel.cs
+++ b/src/Api/Models/Request/Organizations/OrganizationConnectionRequestModel.cs
@@ -2,6 +2,7 @@
 using Bit.Core.Enums;
 using Bit.Core.Exceptions;
 using Bit.Core.Models.Data.Organizations.OrganizationConnections;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 using Bit.Core.Utilities;
 
 namespace Bit.Api.Models.Request.Organizations;
@@ -17,7 +18,7 @@ public class OrganizationConnectionRequestModel
 }
 
 
-public class OrganizationConnectionRequestModel<T> : OrganizationConnectionRequestModel where T : new()
+public class OrganizationConnectionRequestModel<T> : OrganizationConnectionRequestModel where T : IConnectionConfig
 {
     public T ParsedConfig { get; private set; }
 
diff --git a/src/Core/Entities/OrganizationConnection.cs b/src/Core/Entities/OrganizationConnection.cs
index cc07177384..5b466fb4a6 100644
--- a/src/Core/Entities/OrganizationConnection.cs
+++ b/src/Core/Entities/OrganizationConnection.cs
@@ -1,15 +1,16 @@
 using System.Text.Json;
 using Bit.Core.Enums;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 using Bit.Core.Utilities;
 
 namespace Bit.Core.Entities;
 
-public class OrganizationConnection<T> : OrganizationConnection where T : new()
+public class OrganizationConnection<T> : OrganizationConnection where T : IConnectionConfig
 {
     public new T Config
     {
         get => base.GetConfig<T>();
-        set => base.SetConfig<T>(value);
+        set => base.SetConfig(value);
     }
 }
 
@@ -26,7 +27,7 @@ public class OrganizationConnection : ITableObject<Guid>
         Id = CoreHelpers.GenerateComb();
     }
 
-    public T GetConfig<T>() where T : new()
+    public T GetConfig<T>() where T : IConnectionConfig
     {
         try
         {
@@ -38,8 +39,32 @@ public class OrganizationConnection : ITableObject<Guid>
         }
     }
 
-    public void SetConfig<T>(T config) where T : new()
+    public void SetConfig<T>(T config) where T : IConnectionConfig
     {
         Config = JsonSerializer.Serialize(config);
     }
+
+    public bool Validate<T>(out string exception) where T : IConnectionConfig
+    {
+        if (!Enabled)
+        {
+            exception = $"Connection disabled for organization {OrganizationId}";
+            return false;
+        }
+
+        if (string.IsNullOrWhiteSpace(Config))
+        {
+            exception = $"No saved Connection config for organization {OrganizationId}";
+            return false;
+        }
+
+        var config = GetConfig<T>();
+        if (config == null)
+        {
+            exception = $"Error parsing Connection config for organization {OrganizationId}";
+            return false;
+        }
+
+        return config.Validate(out exception);
+    }
 }
diff --git a/src/Core/Models/Api/Request/OrganizationLicenses/SelfHostedOrganizationLicenseRequestModel.cs b/src/Core/Models/Api/Request/OrganizationLicenses/SelfHostedOrganizationLicenseRequestModel.cs
new file mode 100644
index 0000000000..365d88877e
--- /dev/null
+++ b/src/Core/Models/Api/Request/OrganizationLicenses/SelfHostedOrganizationLicenseRequestModel.cs
@@ -0,0 +1,7 @@
+namespace Bit.Core.Models.Api.OrganizationLicenses;
+
+public class SelfHostedOrganizationLicenseRequestModel
+{
+    public string LicenseKey { get; set; }
+    public string BillingSyncKey { get; set; }
+}
diff --git a/src/Core/Models/Data/Organizations/OrganizationConnections/OrganizationConnectionData.cs b/src/Core/Models/Data/Organizations/OrganizationConnections/OrganizationConnectionData.cs
index 3a3edaed45..7a9aa77110 100644
--- a/src/Core/Models/Data/Organizations/OrganizationConnections/OrganizationConnectionData.cs
+++ b/src/Core/Models/Data/Organizations/OrganizationConnections/OrganizationConnectionData.cs
@@ -1,9 +1,10 @@
 using Bit.Core.Entities;
 using Bit.Core.Enums;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 
 namespace Bit.Core.Models.Data.Organizations.OrganizationConnections;
 
-public class OrganizationConnectionData<T> where T : new()
+public class OrganizationConnectionData<T> where T : IConnectionConfig
 {
     public Guid? Id { get; set; }
     public OrganizationConnectionType Type { get; set; }
diff --git a/src/Core/Models/OrganizationConnectionConfigs/BillingSyncConfig.cs b/src/Core/Models/OrganizationConnectionConfigs/BillingSyncConfig.cs
index 204e165d05..07f07093d2 100644
--- a/src/Core/Models/OrganizationConnectionConfigs/BillingSyncConfig.cs
+++ b/src/Core/Models/OrganizationConnectionConfigs/BillingSyncConfig.cs
@@ -1,7 +1,20 @@
 namespace Bit.Core.Models.OrganizationConnectionConfigs;
 
-public class BillingSyncConfig
+public class BillingSyncConfig : IConnectionConfig
 {
     public string BillingSyncKey { get; set; }
     public Guid CloudOrganizationId { get; set; }
+    public DateTime? LastLicenseSync { get; set; }
+
+    public bool Validate(out string exception)
+    {
+        if (string.IsNullOrWhiteSpace(BillingSyncKey))
+        {
+            exception = "Failed to get Billing Sync Key";
+            return false;
+        }
+
+        exception = "";
+        return true;
+    }
 }
diff --git a/src/Core/Models/OrganizationConnectionConfigs/IConnectionConfig.cs b/src/Core/Models/OrganizationConnectionConfigs/IConnectionConfig.cs
new file mode 100644
index 0000000000..9b02c359e4
--- /dev/null
+++ b/src/Core/Models/OrganizationConnectionConfigs/IConnectionConfig.cs
@@ -0,0 +1,6 @@
+namespace Bit.Core.Models.OrganizationConnectionConfigs;
+
+public interface IConnectionConfig
+{
+    bool Validate(out string exception);
+}
diff --git a/src/Core/Models/OrganizationConnectionConfigs/ScimConfig.cs b/src/Core/Models/OrganizationConnectionConfigs/ScimConfig.cs
index 63a1606cb2..8a4fcb4e8c 100644
--- a/src/Core/Models/OrganizationConnectionConfigs/ScimConfig.cs
+++ b/src/Core/Models/OrganizationConnectionConfigs/ScimConfig.cs
@@ -3,9 +3,21 @@ using Bit.Core.Enums;
 
 namespace Bit.Core.Models.OrganizationConnectionConfigs;
 
-public class ScimConfig
+public class ScimConfig : IConnectionConfig
 {
     public bool Enabled { get; set; }
     [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
     public ScimProviderType? ScimProvider { get; set; }
+
+    public bool Validate(out string exception)
+    {
+        if (!Enabled)
+        {
+            exception = "Scim Config is disabled";
+            return false;
+        }
+
+        exception = "";
+        return true;
+    }
 }
diff --git a/src/Core/OrganizationFeatures/OrganizationConnections/CreateOrganizationConnectionCommand.cs b/src/Core/OrganizationFeatures/OrganizationConnections/CreateOrganizationConnectionCommand.cs
index e3f308bc57..6c019001c0 100644
--- a/src/Core/OrganizationFeatures/OrganizationConnections/CreateOrganizationConnectionCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationConnections/CreateOrganizationConnectionCommand.cs
@@ -1,5 +1,6 @@
 using Bit.Core.Entities;
 using Bit.Core.Models.Data.Organizations.OrganizationConnections;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 using Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 using Bit.Core.Repositories;
 
@@ -14,7 +15,7 @@ public class CreateOrganizationConnectionCommand : ICreateOrganizationConnection
         _organizationConnectionRepository = organizationConnectionRepository;
     }
 
-    public async Task<OrganizationConnection> CreateAsync<T>(OrganizationConnectionData<T> connectionData) where T : new()
+    public async Task<OrganizationConnection> CreateAsync<T>(OrganizationConnectionData<T> connectionData) where T : IConnectionConfig
     {
         return await _organizationConnectionRepository.CreateAsync(connectionData.ToEntity());
     }
diff --git a/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/ICreateOrganizationConnectionCommand.cs b/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/ICreateOrganizationConnectionCommand.cs
index b31920b10a..a97be09c3b 100644
--- a/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/ICreateOrganizationConnectionCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/ICreateOrganizationConnectionCommand.cs
@@ -1,9 +1,10 @@
 using Bit.Core.Entities;
 using Bit.Core.Models.Data.Organizations.OrganizationConnections;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 
 namespace Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 
 public interface ICreateOrganizationConnectionCommand
 {
-    Task<OrganizationConnection> CreateAsync<T>(OrganizationConnectionData<T> connectionData) where T : new();
+    Task<OrganizationConnection> CreateAsync<T>(OrganizationConnectionData<T> connectionData) where T : IConnectionConfig;
 }
diff --git a/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IUpdateOrganizationConnectionCommand.cs b/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IUpdateOrganizationConnectionCommand.cs
index 742e89c970..b245b89693 100644
--- a/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IUpdateOrganizationConnectionCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IUpdateOrganizationConnectionCommand.cs
@@ -1,9 +1,10 @@
 using Bit.Core.Entities;
 using Bit.Core.Models.Data.Organizations.OrganizationConnections;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 
 namespace Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 
 public interface IUpdateOrganizationConnectionCommand
 {
-    Task<OrganizationConnection> UpdateAsync<T>(OrganizationConnectionData<T> connectionData) where T : new();
+    Task<OrganizationConnection> UpdateAsync<T>(OrganizationConnectionData<T> connectionData) where T : IConnectionConfig;
 }
diff --git a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Interfaces/IValidateBillingSyncKeyCommand.cs b/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IValidateBillingSyncKeyCommand.cs
similarity index 64%
rename from src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Interfaces/IValidateBillingSyncKeyCommand.cs
rename to src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IValidateBillingSyncKeyCommand.cs
index 53e926903f..9fb979548a 100644
--- a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Interfaces/IValidateBillingSyncKeyCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationConnections/Interfaces/IValidateBillingSyncKeyCommand.cs
@@ -1,6 +1,6 @@
 using Bit.Core.Entities;
 
-namespace Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
+namespace Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 
 public interface IValidateBillingSyncKeyCommand
 {
diff --git a/src/Core/OrganizationFeatures/OrganizationConnections/UpdateOrganizationConnectionCommand.cs b/src/Core/OrganizationFeatures/OrganizationConnections/UpdateOrganizationConnectionCommand.cs
index 0d872b6f1f..3e64fd47ab 100644
--- a/src/Core/OrganizationFeatures/OrganizationConnections/UpdateOrganizationConnectionCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationConnections/UpdateOrganizationConnectionCommand.cs
@@ -1,6 +1,7 @@
 using Bit.Core.Entities;
 using Bit.Core.Exceptions;
 using Bit.Core.Models.Data.Organizations.OrganizationConnections;
+using Bit.Core.Models.OrganizationConnectionConfigs;
 using Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 using Bit.Core.Repositories;
 
@@ -15,7 +16,7 @@ public class UpdateOrganizationConnectionCommand : IUpdateOrganizationConnection
         _organizationConnectionRepository = organizationConnectionRepository;
     }
 
-    public async Task<OrganizationConnection> UpdateAsync<T>(OrganizationConnectionData<T> connectionData) where T : new()
+    public async Task<OrganizationConnection> UpdateAsync<T>(OrganizationConnectionData<T> connectionData) where T : IConnectionConfig
     {
         if (!connectionData.Id.HasValue)
         {
diff --git a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/ValidateBillingSyncKeyCommand.cs b/src/Core/OrganizationFeatures/OrganizationConnections/ValidateBillingSyncKeyCommand.cs
similarity index 70%
rename from src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/ValidateBillingSyncKeyCommand.cs
rename to src/Core/OrganizationFeatures/OrganizationConnections/ValidateBillingSyncKeyCommand.cs
index 19c4398a70..a764bbcf23 100644
--- a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/ValidateBillingSyncKeyCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationConnections/ValidateBillingSyncKeyCommand.cs
@@ -1,20 +1,17 @@
 using Bit.Core.Entities;
 using Bit.Core.Exceptions;
-using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
+using Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
 using Bit.Core.Repositories;
 
-namespace Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Cloud;
+namespace Bit.Core.OrganizationFeatures.OrganizationConnections;
 
 public class ValidateBillingSyncKeyCommand : IValidateBillingSyncKeyCommand
 {
-    private readonly IOrganizationSponsorshipRepository _organizationSponsorshipRepository;
     private readonly IOrganizationApiKeyRepository _apiKeyRepository;
 
     public ValidateBillingSyncKeyCommand(
-        IOrganizationSponsorshipRepository organizationSponsorshipRepository,
         IOrganizationApiKeyRepository organizationApiKeyRepository)
     {
-        _organizationSponsorshipRepository = organizationSponsorshipRepository;
         _apiKeyRepository = organizationApiKeyRepository;
     }
 
diff --git a/src/Core/OrganizationFeatures/OrganizationLicenses/Cloud/CloudGetOrganizationLicenseQuery.cs b/src/Core/OrganizationFeatures/OrganizationLicenses/Cloud/CloudGetOrganizationLicenseQuery.cs
new file mode 100644
index 0000000000..ff8a6d34fb
--- /dev/null
+++ b/src/Core/OrganizationFeatures/OrganizationLicenses/Cloud/CloudGetOrganizationLicenseQuery.cs
@@ -0,0 +1,38 @@
+using Bit.Core.Entities;
+using Bit.Core.Exceptions;
+using Bit.Core.Models.Business;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
+using Bit.Core.Repositories;
+using Bit.Core.Services;
+
+namespace Bit.Core.OrganizationFeatures.OrganizationLicenses;
+
+public class CloudGetOrganizationLicenseQuery : ICloudGetOrganizationLicenseQuery
+{
+    private readonly IInstallationRepository _installationRepository;
+    private readonly IPaymentService _paymentService;
+    private readonly ILicensingService _licensingService;
+
+    public CloudGetOrganizationLicenseQuery(
+        IInstallationRepository installationRepository,
+        IPaymentService paymentService,
+        ILicensingService licensingService)
+    {
+        _installationRepository = installationRepository;
+        _paymentService = paymentService;
+        _licensingService = licensingService;
+    }
+
+    public async Task<OrganizationLicense> GetLicenseAsync(Organization organization, Guid installationId,
+        int? version = null)
+    {
+        var installation = await _installationRepository.GetByIdAsync(installationId);
+        if (installation is not { Enabled: true })
+        {
+            throw new BadRequestException("Invalid installation id");
+        }
+
+        var subInfo = await _paymentService.GetSubscriptionAsync(organization);
+        return new OrganizationLicense(organization, subInfo, installationId, _licensingService, version);
+    }
+}
diff --git a/src/Core/OrganizationFeatures/OrganizationLicenses/Interfaces/IGetOrganizationLicenseQuery.cs b/src/Core/OrganizationFeatures/OrganizationLicenses/Interfaces/IGetOrganizationLicenseQuery.cs
new file mode 100644
index 0000000000..2c66833e63
--- /dev/null
+++ b/src/Core/OrganizationFeatures/OrganizationLicenses/Interfaces/IGetOrganizationLicenseQuery.cs
@@ -0,0 +1,15 @@
+using Bit.Core.Entities;
+using Bit.Core.Models.Business;
+
+namespace Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
+
+public interface ICloudGetOrganizationLicenseQuery
+{
+    Task<OrganizationLicense> GetLicenseAsync(Organization organization, Guid installationId,
+        int? version = null);
+}
+
+public interface ISelfHostedGetOrganizationLicenseQuery
+{
+    Task<OrganizationLicense> GetLicenseAsync(Organization organization, OrganizationConnection billingSyncConnection);
+}
diff --git a/src/Core/OrganizationFeatures/OrganizationLicenses/SelfHosted/SelfHostedGetOrganizationLicenseQuery.cs b/src/Core/OrganizationFeatures/OrganizationLicenses/SelfHosted/SelfHostedGetOrganizationLicenseQuery.cs
new file mode 100644
index 0000000000..84ae0a27db
--- /dev/null
+++ b/src/Core/OrganizationFeatures/OrganizationLicenses/SelfHosted/SelfHostedGetOrganizationLicenseQuery.cs
@@ -0,0 +1,66 @@
+using Bit.Core.Context;
+using Bit.Core.Entities;
+using Bit.Core.Exceptions;
+using Bit.Core.Models.Api.OrganizationLicenses;
+using Bit.Core.Models.Business;
+using Bit.Core.Models.OrganizationConnectionConfigs;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
+using Bit.Core.Services;
+using Bit.Core.Settings;
+using Microsoft.Extensions.Logging;
+
+namespace Bit.Core.OrganizationFeatures.OrganizationLicenses;
+
+public class SelfHostedGetOrganizationLicenseQuery : BaseIdentityClientService, ISelfHostedGetOrganizationLicenseQuery
+{
+    private readonly IGlobalSettings _globalSettings;
+
+    public SelfHostedGetOrganizationLicenseQuery(IHttpClientFactory httpFactory, IGlobalSettings globalSettings, ILogger<SelfHostedGetOrganizationLicenseQuery> logger, ICurrentContext currentContext)
+        : base(
+            httpFactory,
+            globalSettings.Installation.ApiUri,
+            globalSettings.Installation.IdentityUri,
+            "api.licensing",
+            $"installation.{globalSettings.Installation.Id}",
+            globalSettings.Installation.Key,
+            logger)
+    {
+        _globalSettings = globalSettings;
+    }
+
+    public async Task<OrganizationLicense> GetLicenseAsync(Organization organization, OrganizationConnection billingSyncConnection)
+    {
+        if (!_globalSettings.SelfHosted)
+        {
+            throw new BadRequestException("This action is only available for self-hosted.");
+        }
+
+        if (!_globalSettings.EnableCloudCommunication)
+        {
+            throw new BadRequestException("Cloud communication is disabled in global settings");
+        }
+
+        if (!billingSyncConnection.Validate<BillingSyncConfig>(out var exception))
+        {
+            throw new BadRequestException(exception);
+        }
+
+        var billingSyncConfig = billingSyncConnection.GetConfig<BillingSyncConfig>();
+        var cloudOrganizationId = billingSyncConfig.CloudOrganizationId;
+
+        var response = await SendAsync<SelfHostedOrganizationLicenseRequestModel, OrganizationLicense>(
+            HttpMethod.Get, $"licenses/organization/{cloudOrganizationId}", new SelfHostedOrganizationLicenseRequestModel()
+            {
+                BillingSyncKey = billingSyncConfig.BillingSyncKey,
+                LicenseKey = organization.LicenseKey,
+            }, true);
+
+        if (response == null)
+        {
+            _logger.LogDebug("Organization License sync failed for '{OrgId}'", organization.Id);
+            throw new BadRequestException("An error has occurred. Check your internet connection and ensure the billing token is correct.");
+        }
+
+        return response;
+    }
+}
diff --git a/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs b/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs
index 18c2f44dc9..b8e2a775e2 100644
--- a/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs
+++ b/src/Core/OrganizationFeatures/OrganizationServiceCollectionExtensions.cs
@@ -7,6 +7,8 @@ using Bit.Core.OrganizationFeatures.OrganizationCollections;
 using Bit.Core.OrganizationFeatures.OrganizationCollections.Interfaces;
 using Bit.Core.OrganizationFeatures.OrganizationConnections;
 using Bit.Core.OrganizationFeatures.OrganizationConnections.Interfaces;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
 using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise;
 using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Cloud;
 using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Interfaces;
@@ -32,6 +34,7 @@ public static class OrganizationServiceCollectionExtensions
         services.AddOrganizationApiKeyCommandsQueries();
         services.AddOrganizationCollectionCommands();
         services.AddOrganizationGroupCommands();
+        services.AddOrganizationLicenseCommandQueries();
     }
 
     private static void AddOrganizationConnectionCommands(this IServiceCollection services)
@@ -85,6 +88,12 @@ public static class OrganizationServiceCollectionExtensions
         services.AddScoped<IUpdateGroupCommand, UpdateGroupCommand>();
     }
 
+    private static void AddOrganizationLicenseCommandQueries(this IServiceCollection services)
+    {
+        services.AddScoped<ICloudGetOrganizationLicenseQuery, CloudGetOrganizationLicenseQuery>();
+        services.AddScoped<ISelfHostedGetOrganizationLicenseQuery, SelfHostedGetOrganizationLicenseQuery>();
+    }
+
     private static void AddTokenizers(this IServiceCollection services)
     {
         services.AddSingleton<IDataProtectorTokenFactory<OrganizationSponsorshipOfferTokenable>>(serviceProvider =>
diff --git a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs b/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs
index eed143838e..0d22b53bad 100644
--- a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs
+++ b/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs
@@ -48,20 +48,13 @@ public class SelfHostedSyncSponsorshipsCommand : BaseIdentityClientService, ISel
         {
             throw new BadRequestException("Failed to sync instance with cloud - Cloud communication is disabled in global settings");
         }
-        if (!billingSyncConnection.Enabled)
+
+        if (!billingSyncConnection.Validate<BillingSyncConfig>(out var exception))
         {
-            throw new BadRequestException($"Billing Sync Key disabled for organization {organizationId}");
-        }
-        if (string.IsNullOrWhiteSpace(billingSyncConnection.Config))
-        {
-            throw new BadRequestException($"No Billing Sync Key known for organization {organizationId}");
-        }
-        var billingSyncConfig = billingSyncConnection.GetConfig<BillingSyncConfig>();
-        if (billingSyncConfig == null || string.IsNullOrWhiteSpace(billingSyncConfig.BillingSyncKey))
-        {
-            throw new BadRequestException($"Failed to get Billing Sync Key for organization {organizationId}");
+            throw new BadRequestException(exception);
         }
 
+        var billingSyncConfig = billingSyncConnection.GetConfig<BillingSyncConfig>();
         var organizationSponsorshipsDict = (await _organizationSponsorshipRepository.GetManyBySponsoringOrganizationAsync(organizationId))
             .ToDictionary(i => i.SponsoringOrganizationUserId);
         if (!organizationSponsorshipsDict.Any())
diff --git a/src/Core/Services/IOrganizationService.cs b/src/Core/Services/IOrganizationService.cs
index f3f3f16139..5383c1a3e3 100644
--- a/src/Core/Services/IOrganizationService.cs
+++ b/src/Core/Services/IOrganizationService.cs
@@ -56,9 +56,6 @@ public interface IOrganizationService
         IEnumerable<Guid> organizationUserIds, Guid? deletingUserId);
     Task UpdateUserGroupsAsync(OrganizationUser organizationUser, IEnumerable<Guid> groupIds, Guid? loggedInUserId);
     Task UpdateUserResetPasswordEnrollmentAsync(Guid organizationId, Guid userId, string resetPasswordKey, Guid? callingUserId);
-    Task<OrganizationLicense> GenerateLicenseAsync(Guid organizationId, Guid installationId);
-    Task<OrganizationLicense> GenerateLicenseAsync(Organization organization, Guid installationId,
-        int? version = null);
     Task ImportAsync(Guid organizationId, Guid? importingUserId, IEnumerable<ImportedGroup> groups,
         IEnumerable<ImportedOrganizationUser> newUsers, IEnumerable<string> removeUserExternalIds,
         bool overwriteExisting);
diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs
index bff3b9fa4a..8f89e7ed6e 100644
--- a/src/Core/Services/Implementations/OrganizationService.cs
+++ b/src/Core/Services/Implementations/OrganizationService.cs
@@ -1926,30 +1926,6 @@ public class OrganizationService : IOrganizationService
             EventType.OrganizationUser_ResetPassword_Enroll : EventType.OrganizationUser_ResetPassword_Withdraw);
     }
 
-    public async Task<OrganizationLicense> GenerateLicenseAsync(Guid organizationId, Guid installationId)
-    {
-        var organization = await GetOrgById(organizationId);
-        return await GenerateLicenseAsync(organization, installationId);
-    }
-
-    public async Task<OrganizationLicense> GenerateLicenseAsync(Organization organization, Guid installationId,
-        int? version = null)
-    {
-        if (organization == null)
-        {
-            throw new NotFoundException();
-        }
-
-        var installation = await _installationRepository.GetByIdAsync(installationId);
-        if (installation == null || !installation.Enabled)
-        {
-            throw new BadRequestException("Invalid installation id");
-        }
-
-        var subInfo = await _paymentService.GetSubscriptionAsync(organization);
-        return new OrganizationLicense(organization, subInfo, installationId, _licensingService, version);
-    }
-
     public async Task<OrganizationUser> InviteUserAsync(Guid organizationId, Guid? invitingUserId, string email,
         OrganizationUserType type, bool accessAll, string externalId, IEnumerable<CollectionAccessSelection> collections,
         IEnumerable<Guid> groups)
diff --git a/test/Api.Test/Controllers/OrganizationConnectionsControllerTests.cs b/test/Api.Test/Controllers/OrganizationConnectionsControllerTests.cs
index 594e708bdf..0f243b9efb 100644
--- a/test/Api.Test/Controllers/OrganizationConnectionsControllerTests.cs
+++ b/test/Api.Test/Controllers/OrganizationConnectionsControllerTests.cs
@@ -366,7 +366,7 @@ public class OrganizationConnectionsControllerTests
     }
 
     private static OrganizationConnectionRequestModel<T> RequestModelFromEntity<T>(OrganizationConnection entity)
-        where T : new()
+        where T : IConnectionConfig
     {
         return new(new OrganizationConnectionRequestModel()
         {
diff --git a/test/Api.Test/Controllers/OrganizationsControllerTests.cs b/test/Api.Test/Controllers/OrganizationsControllerTests.cs
index fa1855c70d..f056beea80 100644
--- a/test/Api.Test/Controllers/OrganizationsControllerTests.cs
+++ b/test/Api.Test/Controllers/OrganizationsControllerTests.cs
@@ -6,6 +6,7 @@ using Bit.Core.Entities;
 using Bit.Core.Exceptions;
 using Bit.Core.Models.Data;
 using Bit.Core.OrganizationFeatures.OrganizationApiKeys.Interfaces;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses.Interfaces;
 using Bit.Core.Repositories;
 using Bit.Core.Services;
 using Bit.Core.Settings;
@@ -29,6 +30,7 @@ public class OrganizationsControllerTests : IDisposable
     private readonly IGetOrganizationApiKeyQuery _getOrganizationApiKeyQuery;
     private readonly IRotateOrganizationApiKeyCommand _rotateOrganizationApiKeyCommand;
     private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository;
+    private readonly ICloudGetOrganizationLicenseQuery _cloudGetOrganizationLicenseQuery;
     private readonly ICreateOrganizationApiKeyCommand _createOrganizationApiKeyCommand;
 
     private readonly OrganizationsController _sut;
@@ -48,12 +50,13 @@ public class OrganizationsControllerTests : IDisposable
         _rotateOrganizationApiKeyCommand = Substitute.For<IRotateOrganizationApiKeyCommand>();
         _organizationApiKeyRepository = Substitute.For<IOrganizationApiKeyRepository>();
         _userService = Substitute.For<IUserService>();
+        _cloudGetOrganizationLicenseQuery = Substitute.For<ICloudGetOrganizationLicenseQuery>();
         _createOrganizationApiKeyCommand = Substitute.For<ICreateOrganizationApiKeyCommand>();
 
         _sut = new OrganizationsController(_organizationRepository, _organizationUserRepository,
             _policyRepository, _organizationService, _userService, _paymentService, _currentContext,
             _ssoConfigRepository, _ssoConfigService, _getOrganizationApiKeyQuery, _rotateOrganizationApiKeyCommand,
-            _createOrganizationApiKeyCommand, _organizationApiKeyRepository, _globalSettings);
+            _createOrganizationApiKeyCommand, _organizationApiKeyRepository, _cloudGetOrganizationLicenseQuery, _globalSettings);
     }
 
     public void Dispose()
diff --git a/test/Common/AutoFixture/SutProviderExtensions.cs b/test/Common/AutoFixture/SutProviderExtensions.cs
new file mode 100644
index 0000000000..1fdf226539
--- /dev/null
+++ b/test/Common/AutoFixture/SutProviderExtensions.cs
@@ -0,0 +1,50 @@
+using AutoFixture;
+using Bit.Core.Services;
+using Bit.Core.Settings;
+using NSubstitute;
+using RichardSzalay.MockHttp;
+
+namespace Bit.Test.Common.AutoFixture;
+
+public static class SutProviderExtensions
+{
+    public static SutProvider<T> ConfigureBaseIdentityClientService<T>(this SutProvider<T> sutProvider,
+        string requestUrlFragment, HttpMethod requestHttpMethod, string identityResponse = null, string apiResponse = null)
+        where T : BaseIdentityClientService
+    {
+        var fixture = new Fixture().WithAutoNSubstitutionsAutoPopulatedProperties();
+        fixture.AddMockHttp();
+
+        var settings = fixture.Create<IGlobalSettings>();
+        settings.SelfHosted = true;
+        settings.EnableCloudCommunication = true;
+
+        var apiUri = fixture.Create<Uri>();
+        var identityUri = fixture.Create<Uri>();
+        settings.Installation.ApiUri.Returns(apiUri.ToString());
+        settings.Installation.IdentityUri.Returns(identityUri.ToString());
+
+        var apiHandler = new MockHttpMessageHandler();
+        var identityHandler = new MockHttpMessageHandler();
+        var syncUri = string.Concat(apiUri, requestUrlFragment);
+        var tokenUri = string.Concat(identityUri, "connect/token");
+
+        apiHandler.When(requestHttpMethod, syncUri)
+            .Respond("application/json", apiResponse);
+        identityHandler.When(HttpMethod.Post, tokenUri)
+            .Respond("application/json", identityResponse ?? "{\"access_token\":\"string\",\"expires_in\":3600,\"token_type\":\"Bearer\",\"scope\":\"string\"}");
+
+
+        var apiHttp = apiHandler.ToHttpClient();
+        var identityHttp = identityHandler.ToHttpClient();
+
+        var mockHttpClientFactory = Substitute.For<IHttpClientFactory>();
+        mockHttpClientFactory.CreateClient(Arg.Is("client")).Returns(apiHttp);
+        mockHttpClientFactory.CreateClient(Arg.Is("identity")).Returns(identityHttp);
+
+        return sutProvider
+            .SetDependency(settings)
+            .SetDependency(mockHttpClientFactory)
+            .Create();
+    }
+}
diff --git a/test/Core.Test/AutoFixture/SubscriptionInfoCustomization.cs b/test/Core.Test/AutoFixture/SubscriptionInfoCustomization.cs
new file mode 100644
index 0000000000..d16d13b578
--- /dev/null
+++ b/test/Core.Test/AutoFixture/SubscriptionInfoCustomization.cs
@@ -0,0 +1,18 @@
+using AutoFixture;
+using Bit.Core.Models.Business;
+using Bit.Test.Common.AutoFixture.Attributes;
+
+namespace Bit.Core.Test.AutoFixture;
+
+public class SubscriptionInfoCustomizeAttribute : BitCustomizeAttribute
+{
+    public override ICustomization GetCustomization() => new SubscriptionInfoCustomization();
+}
+public class SubscriptionInfoCustomization : ICustomization
+{
+    public void Customize(IFixture fixture)
+    {
+        // The Subscription property uses the external Stripe library, which Autofixture doesn't handle
+        fixture.Customize<SubscriptionInfo>(c => c.Without(s => s.Subscription));
+    }
+}
diff --git a/test/Core.Test/Entities/OrganizationConnectionTests.cs b/test/Core.Test/Entities/OrganizationConnectionTests.cs
new file mode 100644
index 0000000000..32690416c2
--- /dev/null
+++ b/test/Core.Test/Entities/OrganizationConnectionTests.cs
@@ -0,0 +1,78 @@
+using Bit.Core.Entities;
+using Bit.Core.Enums;
+using Bit.Core.Models.OrganizationConnectionConfigs;
+using Bit.Test.Common.AutoFixture.Attributes;
+using Xunit;
+
+namespace Bit.Core.Test.Entities;
+
+public class OrganizationConnectionTests
+{
+    [Theory]
+    [BitAutoData]
+    public void OrganizationConnection_CanUse_Success(Guid connectionId, Guid organizationId)
+    {
+        var connection = new OrganizationConnection<ScimConfig>()
+        {
+            Id = connectionId,
+            OrganizationId = organizationId,
+            Enabled = true,
+            Type = OrganizationConnectionType.Scim,
+            Config = new ScimConfig() { Enabled = true }
+        };
+
+        Assert.True(connection.Validate<ScimConfig>(out var exception));
+        Assert.True(string.IsNullOrEmpty(exception));
+    }
+
+    [Theory]
+    [BitAutoData]
+    public void OrganizationConnection_CanUse_WhenDisabled_ReturnsFalse(Guid connectionId, Guid organizationId)
+    {
+
+        var connection = new OrganizationConnection<ScimConfig>()
+        {
+            Id = connectionId,
+            OrganizationId = organizationId,
+            Enabled = false,
+            Type = OrganizationConnectionType.Scim,
+            Config = new ScimConfig() { Enabled = true }
+        };
+
+        Assert.False(connection.Validate<ScimConfig>(out var exception));
+        Assert.Contains("Connection disabled", exception);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public void OrganizationConnection_CanUse_WhenNoConfig_ReturnsFalse(Guid connectionId, Guid organizationId)
+    {
+        var connection = new OrganizationConnection<ScimConfig>()
+        {
+            Id = connectionId,
+            OrganizationId = organizationId,
+            Enabled = true,
+            Type = OrganizationConnectionType.Scim,
+        };
+
+        Assert.False(connection.Validate<ScimConfig>(out var exception));
+        Assert.Contains("No saved Connection config", exception);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public void OrganizationConnection_CanUse_WhenConfigInvalid_ReturnsFalse(Guid connectionId, Guid organizationId)
+    {
+        var connection = new OrganizationConnection<ScimConfig>()
+        {
+            Id = connectionId,
+            OrganizationId = organizationId,
+            Enabled = true,
+            Type = OrganizationConnectionType.Scim,
+            Config = new ScimConfig() { Enabled = false }
+        };
+
+        Assert.False(connection.Validate<ScimConfig>(out var exception));
+        Assert.Contains("Scim Config is disabled", exception);
+    }
+}
diff --git a/test/Core.Test/Models/OrganizationConnectionConfigs/BillingSyncConfigTests.cs b/test/Core.Test/Models/OrganizationConnectionConfigs/BillingSyncConfigTests.cs
new file mode 100644
index 0000000000..05e717ebde
--- /dev/null
+++ b/test/Core.Test/Models/OrganizationConnectionConfigs/BillingSyncConfigTests.cs
@@ -0,0 +1,27 @@
+using Bit.Core.Models.OrganizationConnectionConfigs;
+using Bit.Test.Common.AutoFixture.Attributes;
+using Xunit;
+
+namespace Bit.Core.Test.Models.OrganizationConnectionConfigs;
+
+public class BillingSyncConfigTests
+{
+    [Theory]
+    [BitAutoData]
+    public void BillingSyncConfig_CanUse_Success(string billingSyncKey)
+    {
+        var config = new BillingSyncConfig() { BillingSyncKey = billingSyncKey };
+
+        Assert.True(config.Validate(out var exception));
+        Assert.True(string.IsNullOrEmpty(exception));
+    }
+
+    [Fact]
+    public void BillingSyncConfig_CanUse_WhenNoKey_ReturnsFalse()
+    {
+        var config = new BillingSyncConfig();
+
+        Assert.False(config.Validate(out var exception));
+        Assert.Contains("Failed to get Billing Sync Key", exception);
+    }
+}
diff --git a/test/Core.Test/Models/OrganizationConnectionConfigs/ScimConfigTests.cs b/test/Core.Test/Models/OrganizationConnectionConfigs/ScimConfigTests.cs
new file mode 100644
index 0000000000..fa476eea26
--- /dev/null
+++ b/test/Core.Test/Models/OrganizationConnectionConfigs/ScimConfigTests.cs
@@ -0,0 +1,23 @@
+using Bit.Core.Models.OrganizationConnectionConfigs;
+using Xunit;
+
+namespace Bit.Core.Test.Models.OrganizationConnectionConfigs;
+
+public class ScimConfigTests
+{
+    [Fact]
+    public void ScimConfig_CanUse_Success()
+    {
+        var config = new ScimConfig() { Enabled = true };
+        Assert.True(config.Validate(out var exception));
+        Assert.True(string.IsNullOrEmpty(exception));
+    }
+
+    [Fact]
+    public void ScimConfig_CanUse_WhenDisabled_ReturnsFalse()
+    {
+        var config = new ScimConfig() { Enabled = false };
+        Assert.False(config.Validate(out var exception));
+        Assert.Contains("Config is disabled", exception);
+    }
+}
diff --git a/test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/ValidateBillingSyncKeyCommandTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationConnections/ValidateBillingSyncKeyCommandTests.cs
similarity index 91%
rename from test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/ValidateBillingSyncKeyCommandTests.cs
rename to test/Core.Test/OrganizationFeatures/OrganizationConnections/ValidateBillingSyncKeyCommandTests.cs
index 9b01e3035f..349f0316d7 100644
--- a/test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/Cloud/ValidateBillingSyncKeyCommandTests.cs
+++ b/test/Core.Test/OrganizationFeatures/OrganizationConnections/ValidateBillingSyncKeyCommandTests.cs
@@ -1,14 +1,14 @@
 using Bit.Core.Entities;
 using Bit.Core.Enums;
 using Bit.Core.Exceptions;
-using Bit.Core.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Cloud;
+using Bit.Core.OrganizationFeatures.OrganizationConnections;
 using Bit.Core.Repositories;
 using Bit.Test.Common.AutoFixture;
 using Bit.Test.Common.AutoFixture.Attributes;
 using NSubstitute;
 using Xunit;
 
-namespace Bit.Core.Test.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.Cloud;
+namespace Bit.Core.Test.OrganizationFeatures.OrganizationConnections;
 
 [SutProviderCustomize]
 public class ValidateBillingSyncKeyCommandTests
diff --git a/test/Core.Test/OrganizationFeatures/OrganizationLicenses/CloudGetOrganizationLicenseQueryTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationLicenses/CloudGetOrganizationLicenseQueryTests.cs
new file mode 100644
index 0000000000..cb896ed717
--- /dev/null
+++ b/test/Core.Test/OrganizationFeatures/OrganizationLicenses/CloudGetOrganizationLicenseQueryTests.cs
@@ -0,0 +1,64 @@
+using Bit.Core.Entities;
+using Bit.Core.Enums;
+using Bit.Core.Exceptions;
+using Bit.Core.Models.Business;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses;
+using Bit.Core.Repositories;
+using Bit.Core.Services;
+using Bit.Core.Test.AutoFixture;
+using Bit.Test.Common.AutoFixture;
+using Bit.Test.Common.AutoFixture.Attributes;
+using NSubstitute;
+using NSubstitute.ReturnsExtensions;
+using Xunit;
+
+namespace Bit.Core.Test.OrganizationFeatures.OrganizationLicenses;
+
+[SubscriptionInfoCustomize]
+[OrganizationLicenseCustomize]
+[SutProviderCustomize]
+public class CloudGetOrganizationLicenseQueryTests
+{
+    [Theory]
+    [BitAutoData]
+    public async Task GetLicenseAsync_InvalidInstallationId_Throws(SutProvider<CloudGetOrganizationLicenseQuery> sutProvider,
+        Organization organization, Guid installationId, int version)
+    {
+        sutProvider.GetDependency<IInstallationRepository>().GetByIdAsync(installationId).ReturnsNull();
+        var exception = await Assert.ThrowsAsync<BadRequestException>(
+            async () => await sutProvider.Sut.GetLicenseAsync(organization, installationId, version));
+        Assert.Contains("Invalid installation id", exception.Message);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public async Task GetLicenseAsync_DisabledOrganization_Throws(SutProvider<CloudGetOrganizationLicenseQuery> sutProvider,
+        Organization organization, Guid installationId, Installation installation)
+    {
+        installation.Enabled = false;
+        sutProvider.GetDependency<IInstallationRepository>().GetByIdAsync(installationId).Returns(installation);
+
+        var exception = await Assert.ThrowsAsync<BadRequestException>(
+            async () => await sutProvider.Sut.GetLicenseAsync(organization, installationId));
+        Assert.Contains("Invalid installation id", exception.Message);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public async Task GetLicenseAsync_CreatesAndReturns(SutProvider<CloudGetOrganizationLicenseQuery> sutProvider,
+        Organization organization, Guid installationId, Installation installation, SubscriptionInfo subInfo,
+        byte[] licenseSignature)
+    {
+        installation.Enabled = true;
+        sutProvider.GetDependency<IInstallationRepository>().GetByIdAsync(installationId).Returns(installation);
+        sutProvider.GetDependency<IPaymentService>().GetSubscriptionAsync(organization).Returns(subInfo);
+        sutProvider.GetDependency<ILicensingService>().SignLicense(Arg.Any<ILicense>()).Returns(licenseSignature);
+
+        var result = await sutProvider.Sut.GetLicenseAsync(organization, installationId);
+
+        Assert.Equal(LicenseType.Organization, result.LicenseType);
+        Assert.Equal(organization.Id, result.Id);
+        Assert.Equal(installationId, result.InstallationId);
+        Assert.Equal(licenseSignature, result.SignatureBytes);
+    }
+}
diff --git a/test/Core.Test/OrganizationFeatures/OrganizationLicenses/SelfHostedGetOrganizationLicenseQueryTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationLicenses/SelfHostedGetOrganizationLicenseQueryTests.cs
new file mode 100644
index 0000000000..df4a93305c
--- /dev/null
+++ b/test/Core.Test/OrganizationFeatures/OrganizationLicenses/SelfHostedGetOrganizationLicenseQueryTests.cs
@@ -0,0 +1,94 @@
+using System.Text.Json;
+using Bit.Core.Entities;
+using Bit.Core.Exceptions;
+using Bit.Core.Models.Business;
+using Bit.Core.Models.OrganizationConnectionConfigs;
+using Bit.Core.OrganizationFeatures.OrganizationLicenses;
+using Bit.Core.Settings;
+using Bit.Core.Test.AutoFixture;
+using Bit.Test.Common.AutoFixture;
+using Bit.Test.Common.AutoFixture.Attributes;
+using Bit.Test.Common.Helpers;
+using Xunit;
+
+namespace Bit.Core.Test.OrganizationFeatures.OrganizationLicenses;
+
+[SutProviderCustomize]
+public class SelfHostedGetOrganizationLicenseQueryTests
+{
+    private static SutProvider<SelfHostedGetOrganizationLicenseQuery> GetSutProvider(BillingSyncConfig config,
+        string apiResponse = null)
+    {
+        return new SutProvider<SelfHostedGetOrganizationLicenseQuery>()
+            .ConfigureBaseIdentityClientService($"licenses/organization/{config.CloudOrganizationId}",
+                HttpMethod.Get, apiResponse: apiResponse);
+    }
+
+    [Theory]
+    [BitAutoData]
+    [OrganizationLicenseCustomize]
+    public async void GetLicenseAsync_Success(Organization organization,
+        OrganizationConnection<BillingSyncConfig> billingSyncConnection, BillingSyncConfig config, OrganizationLicense license)
+    {
+        var sutProvider = GetSutProvider(config, JsonSerializer.Serialize(license));
+        billingSyncConnection.Enabled = true;
+        billingSyncConnection.Config = config;
+
+        var result = await sutProvider.Sut.GetLicenseAsync(organization, billingSyncConnection);
+        AssertHelper.AssertPropertyEqual(result, license);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public async void GetLicenseAsync_WhenNotSelfHosted_Throws(Organization organization,
+        OrganizationConnection billingSyncConnection, BillingSyncConfig config)
+    {
+        var sutProvider = GetSutProvider(config);
+        sutProvider.GetDependency<IGlobalSettings>().SelfHosted = false;
+
+        var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
+            sutProvider.Sut.GetLicenseAsync(organization, billingSyncConnection));
+        Assert.Contains("only available for self-hosted", exception.Message);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public async void GetLicenseAsync_WhenCloudCommunicationDisabled_Throws(Organization organization,
+        OrganizationConnection billingSyncConnection, BillingSyncConfig config)
+    {
+        var sutProvider = GetSutProvider(config);
+        sutProvider.GetDependency<IGlobalSettings>().EnableCloudCommunication = false;
+
+        var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
+            sutProvider.Sut.GetLicenseAsync(organization, billingSyncConnection));
+        Assert.Contains("Cloud communication is disabled", exception.Message);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public async void GetLicenseAsync_WhenCantUseConnection_Throws(Organization organization,
+        OrganizationConnection<BillingSyncConfig> billingSyncConnection, BillingSyncConfig config)
+    {
+        var sutProvider = GetSutProvider(config);
+        billingSyncConnection.Enabled = false;
+
+        var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
+            sutProvider.Sut.GetLicenseAsync(organization, billingSyncConnection));
+        Assert.Contains("Connection disabled", exception.Message);
+    }
+
+    [Theory]
+    [BitAutoData]
+    public async void GetLicenseAsync_WhenNullResponse_Throws(Organization organization,
+        OrganizationConnection<BillingSyncConfig> billingSyncConnection, BillingSyncConfig config)
+    {
+        var sutProvider = GetSutProvider(config);
+        billingSyncConnection.Enabled = true;
+        billingSyncConnection.Config = config;
+
+        var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
+            sutProvider.Sut.GetLicenseAsync(organization, billingSyncConnection));
+        Assert.Contains("An error has occurred. Check your internet connection and ensure the billing token is correct.",
+            exception.Message);
+    }
+}
diff --git a/test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommandTests.cs b/test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommandTests.cs
index 5ec93a976b..1cfe38bf1d 100644
--- a/test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommandTests.cs
+++ b/test/Core.Test/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommandTests.cs
@@ -1,5 +1,4 @@
 using System.Text.Json;
-using AutoFixture;
 using Bit.Core.Entities;
 using Bit.Core.Exceptions;
 using Bit.Core.Models.Api.Response.OrganizationSponsorships;
@@ -12,55 +11,22 @@ using Bit.Core.Test.AutoFixture.OrganizationSponsorshipFixtures;
 using Bit.Test.Common.AutoFixture;
 using Bit.Test.Common.AutoFixture.Attributes;
 using NSubstitute;
-using RichardSzalay.MockHttp;
 using Xunit;
 
 namespace Bit.Core.Test.OrganizationFeatures.OrganizationSponsorships.FamiliesForEnterprise.SelfHosted;
 
 public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTestsBase
 {
-
-    public static SutProvider<SelfHostedSyncSponsorshipsCommand> GetSutProvider(bool enableCloudCommunication = true, string identityResponse = null, string apiResponse = null)
+    private static SutProvider<SelfHostedSyncSponsorshipsCommand> GetSutProvider(string apiResponse = null)
     {
-        var fixture = new Fixture().WithAutoNSubstitutionsAutoPopulatedProperties();
-        fixture.AddMockHttp();
-
-        var settings = fixture.Create<IGlobalSettings>();
-        settings.SelfHosted = true;
-        settings.EnableCloudCommunication = enableCloudCommunication;
-
-        var apiUri = fixture.Create<Uri>();
-        var identityUri = fixture.Create<Uri>();
-        settings.Installation.ApiUri.Returns(apiUri.ToString());
-        settings.Installation.IdentityUri.Returns(identityUri.ToString());
-
-        var apiHandler = new MockHttpMessageHandler();
-        var identityHandler = new MockHttpMessageHandler();
-        var syncUri = string.Concat(apiUri, "organization/sponsorship/sync");
-        var tokenUri = string.Concat(identityUri, "connect/token");
-
-        apiHandler.When(HttpMethod.Post, syncUri)
-            .Respond("application/json", apiResponse);
-        identityHandler.When(HttpMethod.Post, tokenUri)
-            .Respond("application/json", identityResponse ?? "{\"access_token\":\"string\",\"expires_in\":3600,\"token_type\":\"Bearer\",\"scope\":\"string\"}");
-
-
-        var apiHttp = apiHandler.ToHttpClient();
-        var identityHttp = identityHandler.ToHttpClient();
-
-        var mockHttpClientFactory = Substitute.For<IHttpClientFactory>();
-        mockHttpClientFactory.CreateClient(Arg.Is("client")).Returns(apiHttp);
-        mockHttpClientFactory.CreateClient(Arg.Is("identity")).Returns(identityHttp);
-
-        return new SutProvider<SelfHostedSyncSponsorshipsCommand>(fixture)
-            .SetDependency(settings)
-            .SetDependency(mockHttpClientFactory)
-            .Create();
+        return new SutProvider<SelfHostedSyncSponsorshipsCommand>()
+            .ConfigureBaseIdentityClientService("organization/sponsorship/sync",
+                HttpMethod.Post, apiResponse: apiResponse);
     }
 
     [Theory]
     [BitAutoData]
-    public async Task SyncOrganization_BillingSyncKeyDisabled_ThrowsBadRequest(
+    public async Task SyncOrganization_BillingSyncConnectionDisabled_ThrowsBadRequest(
         Guid cloudOrganizationId, OrganizationConnection billingSyncConnection)
     {
         var sutProvider = GetSutProvider();
@@ -73,7 +39,7 @@ public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTests
         var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
             sutProvider.Sut.SyncOrganization(billingSyncConnection.OrganizationId, cloudOrganizationId, billingSyncConnection));
 
-        Assert.Contains($"Billing Sync Key disabled", exception.Message);
+        Assert.Contains($"Connection disabled", exception.Message);
 
         await sutProvider.GetDependency<IOrganizationSponsorshipRepository>()
             .DidNotReceiveWithAnyArgs()
@@ -85,7 +51,7 @@ public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTests
 
     [Theory]
     [BitAutoData]
-    public async Task SyncOrganization_BillingSyncKeyEmpty_ThrowsBadRequest(
+    public async Task SyncOrganization_BillingSyncConfigEmpty_ThrowsBadRequest(
         Guid cloudOrganizationId, OrganizationConnection billingSyncConnection)
     {
         var sutProvider = GetSutProvider();
@@ -94,7 +60,7 @@ public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTests
         var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
             sutProvider.Sut.SyncOrganization(billingSyncConnection.OrganizationId, cloudOrganizationId, billingSyncConnection));
 
-        Assert.Contains($"No Billing Sync Key known", exception.Message);
+        Assert.Contains($"No saved Connection config", exception.Message);
 
         await sutProvider.GetDependency<IOrganizationSponsorshipRepository>()
             .DidNotReceiveWithAnyArgs()
@@ -109,7 +75,8 @@ public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTests
     public async Task SyncOrganization_CloudCommunicationDisabled_EarlyReturn(
         Guid cloudOrganizationId, OrganizationConnection billingSyncConnection)
     {
-        var sutProvider = GetSutProvider(false);
+        var sutProvider = GetSutProvider();
+        sutProvider.GetDependency<IGlobalSettings>().EnableCloudCommunication = false;
 
         var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
             sutProvider.Sut.SyncOrganization(billingSyncConnection.OrganizationId, cloudOrganizationId, billingSyncConnection));
@@ -136,7 +103,8 @@ public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTests
                 SponsorshipsBatch = sponsorships.Select(o => new OrganizationSponsorshipData(o))
             }));
 
-        var sutProvider = GetSutProvider(apiResponse: syncJsonResponse);
+        var sutProvider = GetSutProvider(syncJsonResponse);
+
         billingSyncConnection.SetConfig(new BillingSyncConfig
         {
             BillingSyncKey = "okslkcslkjf"
@@ -166,7 +134,7 @@ public class SelfHostedSyncSponsorshipsCommandTests : FamiliesForEnterpriseTests
                 SponsorshipsBatch = sponsorships.Select(o => new OrganizationSponsorshipData(o) { CloudSponsorshipRemoved = true })
             }));
 
-        var sutProvider = GetSutProvider(apiResponse: syncJsonResponse);
+        var sutProvider = GetSutProvider(syncJsonResponse);
         billingSyncConnection.SetConfig(new BillingSyncConfig
         {
             BillingSyncKey = "okslkcslkjf"