Swift SDK
UnpublishedBlocking + throws (not async/await); re-exports BigInt.
Not yet published
Initialize
Construct with your API key; the initializer throws. Almost every call is marked throws.
import Counters
let client = try CountersClient(
apiKey: ProcessInfo.processInfo.environment["COUNTERS_API_KEY"]!
)Count
add and subtract are buffered and coalesced per counter into one POST /batch; addNow/subtractNow are blocking and return the counter. Amounts accept an Int, a decimal String, or a BigInt (re-exported by the module).
let reg = try client.counter("registrations")
try reg.add(1) // buffered
try reg.add(5) // coalesced
try client.flush() // one POST /batch
let c = try reg.addNow(1) // immediate
print(c.value) // "42"Read
Read the current value, or a per-bucket time series.
let value = try reg.value().value
let series = try reg.series(SeriesParams(
from: "2026-01-01T00:00:00Z",
to: "2026-01-08T00:00:00Z",
bucket: "1d"
))Timestamps are typed inconsistently
Manage
clear resets to zero (new epoch, history retained); delete tombstones the counter; list pages the counters in the organization.
_ = try reg.clear()
try reg.delete()
let page = try client.list(limit: 50)Lifecycle
Buffered writes flush on a background timer. A deallocated client does NOT flush — call close() (or flush()) before exit, or buffered writes are lost.
try client.close() // flush + stop the timerErrors
Errors are one enum: CountersError.validation for bad input, .api(status:title:problem:) for non-2xx, and .transport for network failures. Use .status and .isValidation to branch.
do {
_ = try reg.addNow(1)
} catch let error as CountersError {
switch error {
case .validation: throw error
case .api(let status, _, _): print(status)
case .transport(let message): print(message)
}
}