Add the dependency to your Gradle build:
dependencies {
implementation("com.ekino.oss:karbone:0.2.0")
}Snapshots (built from main) are published to the Central Portal snapshot repository:
repositories {
mavenCentral()
maven { url = uri("https://central.sonatype.com/repository/maven-snapshots/") }
}Against Carbone Cloud, with an API key:
val karbone = Karbone.cloud(apiKey = "YOUR_API_KEY")Against a self-hosted carbone-ee (see On-premise for running one):
val karbone = Karbone.onPremise("http://localhost:4000", token = "YOUR_JWT")token is optional on-premise: pass nothing (or null) when the container runs with authentication disabled.
Both factories accept a trailing configuration block for timeouts, retries, JSON and more — see Configuration.
Every Karbone call is a suspending function that needs a Raise<KarboneError> in scope. The simplest way to get one is Arrow’s either { ... }, which turns the whole block into an Either<KarboneError, T>:
import arrow.core.raise.either
import com.ekino.oss.karbone.Karbone
import com.ekino.oss.karbone.model.PdfVersion
import com.ekino.oss.karbone.model.RenderData
import com.ekino.oss.karbone.model.TemplateSource
import java.nio.file.Path
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put
suspend fun renderInvoice() {
val karbone = Karbone.onPremise("http://localhost:4000", token = "YOUR_JWT")
val template = TemplateSource.file(Path.of("invoice.docx"))
val data =
RenderData.of(
buildJsonObject {
put("number", "F-2026-001")
put("total", 1234.5)
}
)
val result =
either {
karbone.renders.render(template, data) {
pdf { version = PdfVersion.PDF_A_3 }
lang = "fr-fr"
}
}
result.fold(
{ error -> println("Render failed: ${error.describe()}") },
{ document ->
println("Got ${document.fileName} (${document.content.size} bytes)")
document.writeTo(Path.of("invoice.pdf"))
},
)
}template is hashed locally (SHA-256) and rendered directly; Karbone only uploads it if Carbone does not already know that hash. render returns a RenderedDocument with content: ByteArray, fileName and contentType; use inputStream() or writeTo(path) to consume it. See Rendering for the full set of options.
Java has no coroutines and no Raise. Karbone.blocking() (Kotlin: any KarboneClient.blocking(), Java: KarboneBlocking.of(client)) returns a synchronous facade where every call runs to completion on the calling thread and throws KarboneException on failure. Because it works over the KarboneClient interface, the same facade wraps FakeKarbone in tests:
import com.ekino.oss.karbone.Karbone;
import com.ekino.oss.karbone.KarboneException;
import com.ekino.oss.karbone.blocking.KarboneBlocking;
import com.ekino.oss.karbone.model.RenderData;
import com.ekino.oss.karbone.model.RenderOptions;
import com.ekino.oss.karbone.model.RenderedDocument;
import com.ekino.oss.karbone.model.TemplateSource;
KarboneBlocking karbone = Karbone.onPremise("http://localhost:4000", "YOUR_JWT").blocking();
try {
RenderedDocument document =
karbone.getRenders().render(
TemplateSource.bytes(templateBytes, "invoice.docx"),
RenderData.raw("{\"number\":\"F-2026-001\"}"),
RenderOptions.None);
// use document.getContent(), document.getFileName()...
} catch (KarboneException e) {
// e.getError() is the KarboneError value
System.err.println(e.getMessage());
}