Totum.Flags 2.0.3

dotnet add package Totum.Flags --version 2.0.3
                    
NuGet\Install-Package Totum.Flags -Version 2.0.3
                    
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="Totum.Flags" Version="2.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Totum.Flags" Version="2.0.3" />
                    
Directory.Packages.props
<PackageReference Include="Totum.Flags" />
                    
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 Totum.Flags --version 2.0.3
                    
#r "nuget: Totum.Flags, 2.0.3"
                    
#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 Totum.Flags@2.0.3
                    
#: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=Totum.Flags&version=2.0.3
                    
Install as a Cake Addin
#tool nuget:?package=Totum.Flags&version=2.0.3
                    
Install as a Cake Tool

Totum.Flags

.NET client for Totum feature flags. Call InitAsync once at startup, then read flags synchronously from memory — with background refresh and safe fallbacks when the network is unavailable.

Targets .NET Standard 2.1 (.NET Framework 4.7.2+, .NET Core 3.0+, .NET 5+, Unity).

AI agents & developers: use AGENT.md — copy into your app repo (.cursor/rules, AGENTS.md) for correct flag integration. This README is the full reference.


Install

The SDK is split into four NuGet packages. Pick the row that matches your app:

Environment Packages
ASP.NET Core Totum.Flags.Extensions.DependencyInjection (includes core + System.Text.Json)
.NET (console, worker, etc.) Totum.Flags + Totum.Flags.SystemTextJson
Unity (Newtonsoft.Json 13.0.2) Totum.Flags + Totum.Flags.NewtonsoftJson
# ASP.NET Core
dotnet add package Totum.Flags.Extensions.DependencyInjection

# .NET (non-ASP.NET)
dotnet add package Totum.Flags
dotnet add package Totum.Flags.SystemTextJson

# Unity
dotnet add package Totum.Flags
dotnet add package Totum.Flags.NewtonsoftJson

Prerequisites — proxy URL and API key

Every app needs two values from your platform team (see SETUP-WORKER §8):

Value Example Sent as
Proxy URL https://flags.totumcloud.com FlagsClientOptions.ProxyUrl
API key totum-mobile-prod-key FlagsClientOptions.ApiKey → header X-Flags-Api-Key

The names FLAGS_PROXY_URL and FLAGS_API_KEY are conventions for server apps (env vars, appsettings.json). The SDK does not read those names itself — you pass the strings into FlagsClientOptions.

Do not put Cloudflare account tokens or Flagship credentials in app code. The proxy API key is an app-level gate (similar to a mobile app API key): it ships with the client, but it is not a Cloudflare account secret.

.NET / ASP.NET

Load from environment variables, appsettings.json, or your secrets store:

{
  "FLAGS_PROXY_URL": "https://flags.totumcloud.com",
  "FLAGS_API_KEY": "your-proxy-key"
}

Unity

Unity has no process.env or appsettings.json. Use a ScriptableObject or build-time config — not PlayerPrefs. Full guide: Unity configuration below.


Quick start

.NET (System.Text.Json)

using Totum.Flags;
using Totum.Flags.SystemTextJson;

var flags = FlagsClientFactory.Create(new FlagsClientOptions
{
    ProxyUrl = Environment.GetEnvironmentVariable("FLAGS_PROXY_URL")!,
    ApiKey = Environment.GetEnvironmentVariable("FLAGS_API_KEY")!,
});

await flags.InitAsync(new[]
{
    new FlagDeclaration("my-app-dark-mode", FlagType.Boolean, false),
    new FlagDeclaration("my-app-checkout-flow", FlagType.String, "v1"),
});

// Synchronous — no await on getters
var darkMode = flags.GetBoolean("my-app-dark-mode", false);
var checkout = flags.GetString("my-app-checkout-flow", "v1");

Unity (Newtonsoft.Json)

See the full Unity section for where ProxyUrl and ApiKey come from. Minimal usage:

using Totum.Flags;
using Totum.Flags.NewtonsoftJson;

var flags = FlagsClientFactory.Create(new FlagsClientOptions
{
    ProxyUrl = config.ProxyUrl,
    ApiKey = config.ApiKey,
});

await flags.InitAsync(declarations);
var enabled = flags.GetBoolean("video-uploader-metrics-enabled", false);

Unity

