Spec

The spec topic allows a Hex service to serve up schemas such as OpenApi, AsyncApi and a custom format used to generate code.

This functionality can be added to a Benzene message pipeline using the UseSpec middleware extensions. The topic for this should be set to “spec”.

  app.UseBenzeneMessage(benzeneMessageApp => benzeneMessageApp
      .UseSpec("spec")

Making a Spec Request

{
  "topic": "spec",
  "message" : "{\"type\":\"asyncapi\",\"format\":\"json\"}"
}
Field Options
Type “asyncapi”, ”openapi”, ”benzene”
Format “json”, ”yaml”

Example payloads

The benzene format includes a generated example on every request topic and broadcast event — a ready-made payload derived from the request/message schema. Examples are deterministic (the same schema always produces the same example) and respect the validation metadata the spec carries: schema example/default/enum values win when present, string formats (uuid, date-time, date, email, uri) produce format-shaped values, strings are sized within minLength/maxLength, and numbers are clamped into minimum/maximum.

{
  "topic": "tenant:create",
  "request": { "$ref": "#/components/schemas/CreateTenantMessage" },
  "response": { "$ref": "#/components/schemas/TenantDto" },
  "example": { "name": "value", "crn": "value" }
}

Consumers — the Spec UI, code generators, or anyone with curl — can use the example as-is to send a test message to the service. Generation lives in Benzene.Schema.OpenApi.Examples.ExamplePayloadBuilder.

Message endpoint advertisement

When the service exposes a BenzeneMessage-over-HTTP endpoint (UseBenzeneMessage — see Payload Testing), the benzene format advertises it as an optional top-level messageEndpoint field:

{ "openapi": "3.0.1", "info": { }, "messageEndpoint": "/benzene-message", "requests": [ ] }

Consumers feature-detect send capability on this field — no field means the service accepts messages only through its normal transports.

Transport advertisement

The benzene format also advertises every transport the service is wired to receive messages over as an optional top-level transports field — sourced from every registered Benzene.Abstractions.MessageHandlers.Info.ITransportInfo at spec-build time (e.g. "sqs", "kafka", "http"), written only when at least one is registered:

{ "openapi": "3.0.1", "info": { }, "transports": ["http", "sqs"], "requests": [ ] }

This is document-level, not per-topic: any wired non-HTTP transport can reach any registered topic (Benzene's topic routing has no per-topic transport filtering), so a per-topic list would just repeat this same array on every request/event. HTTP is the one exception — a topic's actual HTTP reachability is still its own per-topic httpMappings, which requires an explicit [HttpEndpoint] attribute per handler and is unaffected by this field. Both Spec UI and Mesh UI render this as a chip row.