A strongly-typed .NET client library for the sevDesk API. Manage invoices, contacts, vouchers, orders, credit notes, and more — with full async support and dependency injection.
Feature highlights:
- 20 typed clients covering the entire sevDesk REST API
- Strongly typed models and enums for all resources
- Transaction operations: save invoice/order/voucher with positions atomically
- PDF generation, email sending, status management, and document upload
- Pagination with
SevDeskListResponse<T>and filtering - Proper exception hierarchy (
SevDeskAuthenticationException,SevDeskNotFoundException,SevDeskValidationException) IHttpClientFactoryintegration with automatic auth header injection- Dependency injection via
IServiceCollection.AddSevDesk()
- A sevDesk account and API token
- .NET 10.0
dotnet add package sevDesk.NETIn Program.cs, register sevDesk.NET with your API token:
builder.Services.AddSevDesk(options =>
{
options.ApiToken = "your-api-token";
});For custom base URLs (e.g. self-hosted or proxy):
builder.Services.AddSevDesk(options =>
{
options.ApiToken = "your-api-token";
options.CustomBaseUrl = "https://my-proxy.example.com/api/v1";
});public class InvoiceService
{
private readonly ISevDeskClient _client;
public InvoiceService(ISevDeskClient client)
{
_client = client;
}
public async Task ListRecentInvoicesAsync()
{
var result = await _client.Invoices.ListAsync();
foreach (var invoice in result.Items)
{
Console.WriteLine($"{invoice.InvoiceNumber}: {invoice.SumGross} {invoice.Currency}");
}
}
}{
"SevDesk": {
"ApiToken": "your-api-token"
}
}builder.Services.AddSevDesk(
builder.Configuration.GetSection("SevDesk"));| Client | Property | Operations |
|---|---|---|
| Invoices | client.Invoices |
CRUD, SaveInvoice, ChangeStatus, GetPdf, SendViaEmail, Duplicate, Cancel, MarkAsSent, BookAmount |
| Invoice Positions | client.InvoicePositions |
CRUD, filter by invoice |
| Orders | client.Orders |
CRUD, SaveOrder, ChangeStatus, GetPdf, SendViaEmail, Duplicate |
| Order Positions | client.OrderPositions |
CRUD, filter by order |
| Vouchers | client.Vouchers |
CRUD, SaveVoucher, BookAmount, MarkAsPaid, MarkAsOpen, UploadFile |
| Voucher Positions | client.VoucherPositions |
CRUD, filter by voucher |
| Credit Notes | client.CreditNotes |
CRUD, SaveCreditNote, CreateFromInvoice, GetPdf, SendViaEmail |
| Credit Note Positions | client.CreditNotePositions |
CRUD, filter by credit note |
| Client | Property | Operations |
|---|---|---|
| Contacts | client.Contacts |
CRUD, GetNextCustomerNumber |
| Contact Addresses | client.ContactAddresses |
CRUD, filter by contact |
| Communication Ways | client.CommunicationWays |
CRUD, filter by contact |
| Client | Property | Operations |
|---|---|---|
| Check Accounts | client.CheckAccounts |
CRUD, GetBalance |
| Check Account Transactions | client.CheckAccountTransactions |
CRUD, filter by account |
| Client | Property | Operations |
|---|---|---|
| Parts | client.Parts |
CRUD |
| Client | Property | Operations |
|---|---|---|
| Tags | client.Tags |
Create, List, Get, Delete |
| Categories | client.Categories |
CRUD, filter by object type |
| Documents | client.Documents |
List, Get, Upload, Download |
| Client | Property | Operations |
|---|---|---|
| Unities | client.Unities |
List, Get |
| Tax Rules | client.TaxRules |
List, Get |
| Currency Exchange Rates | client.CurrencyExchangeRates |
List, Get |
var invoice = await client.Invoices.SaveInvoiceAsync(
new Invoice
{
Contact = new SevDeskObjectReference { Id = 123, ObjectName = "Contact" },
InvoiceDate = DateTime.Today,
Header = "Invoice 2024-001",
TimeToPay = 14
},
new[]
{
new InvoicePos
{
Name = "Consulting",
Quantity = 10,
Price = 150.00m,
Unity = new SevDeskObjectReference { Id = 1, ObjectName = "Unity" },
TaxRate = 19
}
});byte[] pdf = await client.Invoices.GetPdfAsync(invoiceId);
File.WriteAllBytes("invoice.pdf", pdf);await client.Invoices.SendViaEmailAsync(
invoiceId,
email: "customer@example.com",
subject: "Your Invoice",
text: "Please find your invoice attached.");var page = await client.Contacts.ListAsync(new PaginationParameters
{
Limit = 50,
Offset = 100
});
Console.WriteLine($"Showing {page.Items.Count} of {page.Total} contacts");await using var stream = File.OpenRead("receipt.pdf");
var document = await client.Vouchers.UploadFileAsync(stream, "receipt.pdf");decimal balance = await client.CheckAccounts.GetBalanceAsync(
accountId,
date: DateTime.Today);sevDesk.NET uses a typed exception hierarchy:
try
{
var invoice = await client.Invoices.GetAsync(id);
}
catch (SevDeskNotFoundException)
{
// 404 — invoice not found
}
catch (SevDeskAuthenticationException)
{
// 401 — invalid API token
}
catch (SevDeskValidationException ex)
{
// 422 — validation error
Console.WriteLine(ex.RawResponse);
}
catch (SevDeskApiException ex)
{
// Other API errors
Console.WriteLine($"{ex.StatusCode}: {ex.Message}");
}| Exception | HTTP Status | When |
|---|---|---|
SevDeskAuthenticationException |
401 | Invalid or missing API token |
SevDeskNotFoundException |
404 | Resource not found |
SevDeskValidationException |
422 | Invalid request data |
SevDeskApiException |
Various | Other API errors |
SevDeskException |
— | Base exception (network errors, etc.) |
| Property | Type | Default | Description |
|---|---|---|---|
ApiToken |
string |
(required) | 32-character API token from sevDesk |
CustomBaseUrl |
string? |
null |
Override the default API base URL |
BaseUrl |
string |
https://my.sevdesk.de/api/v1 |
Computed base URL (uses CustomBaseUrl if set) |
AddSevDesk() validates options on registration:
ApiTokenmust not be emptyCustomBaseUrl(if set) must use HTTPS or be localhost
MIT