Skip to content

Kotlin SDK

Official Kotlin SDK for thelawin.dev.

Requires Kotlin 2.0+ / JDK 17+

Installation

Beta-Phase

Während der Beta sind die SDKs über GitHub/JitPack verfügbar. Maven Central-Veröffentlichung folgt mit dem stabilen Release.

Via JitPack

kotlin
// settings.gradle.kts
repositories {
    maven { url = uri("https://jitpack.io") }
}

// build.gradle.kts
dependencies {
    implementation("com.github.steviee.thelawin-clients:kotlin:main-SNAPSHOT")
}

Lokaler Build

bash
git clone https://github.com/steviee/thelawin-clients.git
cd thelawin-clients/kotlin
./gradlew publishToMavenLocal
kotlin
// build.gradle.kts
dependencies {
    implementation("dev.thelawin:sdk:1.0.0")
}

Quick Start

kotlin
import dev.thelawin.ThelawinClient

val client = ThelawinClient("env_sandbox_xxx")

val result = client.invoice()
    .number("2026-001")
    .date("2026-01-15")
    .seller { name = "Acme GmbH"; vatId = "DE123456789"; city = "Berlin"; country = "DE" }
    .buyer { name = "Customer AG"; city = "München"; country = "DE" }
    .addItem { description = "Consulting Services"; quantity = 8; unit = "HUR"; unitPrice = 150.0; vatRate = 19.0 }
    .template("minimal")
    .generate()

when (result) {
    is Success -> {
        result.savePdf("./invoice.pdf")
        println("Generated: ${result.filename}")
    }
    is Failure -> {
        result.errors.forEach { println("${it.path}: ${it.message}") }
    }
}

Coroutines Support

kotlin
import dev.thelawin.ThelawinClient
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val client = ThelawinClient("env_sandbox_xxx")

    val result = client.invoice()
        .number("2026-001")
        .seller { name = "Acme GmbH"; vatId = "DE123456789"; city = "Berlin"; country = "DE" }
        .buyer { name = "Customer AG"; city = "München"; country = "DE" }
        .addItem { description = "Consulting"; quantity = 8; unit = "HUR"; unitPrice = 150.0; vatRate = 19.0 }
        .generate()

    if (result.isSuccess) {
        result.savePdf("./invoice.pdf")
    }
}

Client Options

kotlin
val client = ThelawinClient(
    apiKey = "env_sandbox_xxx",
    baseUrl = "https://api.thelawin.dev",  // optional
    timeout = 30.seconds                   // optional
)

DSL Builder

Invoice Details

kotlin
client.invoice()
    .number("2026-001")           // Required
    .date("2026-01-15")           // Required
    .dueDate("2026-02-15")        // Optional
    .currency("EUR")              // Default: "EUR"

Parties (DSL Style)

kotlin
.seller {
    name = "Acme GmbH"           // Required
    vatId = "DE123456789"        // Required
    street = "Hauptstraße 1"
    city = "Berlin"              // Required
    postalCode = "10115"
    country = "DE"               // Required
}
.buyer {
    name = "Customer AG"         // Required
    city = "München"             // Required
    country = "DE"               // Required
}

Line Items

kotlin
.addItem {
    description = "Consulting"   // Required
    quantity = 8                 // Required
    unit = "HUR"                 // Required
    unitPrice = 150.0            // Required
    vatRate = 19.0               // Required
}
// Multiple items
.addItem { description = "Support"; quantity = 2; unit = "HUR"; unitPrice = 100.0; vatRate = 19.0 }

Customization

kotlin
.template("minimal")            // "minimal", "classic", "compact"
.locale("de")                   // "en", "de", "fr", "es", "it"
.accentColor("#8b5cf6")
.footerText("Thank you!")
kotlin
// From file (auto Base64)
.logoFile("./logo.png")
.logoFile("./logo.png", widthMm = 30)

// From Base64
.logoBase64("iVBORw0KGgo...", widthMm = 30)

Result Handling

kotlin
when (val result = builder.generate()) {
    is Success -> {
        println(result.filename)      // "invoice-2026-001.pdf"
        println(result.validation)    // ValidationResult(status=valid, ...)

        // Save to file
        result.savePdf("./invoice.pdf")

        // Get bytes
        val bytes = result.toBytes()

        // Get data URL
        val dataUrl = result.toDataUrl()
    }
    is Failure -> {
        result.errors.forEach { error ->
            println("${error.path}: ${error.message}")
        }
    }
}

Error Handling

kotlin
import dev.thelawin.ThelawinApiException
import dev.thelawin.ThelawinNetworkException
import dev.thelawin.ThelawinQuotaExceededException

try {
    val result = client.invoice().generate()
} catch (e: ThelawinQuotaExceededException) {
    println("Quota exceeded, upgrade your plan")
} catch (e: ThelawinNetworkException) {
    println("Network error: ${e.message}")
} catch (e: ThelawinApiException) {
    println("API error ${e.statusCode}: ${e.message}")
}

Source Code

github.com/steviee/thelawin-clients/tree/main/kotlin

ZUGFeRD 2.3 & Factur-X 1.0 compliant