SegOps AIDocs

Kotlin SDK

JVM and Android-compatible Kotlin client. Uses Kotlin coroutines for async flushing, OkHttp for HTTP transport, and implements Closeable for graceful shutdown. Requires JVM 17+ or Android API 26+.

Installation (Gradle)#

Add the dependency to your build.gradle.kts:

kotlin
dependencies {
    implementation("io.github.segops:segops-kotlin:0.1.0")
}

For Groovy DSL (build.gradle):

groovy
dependencies {
    implementation 'io.github.segops:segops-kotlin:0.1.0'
}

Quick Start#

kotlin
import io.github.segops.SegOpsClient
import io.github.segops.SegOpsContext
import io.github.segops.SegOpsEvent
import io.github.segops.SegOpsOptions

val segops = SegOpsClient(SegOpsOptions(
    apiUrl = "https://api.segops.ai",
    apiKey = "sk_..."
))

// Track an event (non-blocking)
segops.track(SegOpsEvent(
    userId = "user-123",
    eventType = "order_placed",
    payload = mapOf(
        "order_id" to "ord-456",
        "total" to 89.95
    )
))

// Identify a user
segops.identify(SegOpsContext(
    userId = "user-123",
    traits = mapOf(
        "email" to "[email protected]",
        "plan" to "starter"
    )
))

// Shut down (flush + cancel coroutines)
segops.close()

Android Usage#

On Android, initialize the client in your Application class:

kotlin
class MyApplication : Application() {
    lateinit var segops: SegOpsClient

    override fun onCreate() {
        super.onCreate()
        segops = SegOpsClient(
            SegOpsOptions(
                apiUrl = "https://api.segops.ai",
                apiKey = BuildConfig.SEGOPS_API_KEY
            )
        )
    }

    override fun onTerminate() {
        super.onTerminate()
        // Best-effort flush on process termination
        segops.close()
    }
}

Public keys (recommended for mobile apps)#

A secret key (sk_…) must never ship inside an APK — anyone can extract it. Use a public key (pk_…) instead, which is safe to embed. When the apiKey starts with pk_, the SDK runs the session handshake: it exchanges the key for a short-lived JWT via POST /api/auth/session/, caches it, and re-mints on expiry/401 — all transparently (concurrent calls share one mint via a coroutine Mutex).

To bind events to a logged-in user, sign the user_id on your backend (HMAC-SHA256 over "$userId|$unixSeconds"with the key's HMAC secret) and return it from userProvider:

kotlin
val client = SegOpsClient(SegOpsOptions(
    apiUrl = "https://api.segops.ai",
    apiKey = "pk_...",
    userProvider = {
        SegOpsUserContext(
            userId = currentUser.id,
            userIdSig = signed.sig,   // from your backend
            userIdTs = signed.ts
        )
    }
))

For anonymous visitors, omit userProvider (or return SegOpsUserContext(anonymousId = ...)).

Tip
Enable "require signed user_id" on the public key so the server rejects unsigned or forged identities. Keys used by mobile apps should have an empty origin allowlist (mobile clients send no Origin header).

Constructor Options#

FieldTypeRequiredDescription
apiUrlStringYesBase URL of your SegOps deployment
apiKeyStringYesPublic key (pk_…, recommended for apps) or secret key (sk_…, server-side only)
userProvider() -> SegOpsUserContextNoRequired with a pk_ key: returns the current user at mint time. Defaults to anonymous.
batchSizeIntNoMax events before auto-flush. Default: 20
flushEveryMsLongNoPeriodic flush interval in milliseconds. Default: 5000
maxRetriesIntNoRetry attempts on 5xx. Default: 3
onError(Throwable) -> UnitNoCalled when all retries are exhausted. Defaults to System.err.

Methods#

track(event: SegOpsEvent)

Enqueue a user event. Non-blocking, thread-safe.

kotlin
segops.track(SegOpsEvent(
    userId = "user-123",
    eventType = "page_viewed",
    // occurredAt defaults to Instant.now() when null
    payload = mapOf("screen" to "Pricing")
))

identify(ctx: SegOpsContext)

Record user traits as a context_identified event.

kotlin
segops.identify(SegOpsContext(
    userId = "user-123",
    traits = mapOf("email" to "[email protected]", "plan" to "starter")
))

suspend fun flush()

Flush all buffered events immediately. Suspends until complete — call from a coroutine.

kotlin
coroutineScope {
    launch { segops.flush() }
}

close()

Flush synchronously and shut down the background coroutine. SegOpsClient implements Closeable, so you can use it in a use {} block or call close()in your app's lifecycle teardown.

kotlin
// Application shutdown (Spring Boot, etc.)
Runtime.getRuntime().addShutdownHook(Thread { segops.close() })

// Or with use:
SegOpsClient(options).use { client ->
    client.track(SegOpsEvent(userId = "user-123", eventType = "page_viewed"))
}

Error Handling#

Transient 5xx errors are retried automatically with back-off (500 ms × attempt). If all retries are exhausted, the batch is dropped and the error is passed to your onError handler, which defaults to printing to System.err.

Types#

kotlin
data class SegOpsEvent(
    val userId: String,
    val eventType: String,
    val occurredAt: Instant? = null,   // defaults to Instant.now()
    val payload: Map<String, Any?> = emptyMap(),
)

data class SegOpsContext(
    val userId: String,
    val traits: Map<String, Any?>,
)

// Supplied to userProvider when authenticating with a pk_ key.
data class SegOpsUserContext(
    val userId: String? = null,        // omit for anonymous visitors
    val anonymousId: String? = null,
    val userIdSig: String? = null,     // hex HMAC signature from your backend
    val userIdTs: Long? = null,        // unix-seconds paired with userIdSig
)