Skip to main content
Version: v1.5.0

Export as OpenAPI 3.1 Webhooks

The Hermodr.Schema.OpenApi package produces OpenAPI 3.1 documents whose webhooks section exposes one webhook entry per event type. This makes the event contract accessible to REST-centric tooling (Swagger UI, Stoplight, Postman, code generators such as Kiota) that consumes OpenAPI natively.

When to use OpenAPI vs AsyncAPI​

NeedChoose
REST-centric tooling, Swagger UI, Kiota codegenOpenAPI 3.1
Native async messaging spec, AMQP/Kafka bindings, broker docsAsyncAPI 2.x
Both audiencesExport both from the same schemas

OpenAPI 3.1 has no concept of channel bindings or servers for webhooks; the transport identifier carried by IEventPublishChannelMetadata is preserved on each webhook operation via the x-hermodr-transport extension so the contract remains lossless.

Programmatic export​

Single schema​

using Hermodr;

var schema = EventSchema.FromDataType<OrderPlacedData>();

var writer = new EventSchemaOpenApiWriter(OpenApiFormat.Json);
await using var fs = File.Create("openapi.json");
await writer.WriteToAsync(fs, schema);

Multiple schemas with channel metadata​

var schemas = new EventSchemaDiscovery()
.DiscoverSchemas(typeof(OrderPlacedData).Assembly);

var channels = publisher.GetChannelMetadata(); // from Hermodr.Publisher

var doc = new OpenApiWebhookDocumentBuilder()
.WithTitle("Order Service Events")
.WithVersion("1.0")
.WithSchemas(schemas)
.WithChannels(channels)
.Build();

using var fs = File.Create("openapi.json");
OpenApiDocumentWriter.Serialize(fs, doc, OpenApiFormat.Json);

Auto-discovery from assemblies​

EventSchemaDiscovery scans one or more assemblies for classes annotated with [Event] that carry a DataVersion, and returns a schema for each. Types that use a DataSchema URI instead of a version are skipped, mirroring EventSchemaRegistry.ScanAssembly.

var schemas = new EventSchemaDiscovery()
.DiscoverSchemas(Assembly.Load("MyService.Events"));

Note: discovery uses reflection and is not suitable for trimmed / AOT deployments. The compile-time source generator planned for v1.5.0 (roadmap item 21) will provide an AOT-safe alternative.

Excluding non-transport channels​

Channels whose IEventPublishChannelMetadata.Transport equals EventTransports.Other (Audit Trail, Outbox, Dead-Letter, ...) are excluded from the exported document. They are storage / deferral / recovery layers, not message transports, and do not belong in the public contract.

Lossless transport passthrough​

For transports that have no native OpenAPI representation (e.g. kafka, nats, azureservicebus), the builder emits the transport identifier and the channel Properties bag as operation extensions:

webhooks:
order-placed:
post:
operationId: publish_order-placed
x-hermodr-transport: kafka
x-hermodr-properties:
topic: orders.v1
requestBody: { ... }