NuGet packageCompense.Sdk
Version1.1.0 · API v1
Targetsnet8.0 and netstandard2.0 (.NET Framework 4.6.2+, .NET 6/7/8+, Mono)
DependenciesSystem.Text.Json, Microsoft.Extensions.Http, Microsoft.Extensions.Logging.Abstractions, Microsoft.Extensions.Options.ConfigurationExtensions
RepositoryAppiasoft/compense-saas-sdk-dotnet · guides in docs/modulos/ · examples in examples/ (console and webhook receiver)

Install #

Shell
dotnet add package Compense.Sdk --version 1.1.0

Client #

C#
using Compense.Sdk;
using Compense.Sdk.Models;

using var client = new CompenseClient(
    Environment.GetEnvironmentVariable("COMPENSE_API_KEY")!, CompenseEnvironment.Sandbox);

// With every option:
var configured = new CompenseClient(new CompenseClientOptions
{
    ApiKey = "cmp_...",
    Environment = CompenseEnvironment.Sandbox,  // Production (default) | Sandbox | Dev
    BaseUrl = null,                             // another URL; takes precedence over Environment
    Timeout = TimeSpan.FromSeconds(30),
    Retry = new RetryOptions { MaxAttempts = 3, RetryWrites = false },
    UserAgent = "horizonte-erp/2.0",
});

You can also use new CompenseClient(httpClient, options) with your own HttpClient (the SDK doesn’t dispose it and ignores its BaseAddress).

ASP.NET Core #

C#
// Program.cs
builder.Services.AddCompense(builder.Configuration.GetSection("Compense"));
// or: builder.Services.AddCompense(o => { o.ApiKey = "..."; o.Environment = CompenseEnvironment.Sandbox; });

app.MapGet("/saldo/{document}", async (string document, CompenseClient compense) =>
    (await compense.Wallet.BalanceAsync(document)).Available.ToString());
JSON
{
  "Compense": {
    "Environment": "Sandbox",
    "Timeout": "00:00:30",
    "Retry": { "MaxAttempts": 3, "RetryWrites": false }
  }
}

Provide the key through an environment variable (Compense__ApiKey=cmp_...) or a user secret. AddCompense registers a typed client with IHttpClientFactory (pooled handlers, DNS refresh) and returns the IHttpClientBuilder so you can add your own handlers (for example, telemetry or high-value signing). Deprecation warnings go to ILogger (category Compense.Sdk).

Conventions #

  • PascalCase methods with the Async suffix, a CancellationToken on all of them and nullable annotations: client.Wallet.Bills.PayAsync(document, billerCode, reference, amount, idempotencyKey: "...").
  • Writes → Transaction (Data is a JsonObject); reads → models (Balance, Resolution, Page, OffsetPage…) or JsonObject; every model keeps the body in .Raw. To map to your own type: tx.Data.Deserialize<MiDto>(CompenseJson.SerializerOptions).
  • Amounts: Amount, with implicit conversion from int, long, decimal or string.
  • Decisions: Decisions.Approve / Decisions.Reject. Affiliates: new AffiliateRef("CC", "1032456789").
  • Free-form fields: IReadOnlyDictionary<string, object?> (text values, numbers, Amount, JsonNode, dictionaries or objects, serialized in snake_case).

Errors #

CompenseException › CompenseConfigException and CompenseApiException › AuthException, NotFoundException, IdempotencyConflictException, ValidationException (Errors), RateLimitException (RetryAfter as TimeSpan?), UpstreamException, ServerException. Properties: Status, Title, Detail, TraceId, Problem. Network failures are the usual HttpRequestException / TaskCanceledException.

Pagination #

Every paginated list has an …AutoPagingAsync twin that returns IAsyncEnumerable<JsonObject> and fetches pages on demand:

C#
await foreach (var delivery in client.Webhooks.Deliveries.ListAutoPagingAsync(status: "failed"))
{
    await client.Webhooks.Deliveries.ReplayAsync((string)delivery["id"]!);
}

Webhooks #

C#
using Compense.Sdk.Webhooks;

WebhookEvent evt = CompenseWebhooks.Verify(rawBodyBytes, request.Headers, new[] { newSecret, oldSecret });
// evt.EventId, evt.Event, evt.Resource, evt.IsTest

It accepts the body as byte[] (preferred) or string, ASP.NET Core headers (IHeaderDictionary), HttpHeaders or key-value pairs, and one or more secrets. A complete minimal API receiver is in Verifying the signature.

Testing #

Pass a fake HttpMessageHandler in CompenseClientOptions.HttpMessageHandler, or an HttpClient built on top of it, and check the requests it receives. The repository uses the same technique in tests/Compense.Sdk.Tests.