C# SDK

Unpublished

Fully async, .NET 8+, zero dependencies, arbitrary precision via BigInteger.

Initialize

Construct with an options object. CountersClient is IAsyncDisposable — prefer await using.

Program.cs
using Counters.Sdk;

await using var client = new CountersClient(new CountersClientOptions
{
    ApiKey = Environment.GetEnvironmentVariable("COUNTERS_API_KEY")!,
});

Count

Add and Subtract are buffered and coalesced per counter (flushed as one POST /batch); AddNowAsync/SubtractNowAsync write immediately and return the counter. Each is overloaded for long, string, and BigInteger amounts.

count
var reg = client.Counter("registrations");

reg.Add(1);                 // buffered
reg.Add(5);                 // coalesced
await client.FlushAsync();  // one POST /batch

Counter c = await reg.AddNowAsync(1); // immediate
Console.WriteLine(c.Value);           // "42"

Read

Read the current value, or a per-bucket time series. Every network call is async and accepts an optional CancellationToken.

read
var value = (await reg.ValueAsync()).Value;

var series = await reg.SeriesAsync(new SeriesParams
{
    From = DateTimeOffset.Parse("2026-01-01T00:00:00Z"),
    To = DateTimeOffset.Parse("2026-01-08T00:00:00Z"),
    Bucket = "1d",
});

Manage

ClearAsync resets to zero (new epoch, history retained); DeleteAsync tombstones the counter; ListAsync pages the counters in the organization.

manage
await reg.ClearAsync();
await reg.DeleteAsync();

var page = await client.ListAsync(limit: 50);

Lifecycle

Buffered writes flush on a background timer and at maxBatchSize. await using disposes the client (flush + stop); or call CloseAsync yourself.

lifecycle
await client.CloseAsync(); // flush + stop the background timer

Errors

Bad keys or amounts throw CountersValidationException before any request. Failed requests throw CountersApiException (Status, Title, Problem); both extend CountersException.

errors
try
{
    await reg.AddNowAsync(1);
}
catch (CountersValidationException)
{
    throw; // bad input
}
catch (CountersApiException e)
{
    Console.Error.WriteLine($"{e.Status} {e.Title}");
}
Prefer raw HTTP? See the REST API reference. Create a key in your dashboard.