Swift SDK
Official Swift SDK for thelawin.dev.
Requires Swift 5.9+ / iOS 14+ / macOS 11+
Installation
Swift Package Manager
swift
// Package.swift
dependencies: [
.package(url: "https://github.com/steviee/thelawin-clients.git", branch: "main")
],
targets: [
.target(
name: "YourApp",
dependencies: [
.product(name: "Thelawin", package: "thelawin-clients", condition: nil)
],
path: "swift"
)
]Oder in Xcode: File → Add Package Dependencies → https://github.com/steviee/thelawin-clients
TIP
Swift Package Manager unterstützt Mono-Repos mit Subdirectories. Das SDK liegt im swift/ Verzeichnis.
Quick Start
swift
import Thelawin
let client = ThelawinClient(apiKey: "env_sandbox_xxx")
let result = try await 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: .hour, unitPrice: 150, vatRate: 19)
.template(.minimal)
.generate()
switch result {
case .success(let invoice):
try invoice.savePdf(to: URL(fileURLWithPath: "./invoice.pdf"))
print("Generated: \(invoice.filename)")
case .failure(let errors):
errors.forEach { print("\($0.path): \($0.message)") }
}Client Options
swift
let client = ThelawinClient(
apiKey: "env_sandbox_xxx",
baseUrl: URL(string: "https://api.thelawin.dev")!, // optional
timeout: 30 // optional, seconds
)Builder API
Invoice Details
swift
client.invoice()
.number("2026-001") // Required
.date("2026-01-15") // Required, String or Date
.dueDate("2026-02-15") // Optional
.currency("EUR") // Default: "EUR"Parties
swift
.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
vatId: "DE987654321",
city: "München", // Required
country: "DE" // Required
)Line Items
swift
.addItem(
description: "Consulting", // Required
quantity: 8, // Required
unit: .hour, // Required (enum)
unitPrice: 150.00, // Required
vatRate: 19.0 // Required
)Unit Types
swift
enum UnitCode: String {
case hour = "HUR"
case day = "DAY"
case month = "MON"
case piece = "C62"
// ... more
}Customization
swift
.template(.minimal) // .minimal, .classic, .compact
.locale(.german) // .english, .german, .french, .spanish, .italian
.accentColor("#8b5cf6")
.footerText("Thank you!")Logo
swift
// From file URL (auto Base64)
.logoFile(URL(fileURLWithPath: "./logo.png"))
.logoFile(URL(fileURLWithPath: "./logo.png"), widthMm: 30)
// From Data
.logoData(imageData, widthMm: 30)
// From Base64
.logoBase64("iVBORw0KGgo...", widthMm: 30)Result Handling
swift
switch result {
case .success(let invoice):
print(invoice.filename) // "invoice-2026-001.pdf"
print(invoice.validation) // ValidationResult(status: .valid, ...)
// Save to file
try invoice.savePdf(to: URL(fileURLWithPath: "./invoice.pdf"))
// Get Data
let data = invoice.toData()
// Get data URL
let dataUrl = invoice.toDataUrl()
case .failure(let errors):
for error in errors {
print("\(error.path): \(error.message)")
}
}Error Handling
swift
do {
let result = try await client.invoice().generate()
} catch ThelawinError.quotaExceeded {
print("Quota exceeded, upgrade your plan")
} catch ThelawinError.network(let message) {
print("Network error: \(message)")
} catch ThelawinError.api(let statusCode, let message) {
print("API error \(statusCode): \(message)")
}SwiftUI Example
swift
import SwiftUI
import Thelawin
struct InvoiceView: View {
@State private var isGenerating = false
@State private var pdfData: Data?
let client = ThelawinClient(apiKey: "env_sandbox_xxx")
var body: some View {
VStack {
if let data = pdfData {
PDFKitView(data: data)
}
Button("Generate Invoice") {
Task { await generateInvoice() }
}
.disabled(isGenerating)
}
}
func generateInvoice() async {
isGenerating = true
defer { isGenerating = false }
let result = try? await 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: .hour, unitPrice: 150, vatRate: 19)
.generate()
if case .success(let invoice) = result {
pdfData = invoice.toData()
}
}
}