Dart SDK
UnpublishedAsync (Future-based); zero dependencies.
Not yet published
Initialize
Construct with your API key (the factory throws on an empty key). Construction is synchronous.
import 'dart:io';
import 'package:counters/counters.dart';
final client = CountersClient(
apiKey: Platform.environment['COUNTERS_API_KEY']!,
);Count
add and subtract are buffered (synchronous, fire-and-forget) and coalesced per counter into one POST /batch; addNow/subtractNow are async and return the counter. Amounts accept an int, a decimal String, or a BigInt.
final reg = client.counter('registrations');
reg.add(1); // buffered
reg.add(5); // coalesced
await client.flush(); // one POST /batch
final c = await reg.addNow(1); // immediate
print(c.value); // "42"Read
Read the current value, or a per-bucket time series. SeriesParams takes native DateTime values.
final value = (await reg.value()).value;
final series = await reg.series(SeriesParams(
from: DateTime.utc(2026, 1, 1),
to: DateTime.utc(2026, 1, 8),
bucket: '1d',
));Manage
clear resets to zero (new epoch, history retained); delete tombstones the counter; list pages the counters in the organization.
await reg.clear();
await reg.delete();
final page = await client.list(limit: 50);Lifecycle
Buffered writes flush on a background timer and at maxBatchSize. Always await close() before your program exits, or buffered writes are lost.
await client.close(); // flush + cancel the timerErrors
Bad keys or amounts throw CountersValidationException before any request. Failed requests throw CountersApiException (status, title, problem); network/retry exhaustion throws CountersTransportException. All extend CountersException.
try {
await reg.addNow(1);
} on CountersValidationException {
rethrow; // bad input
} on CountersApiException catch (e) {
print(e.status);
print(e.title);
}