Kotlin SDK
Connect Kotlin and JVM applications to SikkerKey, authenticate with a machine identity, and read, export, cache, or monitor secrets.
The SikkerKey Kotlin SDK connects Kotlin and JVM applications to your vault. Your application authenticates with its own machine identity, then reads only the secrets and projects that identity is permitted to access.
The SDK uses synchronous calls. In applications with a main or UI thread, run secret operations in an I/O or worker context.
#Requirements
Java 17 or later
A SikkerKey vault
A machine identity with access to the secrets your application needs
#Install the SDK
Add the SDK from Maven Central.
Gradle Kotlin DSL
dependencies {
implementation("io.github.sikkerkeyofficial:sikkerkey-sdk:1.3.0")
}Maven
<dependency>
<groupId>io.github.sikkerkeyofficial</groupId>
<artifactId>sikkerkey-sdk</artifactId>
<version>1.3.0</version>
</dependency>#Connect with a machine identity
A machine identity gives your application a distinct identity and determines which secrets it can read. Use a standard machine for persistent servers and workstations, or an ephemeral machine for short-lived workloads.
Use a standard machine
After provisioning the machine with the SikkerKey CLI, create a client with its vault ID:
import com.sikker.key.sdk.SikkerKey
SikkerKey("vault_abc123").use { sikkerKey ->
val apiKey = sikkerKey.getSecret("secret_abc123")
}You can also provide the path to an identity file directly:
val sikkerKey = SikkerKey("/etc/sikkerkey/identity.json")When you call SikkerKey() without an argument, the SDK first checks SIKKERKEY_IDENTITY. If that variable is not set, it can automatically select the identity when exactly one vault is configured on the machine.
Use an ephemeral machine
For serverless functions, CI jobs, containers, and other short-lived workloads, register an ephemeral machine in memory with an enrollment token:
val sikkerKey = SikkerKey.bootstrapInMemory(
vaultId = "vault_...",
token = System.getenv("SIKKERKEY_ENROLLMENT_TOKEN"),
hostname = "checkout-worker",
name = "Checkout worker"
)
sikkerKey.use {
val apiKey = it.getSecret("secret_abc123")
}The SDK creates the signing key in memory and does not write an identity file to disk. The machine follows the lifetime and access configured on the enrollment token. When the process exits, its in-memory private key is gone.
Keep enrollment tokens outside source code and pass them to the workload through its protected runtime configuration.
#Read secrets
Read a standard secret
val databasePassword = sikkerKey.getSecret("sk...")The returned string is the current secret value.
Read a structured secret
Retrieve every field as a map:
val database = sikkerKey.getFields("sk...")
val username = database["username"]
val password = database["password"]When you need one field, request it directly:
val password = sikkerKey.getField("sk...", "password")Structured fields are returned as strings. If a field name is unavailable, the SDK raises FieldNotFoundException and includes the available field names.
#Find secrets available to the machine
List every secret the current machine can access:
val secrets = sikkerKey.listSecrets()
secrets.forEach { secret ->
println("${secret.name}: ${secret.id}")
}Limit the result to a project when your application works with a specific environment or service:
val productionSecrets = sikkerKey.listSecretsByProject("proj_...")Each result includes the secret ID and name, and can also include its project and structured field names.
#Export secrets for application configuration
Use export() to retrieve accessible secrets as environment-style key and value pairs in one request:
val configuration = sikkerKey.export("proj_...""")
configuration.forEach { (name, value) ->
println(name)
// Pass value to your application's configuration layer.
}Names are converted to uppercase environment-variable format. Spaces and punctuation become underscores. Structured secrets are flattened by combining the secret name and field name, such as DATABASE_PASSWORD.
Avoid logging exported values. The example prints names only.
#Enable encrypted fallback
Encrypted fallback lets a persistent application continue using a previously retrieved value during a temporary network or service interruption. It is disabled until you enable it.
val sikkerKey = SikkerKey("vault_...")
.enableCache(maxAge = 3600) { secretId, cachedAt ->
logger.warn("Using cached value for {} from {}", secretId, cachedAt)
}Successful reads are encrypted locally with a key derived from the machine identity. maxAge is measured in seconds; omit it when cached values should not expire. The callback runs only when the SDK uses the cached value, so you can record or monitor fallback events without handling the secret itself.
Fallback is limited to connection failures and temporary gateway or service availability responses. Authoritative responses—including denied access, missing secrets, rate limits, and application errors—are returned to your application and do not use an older value.
The cache is stored with the machine identity under the SikkerKey home directory and is compatible with SikkerKey CLI cache files. It is most useful for persistent hosts; an in-memory ephemeral identity cannot recover the cache key after the process exits.
#Monitor a secret for changes
Use watch() when a long-running application should react after a secret changes:
import com.sikker.key.sdk.WatchStatus
sikkerKey.setPollInterval(30)
sikkerKey.watch("sk_...") { event ->
when (event.status) {
WatchStatus.CHANGED -> reloadClient(event.value)
WatchStatus.DELETED -> logger.warn("Secret was deleted")
WatchStatus.ACCESS_DENIED -> logger.warn("Secret access was removed")
WatchStatus.ERROR -> logger.error("Secret check failed", event.error)
}
}The SDK checks watched secrets in the background. The default interval is 15 seconds, and the minimum configurable interval is 10 seconds. A change event includes the latest value and, for structured secrets, the latest fields.
Callbacks run on the watcher's background thread. Hand off slow work to your application's own executor or coroutine scope. Deleted secrets and secrets the machine can no longer access are automatically removed from the watch list.
Stop one watcher or close the client when the application no longer needs it:
sikkerKey.unwatch("sk_...")
sikkerKey.close()#Work with multiple vaults
List the vault identities configured on the host:
val vaults = SikkerKey.listVaults()
vaults.forEach { vault ->
println("${vault.name}: ${vault.id}")
}Create a separate client for each vault your application uses. The active client's machineId, machineName, vaultId, and apiUrl properties are available when you need to identify the connection in application diagnostics.
#Handle errors
All SDK errors extend SikkerKeyException. Catch a specific exception when your application can respond to that condition:
import com.sikker.key.sdk.AccessDeniedException
import com.sikker.key.sdk.NotFoundException
import com.sikker.key.sdk.RateLimitedException
try {
val value = sikkerKey.getSecret("secret_abc123")
} catch (error: NotFoundException) {
// The secret does not exist or is no longer available.
} catch (error: AccessDeniedException) {
// The machine does not have access to this secret.
} catch (error: RateLimitedException) {
// Retry later or reduce the request rate.
}The SDK provides dedicated exceptions for configuration problems, invalid structured data, missing fields, authentication failures, denied access, missing resources, conflicts, rate limits, and temporary service availability.
Requests use a 15-second connection and read timeout. The SDK automatically retries connection failures and temporary rate-limit or service-unavailable responses up to three times, waiting progressively longer between attempts.
#Method reference
Task | Method |
|---|---|
Connect with a persistent identity |
|
Create an ephemeral identity |
|
Read a standard secret |
|
Read all structured fields |
|
Read one structured field |
|
List accessible secrets |
|
List secrets in a project |
|
Export configuration values |
|
Enable encrypted fallback |
|
Monitor a secret |
|
Stop monitoring a secret |
|
List locally configured vaults |
|
#Source code and license
The Kotlin SDK is open source under the MIT License. You can review the implementation, report an issue, or contribute through the SikkerKeyOfficial GitHub organization.