Kotlin SDK

Unpublished

Blocking; JDK 17+; zero dependencies.

Initialize

Build a client with the Builder (the constructor is private). CountersClient is Closeable — prefer use { }.

Example.kt
import dev.counters.sdk.CountersClient

val client = CountersClient.builder(System.getenv("COUNTERS_API_KEY")).build()

Count

add and subtract are buffered and coalesced per counter into one POST /batch; addNow/subtractNow are blocking and return the counter. Each is overloaded for Long, String, and BigInteger amounts. Calls are synchronous and thread-safe.

count
val reg = client.counter("registrations")

reg.add(1)         // buffered
reg.add(5)         // coalesced
client.flush()     // one POST /batch

val c = reg.addNow(1) // immediate
println(c.value)      // "42"

Read

Read the current value, or a per-bucket time series via a SeriesParams data class (OffsetDateTime from/to). Kotlin is the one SDK that rejects an unknown bucket client-side.

read
val value = reg.value().value

val series = reg.series(SeriesParams(
    from = OffsetDateTime.parse("2026-01-01T00:00:00Z"),
    to = OffsetDateTime.parse("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
reg.clear()
reg.delete()

val page = client.list(null, 50) // cursor, limit

Lifecycle

Buffered writes flush on a daemon thread that will not keep the JVM alive — so you must close() (or use { }) before exit, or buffered writes are lost.

lifecycle
client.close() // flush + stop the flusher thread

// or: CountersClient.builder(key).build().use { c -> /* ... */ }

Errors

Bad keys or amounts throw CountersValidationException. Failed requests throw CountersApiException (status, title, problem); network failures throw CountersTransportException. The base CountersException is sealed, so a when over it is exhaustive.

errors
try {
    reg.addNow(1)
} catch (e: CountersValidationException) {
    throw e                     // bad input
} catch (e: CountersApiException) {
    println(e.status)
    println(e.title)
}
Prefer raw HTTP? See the REST API reference. Create a key in your dashboard.