> ## Documentation Index
> Fetch the complete documentation index at: https://repost.sh/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure the C# Client

> RepostClientOptions, credential and endpoint precedence, timeouts and retries with production defaults, and the injectable transport, clock, and generators.

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

```csharp theme={"languages":{"custom":["/languages/repost.json"]}}
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, 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](/docs/send/csharp/reliability#bounded-admission). |
| `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:

```csharp theme={"languages":{"custom":["/languages/repost.json"]}}
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](/docs/send/csharp/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`, …); non-scalar options — `Transport`, `Observer`, `ApiKeyProvider`, and the generators — stay code-only through a configure action:

```csharp theme={"languages":{"custom":["/languages/repost.json"]}}
services.AddRepostClient(configuration.GetSection("Repost"));
services.AddRepostClient(options => options.Observer = new MyObserver());
```

## Continue

<Columns cols={3} className="gap-y-4">
  <Card title="Reliability" icon="shield-check" href="/docs/send/csharp/reliability" cta="Outcomes" arrow="true">
    Retries, idempotency, the delivery states, and the exception taxonomy.
  </Card>

  <Card title="Testing" icon="flask-conical" href="/docs/send/csharp/testing" cta="Test" arrow="true">
    The stub transport and deterministic generators in practice.
  </Card>

  <Card title="HTTP API" icon="globe" href="/docs/send/publishing" cta="Raw API" arrow="true">
    The endpoint these options point the client at.
  </Card>
</Columns>
