C#
The official Schematic C# library, supporting .NET Standard, .NET Core, and .NET Framework.
Installation and Setup
- Install the library using the .NET Core command-line interface (CLI) tools:
or using the NuGet Command Line Interface (CLI):
-
Issue an API key for the appropriate environment using the Schematic app.
-
Using this secret key, initialize a client in your application:
Usage
A number of these examples use keys to identify companies and users. Learn more about keys here.
Sending identify events
Create or update users and companies using identify events.
This call is non-blocking and there is no response to check.
Sending track events
Track activity in your application using track events; these events can later be used to produce metrics for targeting.
This call is non-blocking and there is no response to check.
If you want to record large numbers of the same event at once, or perhaps measure usage in terms of a unit like tokens or memory, you can optionally specify a quantity for your event:
Creating and updating companies
Although it is faster to create companies and users via identify events, if you need to handle a response, you can use the companies API to upsert companies. Because you use your own identifiers to identify companies, rather than a Schematic company ID, creating and updating companies are both done via the same upsert operation:
You can define any number of company keys; these are used to address the company in the future, for example by updating the company’s traits or checking a flag for the company.
You can also define any number of company traits; these can then be used as targeting parameters.
Creating and updating users
Similarly, you can upsert users using the Schematic API, as an alternative to using identify events. Because you use your own identifiers to identify users, rather than a Schematic user ID, creating and updating users are both done via the same upsert operation:
You can define any number of user keys; these are used to address the user in the future, for example by updating the user’s traits or checking a flag for the user.
You can also define any number of user traits; these can then be used as targeting parameters.
Checking flags
When checking a flag, you’ll provide keys for a company and/or keys for a user. You can also provide no keys at all, in which case you’ll get the default value for the flag.
Checking flags with entitlement details
If you need more detail about how a flag check was resolved, including any entitlement associated with the check, use CheckFlagWithEntitlement. This returns a response object with the flag value, the reason for the evaluation result, and entitlement details such as usage, allocation, and credit balances when applicable.
Checking multiple flags
The CheckFlags method allows you to efficiently check multiple feature flags in a single operation. When you provide specific flag keys, it will only return the flag values for those flags, leveraging intelligent caching to minimize API calls.
OpenFeature Integration
The Schematic .NET SDK includes built-in support for OpenFeature, allowing you to use Schematic’s feature flags through the OpenFeature standard API.
Using Schematic with OpenFeature
OpenFeature Context
The Schematic provider supports company and user context through OpenFeature’s evaluation context:
Event Tracking with OpenFeature
The provider includes a method to track events:
Credit Leases and Reservations
For features metered by credit burndown (for example inference tokens), Check reserves credits for the work about to run and TrackWithReservation settles the reservation with actual usage. The SDK gates in one of two modes:
- Client mode acquires a lease, a tranche of credits held against the company’s balance, and carves a per-request reservation out of it locally, so a check needs no API call. It requires Datastream (or Replicator Mode) and, across multiple processes, a shared Redis so every instance gates against the same lease.
- Server mode makes one
check-and-reserveAPI call per check. No lease, no Redis, no local state.
CreditLeases.Mode defaults to Auto: client when the datastream is running, server otherwise. A datastream that fails to start counts as server, since there is no local engine behind the gate. Client mode suits high-throughput gating; server mode suits low-volume checks and operations that run for seconds.
Setup
The Redis the cache is configured with also backs lease and reservation state. Set CreditLeases.RedisConfig (or CreditLeases.RedisClient, for a connection you own) to keep lease state in a different Redis.
Server mode needs only a TTL:
Only Mode and DefaultReservationTTL apply in server mode; the SDK warns at startup if a client-only option is set.
Checking and tracking
Usage may be fractional, but a fraction of an event is not something the server bills, so everything that moves credits rounds up to whole units. A client-mode reservation holds ceil(Usage) times the consumption rate, and a settle debits ceil of the actual quantity, so the local ledger moves by exactly what the track event charges. The preflight quantity and the quantity a track event bills round the same way. A check for 2.5 units at a rate of 10 holds 30 credits and bills 3 units, while the reservation still records the Usage the caller declared.
A check can allow without reserving credits (the feature is not credit-metered, Usage is 0, or the check failed open), and that usage still has to be tracked.
An unsettled reservation expires after DefaultReservationTTL and its credits return to the lease. A late settle still bills the usage (the track event carries a deterministic idempotency key, so it never double-bills) but does not re-debit the local lease, so set DefaultReservationTTL above the longest expected gap between Check and TrackWithReservation.
Pre-warming
Pre-warm leases when the user is identified, so a session’s first check does not wait on a lease acquire:
Or call schematic.Prewarm(company, creditTypeIds) directly. Both are no-ops in server mode.
Pre-warming resolves the company the way the server does: it looks the keys up first, whatever they are named, and only when nothing matches does it read a value carrying Schematic’s comp_ prefix as the company id.
An Identify that carries Prewarm flushes the event buffer so the company exists before the lease acquire asks for it, which makes it a call to place once at the start of a session rather than on every event.
Failure behavior
A check that cannot be gated (API unreachable, Redis down, lease exhausted) fails closed by default. Override per check:
In client mode, FailOpen still evaluates the flag’s rules with the credit balance assumed sufficient, so plan targeting and all non-credit conditions apply and only the credit gate is bypassed. In server mode it returns the flag’s default value, which is false unless you pass CheckOptions.DefaultValue or configure a FlagDefaults entry.
In server mode, a check that times out after the server has already reserved leaves those credits reserved until the TTL expires, so keep DefaultReservationTTL short there.
See Credit Lease Options for the full set of knobs.
Webhook Verification
Schematic can send webhooks to notify your application of events. To ensure the security of these webhooks, Schematic signs each request using HMAC-SHA256. The .NET SDK provides utility functions to verify these signatures.
Verifying Webhook Signatures
When your application receives a webhook request from Schematic, you should verify its signature to ensure it’s authentic:
Verifying Signatures Manually
If you need to verify a webhook signature outside of the context of an HTTP request, you can use the VerifySignature method:
Configuration Options
There are a number of configuration options that can be specified by passing ClientOptions as a second parameter when instantiating the Schematic client.
Cache Options
The recommended way to configure caching is through the fluent helpers on ClientOptions or by setting ClientOptions.CacheConfiguration directly.
By default an in-memory cache will be configured, but you can customize it further if required:
If you prefer to configure it explicitly, you can set CacheConfiguration yourself:
You can also disable local caching entirely; bear in mind that, in this case, every flag check will result in a network request:
Redis Cache Configuration
For distributed applications or when you want cache persistence across application restarts, use Redis:
If you need more control over the connection, supply a ConfigurationOptions instance or a ConnectionMultiplexerFactory:
Custom Cache Implementation
If you want to provide your own cache backend, implement ICacheProvider and assign it to ClientOptions.CacheProvider:
Custom caches are useful if you need specialized eviction, a different backing store, or additional observability around cache access.
Default Flags
You may want to specify default flag values for your application, which will be used if there is a service interruption or if the client is running in offline mode (see below):
Offline Mode
In development or testing environments, you may want to avoid making network requests to the Schematic API. You can run Schematic in offline mode by specifying the Offline option; in this case, it does not matter what API key you specify:
Offline mode works well with flag defaults:
You can also set flag defaults dynamically after the client has been constructed using SetFlagDefault and SetFlagDefaults. This is useful in automated testing contexts, where you may want to specify per-test flag values:
Event Buffer
Schematic API uses an Event Buffer to batch Identify and Track requests and avoid multiple API calls. You can set the event buffer flush period in options:
You may also want to use your custom event buffer. To do so, your custom event buffer has to implement IEventBuffer interface, and pass an instance to the Schematic API through options:
HTTP Client
You can override the HttpClient:
Retries
429 Rate Limit, and >=500 Internal errors will all be retried twice with exponential backoff. You can override this behavior globally or per-request.
Timeouts
The SDK defaults to a 60s timeout. You can override this behaviour globally or per-request.
Credit Lease Options
ClientOptions.CreditLeases enables credit reservation behavior on Check and TrackWithReservation. Omit it to keep the client credit-unaware. See Credit Leases and Reservations for the flow these knobs steer.
Without a Redis backend the SDK keeps lease and reservation state per process, which loses cross-pod gating, and warns at startup.
Exception Handling
When the API returns a non-zero status code, (4xx or 5xx response), a subclass of SchematicException will be thrown:
Datastream
Datastream is Schematic’s real-time connection service that optimizes flag check performance and reliability. When enabled, the Schematic client maintains a WebSocket connection to our servers, which pushes down feature flag definitions, company data, and user data as needed.
Benefits of Datastream
- Improved Performance: Flag checks become near-instantaneous after the initial data load
- Reduced API Load: Minimizes HTTP requests to the Schematic API
- Real-time Updates: Flag changes are immediately pushed to your application
- Fault Tolerance: Falls back to standard API requests when needed
Enabling Datastream
Important: Datastream is disabled by default. You must explicitly enable it in your client options:
Customizing Datastream
You can customize Datastream’s behavior through additional client options:
DatastreamOptions currently controls Datastream-specific TTL behavior; the cache provider itself still comes from ClientOptions.CacheConfiguration (or CacheProvider for custom implementations).
Checking Flags with Datastream
The flag checking experience remains the same whether Datastream is enabled or not:
The difference is that with Datastream enabled, after the initial data load, subsequent flag checks for the same company and user will be nearly instantaneous and won’t require additional network requests.
Replicator Mode
Replicator mode is an advanced Datastream configuration that maintains a local replica of your Schematic data using a persistent cache layer. This mode provides enhanced performance and reliability for high-throughput applications.
Enabling Replicator Mode
In replicator mode the client polls the replicator’s health endpoint every 30 seconds to learn whether it is ready and which cache version to read. If you don’t set a health URL, it uses http://localhost:8090/ready, the same default as the other Schematic SDKs. This applies whether you call .WithReplicatorMode() or set ReplicatorMode = true directly and leave ReplicatorHealthUrl unset (null, empty or whitespace). To point at a replicator elsewhere, pass its URL, .WithReplicatorMode("http://my-replicator:8090/ready"), or set ReplicatorHealthUrl. An explicit URL always takes precedence. Passing an empty or whitespace string to .WithReplicatorMode(url) throws an ArgumentException; call the overload with no arguments to use the default.