Skip to content

Bullmark.Sdk (.NET)

Terminal window
dotnet add package Bullmark.Sdk

.NET 10. Server-side only — the key burns vouchers.

var bm = new BullmarkClient(new BullmarkOptions
{
ApiKey = config["Bullmark:ApiKey"]!,
BaseUrl = "https://api.bullmark.net", // optional
});

Register it once — it is thread-safe and holds no per-request state. Pass an HttpClient from IHttpClientFactory so its lifetime and pooling are yours:

services.AddHttpClient("bullmark");
services.AddSingleton(sp => new BullmarkClient(
new BullmarkOptions { ApiKey = cfg["Bullmark:ApiKey"]! },
sp.GetRequiredService<IHttpClientFactory>().CreateClient("bullmark")));
await bm.Vouchers.InspectAsync(codeOrTicket, ct); // what do I owe them?
await bm.Vouchers.ReserveAsync(code, ct); // hold it (optional)
await bm.Vouchers.RedeemAsync(new RedeemRequest( // burn it
ExternalRef: order.Id.ToString(), Code: code), ct);
await bm.Vouchers.ReleaseAsync(ticketOrCode, "payment_failed", ct); // give it back
await bm.Integrity.ChainAsync(code, ct); // check us

RedeemAsync throws ArgumentException before making a request when ExternalRef is missing — a missing reference is otherwise only discovered when a timeout costs a customer their voucher.

catch (BullmarkException ex) when (ex.Unreachable)
{
// We never got an answer. Do NOT tell the customer their voucher is invalid.
}
catch (BullmarkException ex)
{
// ex.Message — our own words, written for a person. Show it.
// ex.Status — the HTTP status, if you need to branch.
}

ChainAsync returns the sealed chain with canonical payloads, so you can recompute the hashes locally. Axowl.Sdk.Integrity.Hashing computes the same document; the algorithm and its conformance vectors are on The seal hash.