Skip to content
Peter Van den Bosch edited this page Aug 12, 2025 · 20 revisions

Welcome to the openapi-cloudevents wiki!

Work group meeting reports

ADR: Contract of CloudEvent exchanges

status: resolved

Requirements ~ OpenAPI for REST:

  • documentation for users on event exchanges (endpoints, format, descriptions...)
  • validation of messages

OpenAPI and AsyncAPI

OpenAPI: only for REST (webhooks or pull based)

  • in case of webhooks: either an OpenAPI of the receiver's REST API (POST operation) OR a producer's OpenAPI with webhooks (only in OpenAPI 3.1) or callbacks with an in-API registration of a receiver endpoint URL

AsyncAPI: for any protocol If multiple protocols are supported:

  • in case of structured CloudEvent (i.e. context attributes in JSON format): content definitions in AsyncAPI are shared, bindings are specific
  • if binary representation (i.e. context attributes in protocol-specific headers): definitions in Async are different per protocol because context attributes have protocol-specific prefixes

Generic vs specific contract

Depending on use case, it can be necessary to either:

  • use a generic CloudEvent schema that doesn't specify any restrictions on the actual event messages
  • use a specific schema that constrains the CloudEvent to the specific events provided (i.e. list of event types, data/data_base64)

generic CloudEvent:

  • when there's a generic endpoint supporting multiple different use cases
  • the specific events are documented elsewhere then

Specific schemas:

a) to document the specific events exchanged over generic endpoints

b) when there's an endpoint for events (e.g. REST API) that's constrained to events in a single domain (service) it can be useful then to avoid a split between the event metadata (CloudEvent attribute values, including event types), and the payloads

WG decision

Recommend OpenAPI/AsyncAPI to allow a higher level grouping and lifecycle of all event definitions related to a single domain (service). With event data content defined in an OpenAPI schema (for code generation and reuse of belgif). Individual JSON schemas are not recommended, as these don't describe the context attributes and don't offer an overview of the domain.

Note: when using the CloudEvents' optional dataschema attribute, an a URI fragment could be used to point to a schema defined within an OpenAPI, e.g. :

   "dataschema": "https://example.org/eventCatalog/ssin-update-events.yaml#/components/schemas/SsinUpdateEvent"

ADR: Async message model

status: under discussion

Scope

Elaborate standards to exchange message asynchronously. CloudEvents model only events (notifications of occurrences), but don't describe other async exchanges like operations with replies e.g. consultation, modification, ...

Logical model

Message exchanges

The model is derived from the AsyncAPI model, extended with separate types for MessageExchange, Message and MessageDefinition + CloudEvent.

Blue = API contract

Salmon = technical, protocol-related

Yellow = message model with subtypes

Message

Data belonging together that is exchanged as a whole.

Messages are immutable. During a message exchange, all data that has a functional/business meaning is considered part of the message, even if it's encoded in protocol headers. Technical protocol data, that's only meaningful for the transfer itself, isn't considered part of the message.

MessageDefinition

The definition of messages with the context of an operation, both functional as representation (schemas)

A MessageDefinition is always part of a single operation, though parts of its definitions like schemas may be reused by other instances.

Requirements

  • Protocol-independent message model (though protocol binding can be specific)
  • Routing messages to correct client application(s)
    • routing is expected to be done primarily based on Service and MessageDefinition
  • Within an application:
    • trigger appropriate application logic
    • Be able to link a MessageExchange to corresponding MessageDefinition for correct interpretation and deserialization
  • Best practices resource-oriented API (REST-like), reuse of models used in REST API and CloudEvents where applicable
  • JSON-first for structured data, avoid having to split strings in parts with regexps/templates

Proposition

Expand use of CloudEvent attributes:

  • type as identifier for the MessageDefinition
  • id as message identifier
  • source - same meaning. An API may enforce restrictions on its value. e.g. for a message sent by a client cross-check its value with authenticated user
  • datacontenttype - same meaning
  • specversion - same meaning or different bc of extensions?

Resource-oriented messages

Messages modeled as an execution of an operation on a resource:

  • service as identifier for Service: ``serviceName.vmajorVersion"
  • subject: identifier of the resource ; but can also be modeled as body property for more complex identifiers (e.g. composite parent/child id) or if subject is sensitive (as not to pass it in protocol headers)
    • cloudevent subject is string value
  • type: serviceName.vmajorVersion.resourceType[.resourceSubtype].method[.suffix]
    • method: get, create, update (partialUpdate?), delete or custom method (~ controller)
    • suffix: reply or problemReply (can be extended with API-specific suffix e.g. intermediateReply)
    • TBD: for events; method.suffix = notify.past participle? (e.g notify.canceled)
      • in order to maintain events + commands in same async API
    • resourceType in plural unless a singleton resource (like in REST APIs)
  • relatedto (name TBD) in case of a reply message, with the id of the request message

Note that resourceType or method aren't added as separated properties; bc there's probably no generic processing based on them (similar as the resource types aren't a specific field in REST APIs either).

Problem messages have same representation as REST (TBD - status codes in payload - also needed in header?)

Example: creation of meeting, with a reply The default value of datacontenttype is application/json for CloudEvents JSON Format representation, so can be omitted in some of these examples.

{
  "specversion": "1.0",
  "id": "1",
  "service": "be.belgif.meeting.v3",
  "source": "urn:cbe:enterprisenumber:1234567890",
  "type": "be.belgif.meeting.v3.meetings.create",
  "datacontenttype": "application/json",
  "data": {"...":"..."}
}
{
  "specversion": "1.0",
  "id": "2",
  "service": "be.belgif.meeting.v3",
  "source": "urn:cbe:enterprisenumber:<nsso enterprisenumber>",
  "type": "be.belgif.meeting.v3.meetings.create.reply",
  "datacontenttype": "application/json",
  "relatedto": "1",
  "relatedtosource": "urn:cbe:enterprisenumber:1234567890",
  "subject": "132456",
  "data": {"...":"..."}
}
{
  "specversion": "1.0",
  "id": "987654-1234-1235-4567489798",
  "service": "be.belgif.meeting.v3",
  "source": "urn:cbe:enterprisenumber:<nsso enterprisenumber>",
  "type": "be.belgif.meeting.v3.meetings.create.problemReply",
  "datacontenttype": "application/problem+json",
  "relatedto": "1",
  "relatedtosource": "urn:cbe:enterprisenumber:1234567890",
  "data": {
     "type": "urn:problem-type:belgif:badRequest",
     "href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
     "title": "Bad Request",
     "status": 400,
     "detail":  "The input message is incorrect",
     "instance": "urn:uuid:987654-1234-1235-4567489798",
     "issues": [
       {
        "type": "urn:problem-type:belgif:input-validation:schemaViolation",
        "detail": "examplePropertyWithPattern a2345678901 doesn't match pattern '^\\d{11}$'",
        "in": "body",
        "name": "items[0].examplePropertyWithPattern",
        "value": "a2345678901"
      }
    ]
  }
}

Notification of a creation:

{
  "specversion": "1.0",
  "id": "4",
  "source": "urn:cbe:enterprisenumber:<nsso enterprisenumber>",
  "service": "be.belgif.meeting.v3",
  "type": "be.belgif.meeting.v3.meetings.notify.created",
  "datacontenttype": "application/json",
  "subject": "132456",
  "data": {"...":"..."}
}

Clone this wiki locally