Swift SDK

Unpublished

Blocking + throws (not async/await); re-exports BigInt.

Initialize

Construct with your API key; the initializer throws. Almost every call is marked throws.

main.swift
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).

count
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.

read
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"
))

Manage

clear resets to zero (new epoch, history retained); delete tombstones the counter; list pages the counters in the organization.

manage
_ = 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.

lifecycle
try client.close() // flush + stop the timer

Errors

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.

errors
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)
    }
}
Prefer raw HTTP? See the REST API reference. Create a key in your dashboard.