Skip to content

C# SDK

Official .NET SDK for thelawin.dev.

Requires .NET 8.0+

Installation

Beta-Phase

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

Via Git Submodule

bash
git submodule add https://github.com/steviee/thelawin-clients.git lib/thelawin-clients
xml
<!-- In deiner .csproj -->
<ItemGroup>
    <ProjectReference Include="lib/thelawin-clients/csharp/Thelawin.csproj" />
</ItemGroup>

Lokaler Build

bash
git clone https://github.com/steviee/thelawin-clients.git
cd thelawin-clients/csharp
dotnet pack -o ./nupkg

# In deinem Projekt
dotnet add package Thelawin --source ./thelawin-clients/csharp/nupkg

Quick Start

csharp
using Thelawin;

using var client = new ThelawinClient("env_sandbox_xxx");

var result = await client.Invoice()
    .Number("2026-001")
    .Date("2026-01-15")
    .Seller(s => s.Name("Acme GmbH").VatId("DE123456789").City("Berlin").Country("DE"))
    .Buyer(b => b.Name("Customer AG").City("München").Country("DE"))
    .AddItem(i => i.Description("Consulting Services").Quantity(8).Unit("HUR").UnitPrice(150).VatRate(19))
    .Template("minimal")
    .GenerateAsync();

if (result.IsSuccess)
{
    var success = (InvoiceSuccess)result;
    await success.SavePdfAsync("./invoice.pdf");
    Console.WriteLine($"Generated: {success.Filename}");
}
else
{
    var failure = (InvoiceFailure)result;
    foreach (var error in failure.Errors)
        Console.Error.WriteLine($"{error.Path}: {error.Message}");
}

Client Options

csharp
using var client = new ThelawinClient(
    apiKey: "env_sandbox_xxx",
    apiUrl: "https://api.thelawin.dev",  // optional
    timeout: TimeSpan.FromSeconds(30)    // optional
);

Builder API

Invoice Details

csharp
client.Invoice()
    .Number("2026-001")           // Required
    .Date("2026-01-15")           // Required, string or DateOnly
    .DueDate("2026-02-15")        // Optional
    .Currency("EUR")              // Default: "EUR"

Parties (Lambda Style)

csharp
.Seller(s => s
    .Name("Acme GmbH")           // Required
    .VatId("DE123456789")        // Required
    .Street("Hauptstraße 1")
    .City("Berlin")              // Required
    .PostalCode("10115")
    .Country("DE"))              // Required
.Buyer(b => b
    .Name("Customer AG")         // Required
    .City("München")             // Required
    .Country("DE"))              // Required

Line Items

csharp
.AddItem(i => i
    .Description("Consulting")   // Required
    .Quantity(8)                 // Required
    .Unit("HUR")                 // Required
    .UnitPrice(150.00)           // Required
    .VatRate(19.0))              // Required

Customization

csharp
.Template("minimal")            // "minimal", "classic", "compact"
.Locale("de")                   // "en", "de", "fr", "es", "it"
.AccentColor("#8b5cf6")
.FooterText("Thank you!")
csharp
// From file (auto Base64) - async
await builder.LogoFileAsync("./logo.png");
await builder.LogoFileAsync("./logo.png", widthMm: 30);

// From Base64
.LogoBase64("iVBORw0KGgo...", widthMm: 30)

Result Handling

csharp
var result = await builder.GenerateAsync();

if (result.IsSuccess)
{
    var success = (InvoiceSuccess)result;
    Console.WriteLine(success.Filename);      // "invoice-2026-001.pdf"
    Console.WriteLine(success.Validation);    // ValidationResult { Status = valid, ... }

    // Save to file
    await success.SavePdfAsync("./invoice.pdf");

    // Get bytes
    byte[] bytes = success.ToBytes();

    // Get data URL
    string dataUrl = success.ToDataUrl();
}
else
{
    var failure = (InvoiceFailure)result;
    foreach (var error in failure.Errors)
        Console.Error.WriteLine($"{error.Path}: {error.Message}");
}

Pattern Matching

csharp
switch (result)
{
    case InvoiceSuccess success:
        await success.SavePdfAsync("./invoice.pdf");
        Console.WriteLine($"Generated: {success.Filename}");
        break;
    case InvoiceFailure failure:
        foreach (var error in failure.Errors)
            Console.Error.WriteLine($"{error.Path}: {error.Message}");
        break;
}

Error Handling

csharp
try
{
    var result = await client.Invoice().GenerateAsync();
}
catch (ThelawinQuotaExceededException)
{
    Console.WriteLine("Quota exceeded, upgrade your plan");
}
catch (ThelawinNetworkException ex)
{
    Console.WriteLine($"Network error: {ex.Message}");
}
catch (ThelawinApiException ex)
{
    Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
}

ASP.NET Core Integration

csharp
// Program.cs
builder.Services.AddSingleton<IThelawinClient>(sp =>
    new ThelawinClient(builder.Configuration["Thelawin:ApiKey"]!));

// InvoiceController.cs
[ApiController]
[Route("api/[controller]")]
public class InvoicesController : ControllerBase
{
    private readonly IThelawinClient _thelawin;

    public InvoicesController(IThelawinClient thelawin)
    {
        _thelawin = thelawin;
    }

    [HttpPost]
    public async Task<IActionResult> Generate([FromBody] InvoiceRequest request)
    {
        var result = await _thelawin.Invoice()
            .Number(request.Number)
            .Date(request.Date)
            .Seller(s => s.Name(request.SellerName).VatId(request.SellerVatId)...)
            .Buyer(b => b.Name(request.BuyerName)...)
            .GenerateAsync();

        if (result.IsSuccess)
        {
            var success = (InvoiceSuccess)result;
            return File(success.ToBytes(), "application/pdf", success.Filename);
        }

        var failure = (InvoiceFailure)result;
        return BadRequest(failure.Errors);
    }
}

Source Code

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

ZUGFeRD 2.3 & Factur-X 1.0 compliant