Yllibed.TenantCloudClient.Cdp 3.0.19-dev

This is a prerelease version of Yllibed.TenantCloudClient.Cdp.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Yllibed.TenantCloudClient.Cdp --version 3.0.19-dev
                    
NuGet\Install-Package Yllibed.TenantCloudClient.Cdp -Version 3.0.19-dev
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Yllibed.TenantCloudClient.Cdp" Version="3.0.19-dev" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Yllibed.TenantCloudClient.Cdp" Version="3.0.19-dev" />
                    
Directory.Packages.props
<PackageReference Include="Yllibed.TenantCloudClient.Cdp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Yllibed.TenantCloudClient.Cdp --version 3.0.19-dev
                    
#r "nuget: Yllibed.TenantCloudClient.Cdp, 3.0.19-dev"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Yllibed.TenantCloudClient.Cdp@3.0.19-dev
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Yllibed.TenantCloudClient.Cdp&version=3.0.19-dev&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Yllibed.TenantCloudClient.Cdp&version=3.0.19-dev&prerelease
                    
Install as a Cake Tool

Yllibed.TenantCloudClient

Unofficial .NET client library for TenantCloud, a rental property management platform.

Build Status Nuget

This is not an official TenantCloud product. TenantCloud does not provide a public API; this library works against their internal endpoints.

Packages

Package Description
Yllibed.TenantCloudClient Core library: API client, token store abstractions, and OS-native secure storage
Yllibed.TenantCloudClient.Cdp Chrome DevTools Protocol token provider (extracts tokens from a running browser)

Both packages target net8.0 and net10.0 with no external runtime dependencies beyond System.Text.Json and Microsoft.Extensions.DependencyInjection.Abstractions.

Quick start

With dependency injection

services
    .AddSecureTokenStore()      // ITcTokenStore → OS credential store
    .AddCdpTokenProvider()      // ITcAuthTokenProvider → browser extraction + auto-refresh
    .AddTenantCloudClient();    // ITcClient → TcClient

Then inject ITcClient wherever you need it:

public class MyService(ITcClient tc)
{
    public async Task<TcUserInfo?> WhoAmI(CancellationToken ct)
        => await tc.GetUserInfo(ct);
}

Without dependency injection

var tokenStore = new SecureTokenStore();
var tokenProvider = new CdpTokenProvider(new CdpTokenProviderOptions
{
    TokenStore = tokenStore,
    AllowInteractiveLogin = true,
});

using var client = new TcClient(tokenProvider);
var user = await client.GetUserInfo(ct);

Authentication

TcClient requires an ITcAuthTokenProvider to supply Bearer tokens. The library does not store or manage credentials directly.

public interface ITcAuthTokenProvider
{
    Task<string?> GetToken(CancellationToken ct);
    Task OnTokenRejected(CancellationToken ct, string rejectedToken);
}

Built-in: CdpTokenProvider

Provided by the Yllibed.TenantCloudClient.Cdp package. Extracts auth tokens from a running Chromium browser via the Chrome DevTools Protocol, with automatic JWT refresh.

services.AddCdpTokenProvider(options =>
{
    options.DebugPort = 9222;               // CDP debug port (default)
    options.AllowInteractiveLogin = true;   // launch a browser if no session found
});

The provider follows a multi-step strategy:

  1. In-memory cache (if the JWT is still valid)
  2. Token store (load + refresh if expired)
  3. CDP extraction from an existing browser tab on app.tenantcloud.com
  4. Interactive login (if AllowInteractiveLogin is enabled) — launches a browser window and waits for the user to sign in

Custom provider

Implement ITcAuthTokenProvider and register it before calling AddTenantCloudClient():

services.AddSingleton<ITcAuthTokenProvider, MyCustomTokenProvider>();
services.AddTenantCloudClient();

Token persistence

ITcTokenStore allows tokens to survive across process restarts. Both the core library and the CDP provider can use it.

public interface ITcTokenStore
{
    Task<TcTokenSet?> LoadAsync(CancellationToken ct);
    Task SaveAsync(TcTokenSet tokens, CancellationToken ct);
}

Built-in stores

Store Package Description
SecureTokenStore Core OS-native credential storage: DPAPI (Windows), Keychain (macOS), Secret Service (Linux)
FileTokenStore Cdp Plain JSON file with atomic writes (useful for headless/CI scenarios)
// OS-native secure storage (recommended)
services.AddSecureTokenStore();

// With custom options
services.AddSecureTokenStore(options =>
{
    options.ServiceName = "MyApp";
    options.AccountKey = "production";
});

// Or file-based (from the Cdp package, register manually)
services.AddSingleton<ITcTokenStore>(new FileTokenStore("/path/to/tokens.json"));

Custom store

Implement ITcTokenStore to persist tokens wherever you need (database, Azure Key Vault, etc.):

services.AddSingleton<ITcTokenStore, MyDatabaseTokenStore>();

API reference

ITcClient

Member Type Description
GetUserInfo(ct) Task<TcUserInfo?> Current signed-in user info
Contacts IPaginatedSource<TcContact> Contacts (tenants, professionals)
Properties IPaginatedSource<TcProperty> Properties
Units IPaginatedSource<TcUnit> Rental units
Transactions IPaginatedSource<TcTransaction> Financial transactions
Leases IPaginatedSource<TcLease> Leases

Paginated sources

Each collection is an IPaginatedSource<T>. Call .GetAll(ct) to fetch all pages, or .GetAll(ct, maxResults: n) to cap the fetch:

var contacts = await client.Contacts.OnlyMovedIn().GetAll(ct);

The result is a ReadOnlySequence<T> (one segment per API page). Use .AsEnumerable() to bridge to LINQ:

var names = (await client.Contacts.GetAll(ct))
    .AsEnumerable()
    .Select(c => c.Name)
    .ToArray();

Filters

Filters are chainable extension methods that narrow the API query before fetching.

Contacts

  • .OnlyTenants() — tenant contacts only
  • .OnlyMovedIn() — tenants with active leases
  • .OnlyProfessionals() — professional contacts only
  • .OnlyArchived() — archived contacts

Leases

  • .OnlyActive() — active leases
  • .ForProperty(propertyId) — filter by property
  • .ForUnit(unitId) — filter by unit

Units

  • .OnlyOccuped() — units with active leases
  • .OnlyVacant() — vacant units
  • .ForProperty(propertyId) — filter by property

Transactions

  • .ForTenant(tenantId) — filter by tenant
  • .ForProperty(propertyId) — filter by property
  • .ForUnit(unitId) — filter by unit
  • .ForStatus(TcTransactionStatus) — filter by status (Due, Paid, Partial, Pending, Void, WithBalance, Overdue, Waive)
  • .ForCategory(TcTransactionCategory) — filter by category (Income, Expense, Refund, Credits, Liability)
  • .SortByDateDescending() — reverse chronological order

Example: overdue income per property

var balancePerProperty = (await client.Transactions
        .ForCategory(TcTransactionCategory.Income)
        .ForStatus(TcTransactionStatus.WithBalance)
        .GetAll(ct))
    .AsEnumerable()
    .Where(t => t.PropertyId != null)
    .GroupBy(t => (long)t.PropertyId!, t => t.Balance)
    .Select(g => new { PropertyId = g.Key, Balance = g.Sum() })
    .ToArray();

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.41-dev 47 2/16/2026
3.0.40-dev 45 2/16/2026
3.0.39-dev 51 2/16/2026
3.0.20-dev 47 2/16/2026
3.0.19-dev 54 2/16/2026
3.0.18-dev 44 2/16/2026