Table of Contents

Getting Started with PolarSharp

PolarSharp is a .NET 10 AOT-compatible SDK for Polar.sh, an open-source Merchant of Record payment platform.

Installation

# Core library (required)
dotnet add package PolarSharp

# Optional: webhook handler registration + signature verification
dotnet add package PolarSharp.Webhooks

# Optional: multi-tenant support (Finbuckle.MultiTenant integration)
dotnet add package PolarSharp.MultiTenant

Configuration

Add a PolarSharp section to your appsettings.json:

{
  "PolarSharp": {
    "Mode": "Test",
    "AccessToken": "tok_sandbox_xxx"
  }
}

Set Mode to "Test" for Polar's sandbox (no real charges) or "Live" for production.

Use user-secrets to keep the token out of source control:

dotnet user-secrets set "PolarSharp:AccessToken" "tok_sandbox_xxx"

Minimal registration (Program.cs)

var builder = WebApplication.CreateBuilder(args);

// Register PolarSharp services
builder.Services
    .AddPolarInfrastructure(builder.Configuration)   // core
    .AddPolarWebhooks()                               // optional
    .AddPolarMultiTenant();                           // optional

var app = builder.Build();

// UseRequestLocalization before UsePolarInfrastructure (sets culture for error messages)
app.UseRequestLocalization(opts =>
    opts.SetDefaultCulture("en-US")
        .AddSupportedUICultures("en-US", "es-MX"));

// Wire middleware: UseMultiTenancy + MapPolarWebhooks — one call handles all
app.UsePolarInfrastructure();

// Map your own endpoints
app.MapGet("/orders/{id}", async (string id, PolarClient polar, CancellationToken ct) =>
    (await polar.Orders[id].GetAsync(cancellationToken: ct))
        .Match(
            onSuccess: order => Results.Ok(order),
            onFailure: error => error.ToHttpResult()));

app.Run();

See Middleware Pipeline Ordering for the correct position of UsePolarInfrastructure().

First API call

Inject PolarClient into any handler, controller, or service:

app.MapGet("/products", async (PolarClient polar, CancellationToken ct) =>
{
    var result = await polar.Products.EmptyPathSegment.GetAsync(cancellationToken: ct);
    return result is null ? Results.NotFound() : Results.Ok(result);
});

Resource methods return Task<Result<TValue, PolarError>> — never throw for HTTP 4xx responses. Pattern-match the result with .Match(onSuccess, onFailure).

Next steps