-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Welcome to the openapi-cloudevents wiki!
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) orcallbackswith 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,
bindingsare 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"
status: under discussion
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, ...

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.
- 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
Expand use of CloudEvent attributes:
-
typeas identifier for the MessageDefinition -
idas 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?

Messages modeled as an execution of an operation on a resource:
-
serviceas 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
subjectis string value
- cloudevent
-
type: serviceName.vmajorVersion.resourceType[.resourceSubtype].method[.suffix]- method: get, create, update (partialUpdate?), delete or custom method (~ controller)
-
suffix:
replyorproblemReply(can be extended with API-specific suffix e.g.intermediateReply) - TBD: for events; method.suffix =
notify.past participle? (e.gnotify.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 theidof 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": {"...":"..."}
}