/

Configuration

KarboneConfig

KarboneConfig is the immutable, per-client configuration behind every Karbone instance:

FieldDefaultMeaning
baseUrl—https://api.carbone.io or an on-premise URL such as http://localhost:4000. Trailing slash optional.
tokennullBearer token. null sends no Authorization header.
apiVersionnullcarbone-version header. null omits it (what on-premise expects); cloud uses KarboneConfig.LATEST_API_VERSION (5).
connectTimeout10 secondsTCP connect timeout.
requestTimeout60 secondsPer-request timeout. Carbone’s own synchronous render timeout is 60 s.
retryRetryPolicy.NoneRetries transport failures only — API errors are never retried.
jsonKarboneConfig.DefaultJsonkotlinx.serialization.json.Json used for request bodies and response parsing.
userAgent"karbone/<version>"User-Agent header sent with every request.

Building a client

Karbone.cloud and Karbone.onPremise both go through KarboneConfig.Builder, exposed as a trailing lambda:

val cloud = Karbone.cloud("YOUR_API_KEY") {
  requestTimeout = 30.seconds
  retry = RetryPolicy.OnTransportError(maxAttempts = 3, backoff = 300.milliseconds)
}

val onPremise = Karbone.onPremise("http://localhost:4000", token = "YOUR_JWT") {
  connectTimeout = 5.seconds
}

Defaults differ deliberately between the two factories:

Retries (RetryPolicy.OnTransportError) only cover connection resets, timeouts and other I/O failures — never a Carbone API error such as a 4xx or 5xx response, which is always surfaced as the corresponding KarboneError on the first attempt.

Per-call headers

KarboneConfig configures headers for the whole client; a single render can add its own through RenderOptions.headers (or the builder’s header(name, value)), for example to relay a token to a downstream service via carbone-egress-header-authorization, without changing the client’s own Authorization:

karbone.renders.render(template, data) {
  header("carbone-egress-header-authorization", "Bearer downstream-token")
}

Spring Boot compatibility

Spring Boot’s dependency management pins kotlinx-coroutines (1.10.2 in Spring Boot 4.1) and kotlinx-serialization (1.11.0). Karbone is compiled against exactly those versions, so the artifact resolved by the BOM is the one Karbone was built with.

Why it matters: a library compiled against coroutines 1.11 references runBlockingK, an overload that does not exist in 1.10.2. If the BOM downgrades the runtime, the blocking facade fails with NoSuchMethodError at the first call. This bit the first consumer of Karbone 0.1.2. If you need a newer coroutines line anyway, override the managed version for the whole project:

// build.gradle.kts
extra["kotlin-coroutines.version"] = "1.11.0"

Arrow (arrow-core) and kotlin-logging are not managed by Spring Boot; Karbone brings its own versions.

Reading a client’s settings

Karbone does not expose its KarboneConfig: the token stays private and the configuration is a construction detail. Two read-only values are available because they are useful in startup logs and health checks:

logger.info { "Carbone at ${karbone.baseUrl} (api version ${karbone.apiVersion ?: "server default"})" }

Logging

Karbone logs through kotlin-logging under the com.ekino.oss.karbone logger names and stays silent at INFO and above in the normal path. See the dedicated Logging page for backends, levels, what is never logged and configuration examples.