Dart SDK
Official Dart SDK for thelawin.dev.
Requires Dart 3.0+ / Flutter 3.10+
Installation
Beta-Phase
Während der Beta sind die SDKs über GitHub verfügbar. pub.dev-Veröffentlichung folgt mit dem stabilen Release.
In deiner pubspec.yaml:
yaml
dependencies:
thelawin:
git:
url: https://github.com/steviee/thelawin-clients.git
path: dartDann:
bash
dart pub get
# oder für Flutter
flutter pub getQuick Start
dart
import 'package:thelawin/thelawin.dart';
final client = ThelawinClient(apiKey: 'env_sandbox_xxx');
final result = 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: 'HUR', unitPrice: 150, vatRate: 19)
.template('minimal')
.generate();
if (result.isSuccess) {
await result.savePdf('./invoice.pdf');
print('Generated: ${result.filename}');
} else {
for (final error in result.errors) {
print('${error.path}: ${error.message}');
}
}Client Options
dart
final client = ThelawinClient(
apiKey: 'env_sandbox_xxx',
baseUrl: 'https://api.thelawin.dev', // optional
timeout: Duration(seconds: 30), // optional
);Builder API
Invoice Details
dart
client.invoice()
.number('2026-001') // Required
.date('2026-01-15') // Required
.dueDate('2026-02-15') // Optional
.currency('EUR') // Default: 'EUR'Parties
dart
.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
dart
.addItem(
description: 'Consulting', // Required
quantity: 8, // Required
unit: 'HUR', // Required
unitPrice: 150.00, // Required
vatRate: 19.0, // Required
)Customization
dart
.template('minimal') // 'minimal', 'classic', 'compact'
.locale('de') // 'en', 'de', 'fr', 'es', 'it'
.accentColor('#8b5cf6')
.footerText('Thank you!')Logo
dart
// From file (auto Base64)
.logoFile('./logo.png')
.logoFile('./logo.png', widthMm: 30)
// From bytes
.logoBytes(imageBytes, widthMm: 30)
// From Base64
.logoBase64('iVBORw0KGgo...', widthMm: 30)Result Handling
dart
final result = await builder.generate();
if (result.isSuccess) {
print(result.filename); // 'invoice-2026-001.pdf'
print(result.validation); // ValidationResult(status: valid, ...)
// Save to file
await result.savePdf('./invoice.pdf');
// Get bytes
final bytes = result.toBytes();
// Get data URL
final dataUrl = result.toDataUrl();
} else {
for (final error in result.errors) {
print('${error.path}: ${error.message}');
}
}Pattern Matching (Dart 3.0+)
dart
switch (result) {
case InvoiceSuccess(:final filename, :final validation):
print('Generated: $filename');
print('Validation: ${validation.status}');
case InvoiceFailure(:final errors):
for (final error in errors) {
print('${error.path}: ${error.message}');
}
}Error Handling
dart
try {
final result = await client.invoice().generate();
} on ThelawinQuotaExceededException {
print('Quota exceeded, upgrade your plan');
} on ThelawinNetworkException catch (e) {
print('Network error: ${e.message}');
} on ThelawinApiException catch (e) {
print('API error ${e.statusCode}: ${e.message}');
}Flutter Example
dart
import 'package:flutter/material.dart';
import 'package:thelawin/thelawin.dart';
import 'package:printing/printing.dart';
class InvoiceScreen extends StatefulWidget {
@override
_InvoiceScreenState createState() => _InvoiceScreenState();
}
class _InvoiceScreenState extends State<InvoiceScreen> {
final client = ThelawinClient(apiKey: 'env_sandbox_xxx');
Uint8List? pdfBytes;
bool isLoading = false;
Future<void> generateInvoice() async {
setState(() => isLoading = true);
final result = 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: 'HUR', unitPrice: 150, vatRate: 19)
.generate();
setState(() {
isLoading = false;
if (result.isSuccess) {
pdfBytes = result.toBytes();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Invoice Generator')),
body: Column(
children: [
if (pdfBytes != null)
Expanded(child: PdfPreview(build: (format) => pdfBytes!)),
ElevatedButton(
onPressed: isLoading ? null : generateInvoice,
child: Text(isLoading ? 'Generating...' : 'Generate Invoice'),
),
],
),
);
}
}