Where do ProxyUrl and ApiKey come from?

  1. Platform team provisions the Worker and adds your app to API_KEYS (SETUP-WORKER §8).
  2. They give you the proxy URL (e.g. https://flags.totumcloud.com) and an API key for your build (e.g. totum-mobile-prod-key).
  3. Your Unity project stores those two strings in app config and passes them to FlagsClientOptions at startup.

You do not read FLAGS_PROXY_URL / FLAGS_API_KEY from the environment in Unity. You do not use PlayerPrefs for URL or API key — PlayerPrefs is per-user, editable at runtime, and the wrong place for app configuration.

Use one config asset per environment. Swap the asset (or its values) for Dev, Staging, and Production builds.

1. Config assetAssets/Scripts/Flags/FlagsRuntimeConfig.cs:

using UnityEngine;

[CreateAssetMenu(fileName = "FlagsRuntimeConfig", menuName = "Totum/Flags Runtime Config")]
public sealed class FlagsRuntimeConfig : ScriptableObject
{
    [Tooltip("From platform team — e.g. https://flags.totumcloud.com")]
    public string ProxyUrl = "";

    [Tooltip("From platform team — one key from Worker API_KEYS")]
    public string ApiKey = "";
}

2. Create assets in the Editor

Asset Typical use
FlagsRuntimeConfig.dev.asset Local / Editor play mode
FlagsRuntimeConfig.staging.asset QA builds
FlagsRuntimeConfig.prod.asset Store builds — do not commit prod key to git; inject via CI

3. Bootstrap — wire config into the client once at startup:

using System.Collections.Generic;
using System.IO;
using Totum.Flags;
using Totum.Flags.NewtonsoftJson;
using UnityEngine;

public sealed class FlagsBootstrap : MonoBehaviour
{
    [SerializeField] private FlagsRuntimeConfig config = null!;

    private FlagsClient? _client;

    private async void Start()
    {
        _client = FlagsClientFactory.Create(new FlagsClientOptions
        {
            ProxyUrl = config.ProxyUrl,
            ApiKey = config.ApiKey,
            PersistFilePath = Path.Combine(Application.persistentDataPath, "flags_cache.json"),
        });

        await _client.InitAsync(new[]
        {
            new FlagDeclaration("video-uploader-metrics-enabled", FlagType.Boolean, false),
        });
    }

    private void OnDestroy() => _client?.Dispose();

    public bool IsMetricsEnabled() =>
        _client?.GetBoolean("video-uploader-metrics-enabled", false) ?? false;
}

4. Assign the right asset — drag FlagsRuntimeConfig.dev.asset onto the config field in the Inspector for local work. CI replaces or selects the prod asset before a release build.

Switching environments

Approach When to use
Different ScriptableObject assets Most teams — swap asset reference per build profile
#if DEVELOPMENT_BUILD / custom defines Pick asset or URL in code at compile time
CI injects values Prod key never in repo — pipeline writes FlagsRuntimeConfig.prod.asset or patches fields before build
Resources JSON Alternative to ScriptableObject if you prefer a TextAsset

What to use — and what to avoid

Storage Proxy URL / API key? Flag cache?
ScriptableObject (per env) Yes — recommended No
Resources / TextAsset JSON Yes No
Build pipeline / CI secrets Yes (prod) No
Application.persistentDataPath file No Yes — set PersistFilePath here
PlayerPrefs No No — use PersistFilePath instead
Hard-coded in C# Dev smoke tests only No

CI / release builds (sketch)

Your pipeline holds the prod API key as a secret. Before BuildPlayer, generate or patch the prod config:

# Example: write prod config (paths vary per project)
echo '{"ProxyUrl":"https://flags.totumcloud.com","ApiKey":"'"$FLAGS_API_KEY"'"}' \
  > Assets/StreamingAssets/flags-config.json

Or use Unity -executeMethod to assign fields on FlagsRuntimeConfig.prod.asset from environment variables your CI provides.

Troubleshooting (Unity)

Symptom Check
401 / flags always default ApiKey on config asset matches a key in Worker API_KEYS
Works in Editor, fails on device Device build uses prod/staging asset with correct URL (not localhost)
Stale flags after deploy Delete cache file under Application.persistentDataPath, or wait for TTL refresh
JsonCodec is required Install Totum.Flags.NewtonsoftJson and use FlagsClientFactory.Create

Flag keys

Use hyphen-separated prefixes per product:

  • totum-admin-dark-mode
  • video-uploader-metrics-enabled

Each flagKey must exist in the flag dashboard with the matching type.

Dashboard: Enabled is not the same as true

Control Meaning Typical reason
Enabled Flag is active DISABLED if off
Default variant Value when no rules match DEFAULT

Integration pattern

  1. One FlagsClient per app (singleton).
  2. await InitAsync(declarations[, context]) once — list every flag you read.
  3. GetBoolean / GetString / GetNumber / GetObject are synchronous.
  4. await RefreshAsync(context) after login or targeting changes.
  5. Dispose() when tearing down (stops background refresh).

Targeting context

await flags.InitAsync(declarations, EvaluationContext.From(new Dictionary<string, object>
{
    ["userId"] = "anonymous",
}));

await flags.RefreshAsync(EvaluationContext.From(new Dictionary<string, object>
{
    ["userId"] = user.Id,
    ["plan"] = user.Plan,
}));

Optional file persistence

.NET — any writable path:

PersistFilePath = Path.Combine(Path.GetTempPath(), "flags_cache.json"),

Unity — use Application.persistentDataPath (see Unity bootstrap example).

ASP.NET Core

Install Totum.Flags.Extensions.DependencyInjection and register in Program.cs:

using Totum.Flags;
using Totum.Flags.Extensions.DependencyInjection;

builder.Services.AddTotumFlags(
    builder.Configuration,
    new[]
    {
        new FlagDeclaration("my-app-dark-mode", FlagType.Boolean, false),
        new FlagDeclaration("my-app-checkout-flow", FlagType.String, "v1"),
    });

var app = builder.Build();
// InitAsync runs automatically via IHostedService — inject IFlagsClient in controllers/services

Custom TTL, cache path, or HttpClient:

builder.Services.AddTotumFlags(options =>
{
    options.ProxyUrl = builder.Configuration["FLAGS_PROXY_URL"]!;
    options.ApiKey = builder.Configuration["FLAGS_API_KEY"]!;
    options.Ttl = TimeSpan.FromMinutes(5);
}, declarations);

Advanced: custom JSON codec

If you need direct control, set JsonCodec on FlagsClientOptions and construct FlagsClient yourself:

var options = new FlagsClientOptions
{
    ProxyUrl = proxyUrl,
    ApiKey = apiKey,
    JsonCodec = SystemTextJsonCodec.Instance,
};
var flags = new FlagsClient(options);

Client options

Option Default Description
ProxyUrl required Flags API base URL
ApiKey required X-Flags-Api-Key header
JsonCodec required Set via adapter FlagsClientFactory or manually
Ttl 30 seconds Background refresh interval
PersistFilePath null Optional cache file path
HttpClient new instance Inject for DI / testing

Caching and failures

Fallback order:

  1. Fresh batch response
  2. In-memory cache
  3. Persisted file (if PersistFilePath set)
  4. defaultValue passed to getters

InitAsync and RefreshAsync do not throw on network errors. Diagnostics use System.Diagnostics.Trace with prefix [Totum.Flags].


Anti-patterns

Wrong Correct
Infrastructure credentials in the app Proxy URL + API key only (from platform team)
PlayerPrefs for URL or API key (Unity) ScriptableObject or build-time config per environment
Totum.Flags without a JSON adapter Add Totum.Flags.SystemTextJson or Totum.Flags.NewtonsoftJson
await flags.GetBoolean(...) flags.GetBoolean(...)
HTTP per flag per request InitAsync once; sync reads
Flag not in InitAsync list Declare every flag up front

AI agents

  • .NET: load proxy URL and API key from env / appsettings (FLAGS_PROXY_URL, FLAGS_API_KEY).
  • Unity: load from ScriptableObject or build config — not env vars, not PlayerPrefs.
  • List every flag in InitAsync before calling getters.
  • Do not bypass this client for routine flag reads.

License

Closed Source. Proprietary & Confidential. See package LICENSE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 was computed.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Totum.Flags:

Package Downloads
Totum.Flags.NewtonsoftJson

Newtonsoft.Json adapter for Totum.Flags (Unity-compatible).

Totum.Flags.SystemTextJson

System.Text.Json adapter for Totum.Flags.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.3 35 6/6/2026
2.0.2 27 6/6/2026
2.0.1 36 6/6/2026
2.0.0 40 6/6/2026