Skip to main content
Version: Next

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: { ... }