The generated client takes a RepostClientOptions. The constructor validates every value and snapshots the result; mutating the options instance afterwards never affects a constructed client. The defaults are the production values.
Client options#
await using var repost = new RepostClient(new RepostClientOptions
{
ApiKey = Environment.GetEnvironmentVariable("REPOST_SEND_API_KEY"),
BaseUri = "https://api.repost.sh",
OperationTimeout = TimeSpan.FromSeconds(30),
MaxAttempts = 4,
});Credential and endpoint precedence#
Credentials, highest first: an ApiKeyProvider (resolved once per send) or a fixed ApiKey (the two conflict, so set only one), then the REPOST_SEND_API_KEY environment variable, then REPOST_TOKEN, both snapshotted at construction. With none set, the first send fails with a Configuration error and never touches the network.
Base URI: an explicit BaseUri, then REPOST_API_URL, then the default https://api.repost.sh. Trailing slashes are stripped and /v1/messages is appended. Lowercase http:// is accepted only for loopback hosts.
RepostClientOptions.ToString() is redacted: it never prints your credential.
Defaults#
The defaults are production-ready:
| Option | Default | Notes |
|---|---|---|
ConnectTimeout | 10s | Connection establishment. |
AttemptTimeout | 30s | One HTTP attempt, clamped to the remaining operation budget. |
OperationTimeout | 120s | Whole operation, including retries: the one deadline that bounds a send. |
MaxAttempts | 4 | 1–10. Transport attempts before giving up. |
RetryBaseDelay / RetryMaxDelay | 250ms / 60s | Exponential backoff with full jitter. |
MaxInFlightOperations | 256 | 1–65,536. Bounded admission. See Reliability. |
MaxBufferedBytes | 64 MiB | 4 MiB–1 GiB. Aggregate request/response byte budget. |
TelemetryEnabled | true | The built-in Repost.Client ActivitySource and Meter. |
TraceParentPropagationEnabled | true | W3C traceparent/tracestate request headers. |
Every request goes to POST <BaseUri>/v1/messages with Authorization: Bearer, Content-Type: application/json, and Idempotency-Key headers.
Custom transport and enterprise networking#
Retries, timeouts, and cancellation always stay with the runtime; a transport executes exactly one attempt. Set HttpTransportOptions to configure the built-in transport (an explicit HttpProxyOptions, a custom X509Certificate2Collection trust store, client certificates for mutual TLS, and, on .NET 8, a custom IDnsResolver), or set Transport to a custom ITransport. The two conflict.
Injectable generators#
The runtime asks injectable functions for values it has to invent. Set DefaultValueGenerators for the @default(now()/uuid()/cuid()) seams and the envelope timestamp, and IdempotencyKeyGenerator for minted keys:
var options = new RepostClientOptions
{
IdempotencyKeyGenerator = () => Guid.NewGuid().ToString(),
};Now() is snapshotted once per send, so the envelope timestamp and any @default(now()) field in the same event always match. The default idempotency-key generator is Guid.NewGuid().ToString(), and the default value generators are the system implementations. TimeProvider (deadlines, retry pacing, and Retry-After evaluation) and RetryEntropy (CSPRNG-backed jitter) are injectable too; Testing covers the deterministic implementations that ship in Repost.Client.Testing.
Dependency injection#
The Repost.Client.DependencyInjection package registers RepostClientOptions with the options pattern and binds it from IConfiguration. Scalar options bind by name (ApiKey, BaseUri, the TimeSpan timeouts, MaxAttempts, …); the non-scalar options (Transport, Observer, ApiKeyProvider, and the generators) stay code-only through a configure action:
services.AddRepostClient(configuration.GetSection("Repost"));
services.AddRepostClient(options => options.Observer = new MyObserver());