PHP SDK
UnpublishedPHP 8.1+, zero Composer dependencies (ext-json, ext-curl).
Not yet published
Initialize
The API key is the first constructor argument.
<?php
use Counters\CountersClient;
$client = new CountersClient(getenv('COUNTERS_API_KEY'));Count
add and subtract are buffered and coalesced per counter (flushed as one POST /batch); addNow/subtractNow write immediately and return an array. Amounts accept an int or a digit string.
$reg = $client->counter('registrations');
$reg->add(1); // buffered
$reg->add(5); // coalesced
$client->flush(); // one POST /batch
$c = $reg->addNow(1); // immediate; returns an array
echo $c['value']; // "42"Read
Read the current value, or a per-bucket time series. Series parameters are passed as an associative array.
$value = $reg->value()['value'];
$series = $reg->series([
'from' => '2026-01-01T00:00:00Z',
'to' => '2026-01-08T00:00:00Z',
'bucket' => '1d',
]);Manage
clear resets to zero (new epoch, history retained); delete tombstones the counter; list pages the counters in the organization.
$reg->clear();
$reg->delete();
$page = $client->list(null, 50); // cursor, limitLifecycle
PHP has no background flush timer. Buffered writes leave only at maxBatchSize, on flush()/close(), or in the destructor. In long-running workers, call flush() periodically.
$client->flush(); // send buffered writes before the request endsNo background flush
Errors
Bad keys or amounts throw CountersValidationException (an InvalidArgumentException). Failed requests throw CountersApiException (a RuntimeException) with a status and problem. These two do not share a Counters base class.
use Counters\CountersValidationException;
use Counters\CountersApiException;
try {
$reg->addNow(1);
} catch (CountersValidationException $e) {
throw $e; // bad input
} catch (CountersApiException $e) {
error_log($e->status . ' ' . $e->getMessage());
}