.NET / C# SDK
The C# SDK targets net8.0 and net10.0. NuGet:
dotnet add package Paylera.SdkConstruct a client
using Paylera;
var paylera = new PayleraClient(new PayleraOptions{ ApiKey = Environment.GetEnvironmentVariable("PAYLERA_KEY")!, BaseUrl = PayleraEnvironment.Sandbox, // or .Live ApiVersion = "2026-04-01",});PayleraOptions is plain record — easy to bind from
IConfiguration. The client is thread-safe; create one and reuse it.
DI registration
builder.Services.AddPayleraClient(options =>{ options.ApiKey = builder.Configuration["Paylera:ApiKey"]!; options.BaseUrl = PayleraEnvironment.Sandbox; options.ApiVersion = "2026-04-01";});AddPayleraClient registers IPayleraClient as a singleton.
Make a call
var customer = await paylera.Customers.CreateAsync(new(){ Email = "ada@example.com", Name = "Ada Lovelace", BillingAddress = new() { Country = "US", PostalCode = "94105" },});CreateAsync auto-generates an idempotency key. Override with the
overload:
await paylera.Customers.CreateAsync(request, idempotencyKey: "my-key");Handle structured errors
try{ var pay = await paylera.Invoices.PayAsync(invoiceId);}catch (PayleraApiException ex) when (ex.Problem == "payment.requires_action"){ // ex.NextAction.Url is set}catch (PayleraApiException ex){ logger.LogWarning("Paylera error {Problem} (trace {TraceId}): {Detail}", ex.Problem, ex.TraceId, ex.Detail); throw;}List with pagination
await foreach (var sub in paylera.Subscriptions.ListAsync(new(){ Status = ["active", "past_due"]})){ Console.WriteLine($"{sub.Id} {sub.PlanCode} {sub.Status}");}The async-iterator walks pages for you. Bound the iteration with
Take(N) if you only want a slice.
Idempotency helpers
var key = IdempotencyKey.From("subscribe", userId, planCode);await paylera.Subscriptions.CreateAsync(req, idempotencyKey: key);IdempotencyKey.From deterministically derives a key from intent
fields — safe to reuse across retries.
Money
var amount = Money.Of(29.00m, "USD");var sum = amount + Money.Of(5, "USD"); // operator-overloadedvar s = amount.ToString(); // "29.00 USD"Money rejects mixed-currency arithmetic at compile time if both
operands are typed Money — it throws at runtime if you’ve cast away
the type.
Webhook verification
app.MapPost("/webhooks/paylera", async (HttpRequest req) =>{ using var ms = new MemoryStream(); await req.Body.CopyToAsync(ms); var body = ms.ToArray();
var header = req.Headers["Paylera-Signature"].ToString(); if (!Webhooks.Verify(body, header, secret)) return Results.Unauthorized();
var evt = Webhooks.Parse(body); // dispatch on evt.Type, evt.Id, evt.Data return Results.Ok();});Webhooks.Verify does timing-safe comparison and replay-window
checking.
Retries and timeouts
Defaults: 5 attempts on 429/5xx, exponential backoff with jitter, 30s
per-request timeout. Tune via PayleraOptions.Retry and Timeout.
To disable automatic retries (you’ve got a smarter outer loop):
options.Retry.MaxAttempts = 0;Observability
Pass an ILogger<PayleraClient> and the SDK logs request IDs, status
codes, and trace IDs at Information. To get raw bodies on errors,
set options.Logging.IncludeRawBodyOnError = true — only enable in
dev; bodies may include PII.
Source
github.com/paylera/paylera-dotnet — issues and PRs welcome.