The C# client is generated from your .repost schema into a folder in your project: immutable model classes, a Webhooks.<Catalog>.<Member>Async() method tree, and a shared runtime that owns serialization, retries, idempotency, and delivery outcomes. The same schema and wire format back the TypeScript, Go, Python, and Java SDKs, pinned by a cross-language conformance suite.
.NET 8, .NET Framework 4.7.2, or any netstandard2.0 target is supported. The runtime is server-side only: it holds a publish credential and must not ship in a client app.
The runtime package Repost.Client is version 1.0.8 and the schema engine is 0.10.0.
pnpm add -g @repost/cli dotnet add package Repost.Client
repost schema init --language csharpThis scaffolds repost/schema.repost with a starter event and a .env file with an empty REPOST_SEND_API_KEY. A C# generator block sets output, namespace, and clientName, three things the other languages don't need:
generator sdk {
language = "csharp"
output = "../Generated"
namespace = "Contoso.Events"
clientName = "RepostClient"
}
enum Currency {
USD
EUR
}
type Book {
/// A book was created
created
}
model Author {
name String
email String?
}
model Book {
title String
authors Author[]
price Float
currency Currency
subtitle String?
}
event BookCreated {
type @type(Book.created)
data Book
timestamp DateTime
}output is resolved relative to the schema file, so ../Generated writes the client to a Generated/ folder next to your .csproj. Code generation explains each field and the build-time MSBuild alternative.
repost schema migrate dev --name initThis records your schema as a migration and generates the client into Generated/: Client.cs, Descriptors.cs, and Models.cs, plus a copy of the schema and a marker file. The .cs files compile through your project's default glob, so there is nothing to wire up.
Create an environment in the dashboard, copy its publish API key into .env, and deploy your schema:
repost auth login
repost schema migrate deployLoad .env however your app already loads configuration; the runtime reads REPOST_SEND_API_KEY from the environment at send time.
Your first send#
The generated client is IAsyncDisposable. Open it with await using; with no ApiKey set the runtime resolves the credential and endpoint from the environment on the first send:
using Repost.Client;
using Contoso.Events;
await using var repost = new RepostClient(new RepostClientOptions());
SendResult result = await repost.Webhooks.Book.CreatedAsync(new BookCreatedInput
{
CustomerId = "cus_123",
Data = new Book
{
Title = "Dune",
Authors = new[] { new Author { Name = "Frank Herbert" } },
Price = 9.99,
Currency = Currency.Usd,
Subtitle = "A Desert Epic",
},
IdempotencyKey = "book_dune:created",
});
Console.WriteLine(result.Id); // msg_...new RepostClient(...) validates its options and runs the descriptor-version handshake at construction; a missing credential surfaces on the first send. CustomerId names the customer receiving the event. IdempotencyKey is optional; reusing it with the same payload is safe, and Reliability explains when to pass your own. The compiler rejects unknown events, missing required fields, and wrong types before a send ever leaves your process.