From bf76bf5b07dcabdab5d034a83e1d6286fa5d263a Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Wed, 25 Mar 2026 10:09:33 +0100 Subject: [PATCH 1/6] Update event-subscription-template.yaml --- .../event-subscription-template.yaml | 553 +++++++++++------- 1 file changed, 342 insertions(+), 211 deletions(-) diff --git a/artifacts/camara-cloudevents/event-subscription-template.yaml b/artifacts/camara-cloudevents/event-subscription-template.yaml index 17b28d80..b9a67167 100644 --- a/artifacts/camara-cloudevents/event-subscription-template.yaml +++ b/artifacts/camara-cloudevents/event-subscription-template.yaml @@ -5,6 +5,17 @@ info: This file is a template for CAMARA API explicit subscription endpoint and for Notification model. Additional information are provided in [CAMARA API Event Subscription and Notification Guide](https://github.com/camaraproject/Commonalities/blob/main/documentation/CAMARA-API-Event-Subscription-and-Notification-Guide.md). + ## Schema layering + + | Schema | Owner | Responsibility | + |---|---|---| + | `CloudEvent` | Commonalities | CloudEvents 1.0 envelope — no CAMARA-specific constraints | + | `ApiNotificationEvent` | API project | Constrains `type` to `ApiEventType`; owns the discriminator mapping | + | `ApiEventType` | API project | Enum of valid API-specific event type strings | + | `SubscriptionLifecycleEvent` | Commonalities | Constrains `type` to `SubscriptionLifecycleEventType`; owns lifecycle discriminator | + | `SubscriptionLifecycleEventType` | Commonalities | Enum: subscription-started, subscription-updated, subscription-ended | + | `NotificationEvent` | API project | `oneOf` union at the callback endpoint — enumerates valid groups | + Note on event name convention: the event type name MUST follow: ``org.camaraproject...`` Note on ``security`` - ``openId`` scope: The value in this yaml `api-name:event-type1:grant-level` must be replaced accordingly to the format defined in the guideline document. @@ -12,20 +23,20 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html - version: 0.4.0-rc.1 + version: wip x-camara-commonalities: "0.7" - + externalDocs: description: Product documentation at CAMARA url: https://github.com/camaraproject/apiRepository - # {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted. + servers: - url: "{apiRoot}/api-name/vx.y" - # api-name and version should be valued accordingly to the CAMARA API versioning guidelines, e.g. for a version x.y.z, put v0.y for x=0 or just vx for x>0 in the url. variables: apiRoot: default: http://localhost:9091 description: API root, defined by the service provider, e.g. `api.example.com` or `api.example.com/somepath` + tags: - name: Subscription description: Operations to manage event subscriptions on event-type event @@ -58,7 +69,7 @@ paths: description: | Important: this endpoint is to be implemented by the API consumer. The apiName server will call this endpoint whenever a apiName event occurs. - `operationId` value will have to be replaced accordingly with WG API specific semantic + `operationId` value will have to be replaced accordingly with WG API specific semantic. operationId: postNotification parameters: - $ref: "#/components/parameters/x-correlator" @@ -67,7 +78,7 @@ paths: content: application/cloudevents+json: schema: - $ref: "#/components/schemas/CloudEvent" + $ref: "#/components/schemas/NotificationEvent" responses: "204": description: Successful notification @@ -119,6 +130,7 @@ paths: $ref: "#/components/responses/CreateSubscriptionUnprocessableEntity422" "429": $ref: "#/components/responses/Generic429" + get: tags: - Subscription @@ -150,6 +162,7 @@ paths: $ref: "#/components/responses/Generic401" "403": $ref: "#/components/responses/Generic403" + /subscriptions/{subscriptionId}: get: tags: @@ -181,6 +194,7 @@ paths: $ref: "#/components/responses/Generic403" "404": $ref: "#/components/responses/Generic404" + delete: tags: - Subscription @@ -216,6 +230,7 @@ paths: $ref: "#/components/responses/Generic403" "404": $ref: "#/components/responses/Generic404" + components: securitySchemes: openId: @@ -225,6 +240,7 @@ components: type: http scheme: bearer bearerFormat: "{$request.body#/sinkCredential.credentialType}" + parameters: SubscriptionId: name: subscriptionId @@ -239,41 +255,236 @@ components: description: Correlation id for the different services schema: $ref: "#/components/schemas/XCorrelator" + headers: x-correlator: description: Correlation id for the different services schema: $ref: "#/components/schemas/XCorrelator" + schemas: - ErrorInfo: + + # ───────────────────────────────────────────────────────────────────────── + # Layer 0 — CloudEvents 1.0 envelope (Commonalities-owned, never modified) + # + # Knows nothing about CAMARA event types, data payloads, or discriminator + # mappings. Any CAMARA API that needs to send a notification starts here. + # This schema MUST NOT be modified regardless of how many APIs or event + # types are added to the platform. + # ───────────────────────────────────────────────────────────────────────── + + CloudEvent: type: object - description: A structured error response providing details about a failed request, including the HTTP status code, an error code, and a human-readable message + description: | + CloudEvents 1.0 specification envelope. + This schema is the stable base for all CAMARA event notifications. + It imposes no constraints on `type` values or `data` structure — + those concerns belong to the API-specific and lifecycle group schemas. required: - - status - - code - - message + - id + - source + - specversion + - type + - time properties: - status: - type: integer - format: int32 - minimum: 100 - maximum: 599 - description: HTTP response status code - code: + id: type: string - maxLength: 96 - description: A human-readable code to describe the error - message: + maxLength: 256 + description: Identifier of this event, unique within the source context. + source: + $ref: "#/components/schemas/Source" + specversion: type: string - maxLength: 512 - description: A human-readable description of what the event represents + description: Version of the specification to which this event conforms. + enum: + - "1.0" + type: + type: string + description: | + Identifies the event type. CAMARA APIs use reverse-DNS notation: + org.camaraproject... + The api-name segment makes each type globally unique across API groups. + datacontenttype: + type: string + description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' + enum: + - application/json + data: + type: object + description: Event details payload. Structure is defined by each concrete event schema. + time: + $ref: "#/components/schemas/DateTime" - XCorrelator: + # ───────────────────────────────────────────────────────────────────────── + # Layer 1a — API-specific event group (API project-owned) + # + # Extends CloudEvent via allOf and does exactly two things: + # 1. Constrains `type` to its own ApiEventType enum + # 2. Owns the discriminator mapping from each enum value to a concrete schema + # + # Adding a new event type requires only: adding a value to ApiEventType and + # adding a discriminator mapping entry here. CloudEvent is never touched. + # ───────────────────────────────────────────────────────────────────────── + + ApiNotificationEvent: + description: | + API-specific notification event group. + Extends the CloudEvent envelope and constrains `type` to the set of + event types defined by this API project. + Adding a new event type only requires updating ApiEventType and the + discriminator mapping below — the CloudEvent base never changes. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/ApiEventType" + discriminator: + propertyName: type + mapping: + org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" + org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" + + ApiEventType: type: string - description: Correlator string, UUID format recommended but any string matching the pattern can be used - pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ - maxLength: 256 - example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" + description: | + Enum of API-specific event type strings for this API project. + The reverse-DNS prefix org.camaraproject. makes each value + globally unique, so two different API groups can independently define + identically-named event types without any collision risk. + enum: + - org.camaraproject.api-name.v0.event-type1 + - org.camaraproject.api-name.v0.event-type2 + + # ───────────────────────────────────────────────────────────────────────── + # Layer 1b — Subscription lifecycle event group (Commonalities-owned) + # + # Common to every CAMARA API that supports subscriptions. + # Extends CloudEvent via allOf, constrains `type` to lifecycle values, + # and owns the lifecycle discriminator mapping. + # + # API projects reference this group via NotificationEvent but never modify it. + # In a split-file layout this schema lives in CAMARA_Events_common.yaml. + # ───────────────────────────────────────────────────────────────────────── + + SubscriptionLifecycleEvent: + description: | + Subscription lifecycle event group, common to all CAMARA APIs that + support explicit subscriptions. + Extends the CloudEvent envelope and constrains `type` to the set of + lifecycle event types managed by Commonalities. + API projects include this group via NotificationEvent.oneOf and must + not modify it. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/SubscriptionLifecycleEventType" + discriminator: + propertyName: type + mapping: + org.camaraproject.api-name.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" + org.camaraproject.api-name.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" + org.camaraproject.api-name.v0.subscription-ended: "#/components/schemas/EventSubscriptionEnded" + + SubscriptionLifecycleEventType: + type: string + description: | + Enum of subscription lifecycle event type strings. + These are managed by Commonalities and are identical across all CAMARA + APIs that support explicit subscriptions. + Kept as a separate named schema so the set of valid lifecycle type + strings can be referenced independently from the discriminated schema. + enum: + - org.camaraproject.api-name.v0.subscription-started + - org.camaraproject.api-name.v0.subscription-updated + - org.camaraproject.api-name.v0.subscription-ended + + # ───────────────────────────────────────────────────────────────────────── + # Layer 2 — Callback union (API project-owned) + # + # oneOf over all valid event groups at the callback endpoint. + # Owns no discriminator and applies no constraints of its own. + # Its only job is to enumerate which groups are valid for this API. + # + # To add a new event group: add it to the oneOf list. That is the only + # change required at this layer. + # ───────────────────────────────────────────────────────────────────────── + + NotificationEvent: + description: | + Union of all valid notification event groups at the callback endpoint. + This schema owns no discriminator — routing within each group is + handled by ApiNotificationEvent and SubscriptionLifecycleEvent + respectively. Its only responsibility is to enumerate which groups + are valid payloads for this API's notification callback. + oneOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + + # ───────────────────────────────────────────────────────────────────────── + # Concrete event schemas — API-specific (API project-owned) + # ───────────────────────────────────────────────────────────────────────── + + EventApiSpecific1: + description: Event structure for event-type1 + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - type: object + properties: + data: + type: object + description: | + Event-specific payload for event-type1. + Replace with the actual data schema for this event type. + + EventApiSpecific2: + description: Event structure for event-type2 + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - type: object + properties: + data: + type: object + description: | + Event-specific payload for event-type2. + Replace with the actual data schema for this event type. + + # ───────────────────────────────────────────────────────────────────────── + # Concrete event schemas — Subscription lifecycle (Commonalities-owned) + # ───────────────────────────────────────────────────────────────────────── + + EventSubscriptionStarted: + description: event structure for subscription started + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionStarted" + + EventSubscriptionUpdated: + description: event structure for subscription updated + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionUpdated" + + EventSubscriptionEnded: + description: event structure for subscription ended + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionEnded" + + # ───────────────────────────────────────────────────────────────────────── + # Subscription management schemas + # ───────────────────────────────────────────────────────────────────────── SubscriptionRequest: description: The request for creating a event-type event subscription @@ -298,12 +509,15 @@ components: types: description: | Camara Event types eligible to be delivered by this subscription. - Note: the maximum number of event types per subscription will be decided at API project level + References ApiEventType (not the full NotificationEvent union) — + subscription requests target API-specific events only; lifecycle + events are server-initiated and cannot be subscribed to directly. + Note: the maximum number of event types per subscription will be decided at API project level. type: array minItems: 1 maxItems: 1 items: - $ref: "#/components/schemas/SubscriptionEventType" + $ref: "#/components/schemas/ApiEventType" config: $ref: "#/components/schemas/Config" discriminator: @@ -325,9 +539,8 @@ components: Config: description: | Implementation-specific configuration parameters needed by the subscription manager for acquiring events. - In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent` - Specific event type attributes must be defined in `subscriptionDetail` - Note: if a request is performed for several event type, all subscribed event will use same `config` parameters. + In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent`. + Specific event type attributes must be defined in `subscriptionDetail`. type: object required: - subscriptionDetail @@ -339,20 +552,19 @@ components: format: date-time maxLength: 64 example: 2023-01-17T13:18:23.682Z - description: The subscription expiration time (in date-time format) requested by the API consumer. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. Up to API project decision to keep it. + description: The subscription expiration time (in date-time format) requested by the API consumer. subscriptionMaxEvents: type: integer format: int32 - description: Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer - Once this number is reached, the subscription ends. Up to API project decision to keep it. + description: Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer. minimum: 1 maximum: 1000000 example: 5 initialEvent: type: boolean description: | - Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is created and current situation reflects event request. - Example: Consumer request Roaming event. If consumer sets initialEvent to true and device is in roaming situation, an event is triggered - Up to API project decision to keep it. + Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is + created and current situation reflects event request. SinkCredential: description: A sink credential provides authentication or authorization information necessary to enable delivery of events to a target. @@ -364,8 +576,7 @@ components: - PLAIN - ACCESSTOKEN - PRIVATE_KEY_JWT - description: | - The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now + description: The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now discriminator: propertyName: credentialType mapping: @@ -374,6 +585,7 @@ components: PRIVATE_KEY_JWT: "#/components/schemas/PrivateKeyJWTCredential" required: - credentialType + PlainCredential: type: object description: A plain credential as a combination of an identifier and a secret. @@ -392,9 +604,10 @@ components: description: The secret might be a password or passphrase. type: string maxLength: 512 + AccessTokenCredential: type: object - description: An access token credential. This type of credential is meant to be used by API Consumers that have limited capabilities to handle authorization requests. + description: An access token credential. allOf: - $ref: "#/components/schemas/SinkCredential" - type: object @@ -407,14 +620,10 @@ components: type: string format: date-time maxLength: 64 - description: | - REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. - In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. - If the access token is a JWT and registered "exp" (Expiration Time) claim is present, the two expiry times should match. - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + description: REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. example: "2023-07-03T12:27:08.312Z" accessTokenType: - description: REQUIRED. Type of the access token (See [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). + description: REQUIRED. Type of the access token (See OAuth 2.0). type: string enum: - bearer @@ -422,38 +631,17 @@ components: - accessToken - accessTokenExpiresUtc - accessTokenType + PrivateKeyJWTCredential: type: object - description: Use PRIVATE_KEY_JWT to get an access token. The authorization server information needed for this type of sink credential (token endpoint, client ID, JWKS URL) is shared upfront between the client and the CAMARA entity. This type of credential is to be used by clients that have an authorization server. + description: Use PRIVATE_KEY_JWT to get an access token. allOf: - $ref: "#/components/schemas/SinkCredential" + CreateSubscriptionDetail: description: The detail of the requested event subscription. type: object - EventTypeNotification: - type: string - description: | - event-type - Event triggered when an event-type event occurred. Several event-type could be defined. - - - subscription-started: Event triggered when the subscription starts - - subscription-updated: Event triggered when the subscription is updated - - subscription-ended: Event triggered when the subscription ends - enum: - - org.camaraproject.api-name.v0.event-type1 - - org.camaraproject.api-name.v0.event-type2 - - org.camaraproject.api-name.v0.subscription-started - - org.camaraproject.api-name.v0.subscription-updated - - org.camaraproject.api-name.v0.subscription-ended - - SubscriptionEventType: - type: string - description: | - event-type that could be subscribed through this subscription. Several event-type could be defined. - enum: - - org.camaraproject.api-name.v0.event-type1 - - org.camaraproject.api-name.v0.event-type2 - Subscription: description: Represents a event-type subscription. type: object @@ -474,14 +662,11 @@ components: description: The address to which events shall be delivered using the selected protocol. example: "https://endpoint.example.com/sink" types: - description: | - Camara Event types eligible to be delivered by this subscription. - Note: the maximum number of event types per subscription will be decided at API project level type: array minItems: 1 maxItems: 1 items: - $ref: "#/components/schemas/SubscriptionEventType" + $ref: "#/components/schemas/ApiEventType" config: $ref: '#/components/schemas/Config' id: @@ -490,27 +675,23 @@ components: type: string format: date-time maxLength: 64 - description: | - Date when the event subscription will begin/began - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + description: Date when the event subscription will begin/began. example: "2023-07-03T12:27:08.312Z" expiresAt: type: string format: date-time maxLength: 64 - description: | - Date when the event subscription will expire. Only provided when `subscriptionExpireTime` is indicated by API client or Telco Operator has specific policy about that. - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + description: Date when the event subscription will expire. example: "2023-07-03T12:27:08.312Z" status: type: string description: |- - Current status of the subscription - Management of Subscription State engine is not mandatory for now. Note not all statuses may be considered to be implemented. Details: - - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but subscription creation process is not finished yet. + Current status of the subscription. Details: + - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but not finished yet. - `ACTIVE`: Subscription creation process is completed. Subscription is fully operative. - - `INACTIVE`: Subscription is temporarily inactive, but its workflow logic is not deleted. - - `EXPIRED`: Subscription is ended (no longer active). This status applies when subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED` event. - - `DELETED`: Subscription is ended as deleted (no longer active). This status applies when subscription information is kept (i.e. subscription workflow is no longer active but its meta-information is kept). + - `INACTIVE`: Subscription is temporarily inactive. + - `EXPIRED`: Subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED`. + - `DELETED`: Subscription is ended as deleted. enum: - ACTIVATION_REQUESTED - ACTIVE @@ -528,7 +709,7 @@ components: KAFKA: '#/components/schemas/ApacheKafkaSubscriptionResponse' SubscriptionAsync: - description: Response for a event-type subscription request managed asynchronously (Creation or Deletion) + description: Response for a event-type subscription request managed asynchronously type: object required: - id @@ -539,95 +720,12 @@ components: SubscriptionId: type: string maxLength: 256 - description: The unique identifier of the subscription in the scope of the subscription manager. When this information is contained within an event notification, it SHALL be referred to as `subscriptionId` as per the Commonalities Event Notification Model. + description: The unique identifier of the subscription in the scope of the subscription manager. example: qs15-h556-rt89-1298 - CloudEvent: - type: object - description: The notification callback content - required: - - id - - source - - specversion - - type - - time - properties: - id: - type: string - maxLength: 256 - description: identifier of this event, that must be unique in the source context. - source: - $ref: "#/components/schemas/Source" - type: - $ref: "#/components/schemas/EventTypeNotification" - specversion: - type: string - description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) - enum: - - "1.0" - datacontenttype: - type: string - description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' - enum: - - application/json - data: - type: object - description: Event details payload described in each CAMARA API and referenced by its type - time: - $ref: "#/components/schemas/DateTime" - discriminator: - propertyName: "type" - mapping: - org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" - org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" - org.camaraproject.api-name.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" - org.camaraproject.api-name.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" - org.camaraproject.api-name.v0.subscription-ended: "#/components/schemas/EventSubscriptionEnded" - - Source: - type: string - format: uri-reference - minLength: 1 - maxLength: 2048 - description: | - Identifies the context in which an event happened - be a non-empty `URI-reference` like: - - URI with a DNS authority: - * https://github.com/cloudevents - * mailto:cncf-wg-serverless@lists.cncf.io - - Universally-unique URN with a UUID: - * urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 - - Application-specific identifier: - * /cloudevents/spec/pull/123 - * 1-555-123-4567 - example: "https://notificationSendServer12.example.com" - - DateTime: - type: string - format: date-time - maxLength: 64 - description: Timestamp of when the occurrence happened. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2018-04-05T17:31:00Z" - - EventApiSpecific1: - description: event structure for event-type event 1 - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - - EventApiSpecific2: - description: event structure for event-type event 2 - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - - EventSubscriptionStarted: - description: event structure for event subscription started - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionStarted" + # ───────────────────────────────────────────────────────────────────────── + # Subscription lifecycle data payloads (Commonalities-owned) + # ───────────────────────────────────────────────────────────────────────── SubscriptionStarted: description: Event detail structure for subscription started event @@ -652,15 +750,6 @@ components: enum: - SUBSCRIPTION_CREATED - EventSubscriptionUpdated: - description: event structure for event subscription updated - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionUpdated" - SubscriptionUpdated: description: Event detail structure for subscription updated event type: object @@ -680,21 +769,12 @@ components: UpdateReason: type: string description: | - - SUBSCRIPTION_ACTIVE - API server transitioned susbcription status to `ACTIVE` - - SUBSCRIPTION_INACTIVE - API server transitioned susbcription status to `INACTIVE` + - SUBSCRIPTION_ACTIVE - API server transitioned subscription status to `ACTIVE` + - SUBSCRIPTION_INACTIVE - API server transitioned subscription status to `INACTIVE` enum: - SUBSCRIPTION_ACTIVE - SUBSCRIPTION_INACTIVE - EventSubscriptionEnded: - description: event structure for event subscription ended - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionEnded" - SubscriptionEnded: description: Event detail structure for subscription ended event type: object @@ -715,9 +795,9 @@ components: type: string description: | - NETWORK_TERMINATED - API server stopped sending notification - - SUBSCRIPTION_EXPIRED - Subscription expire time (optionally set by the requester) has been reached - - MAX_EVENTS_REACHED - Maximum number of events (optionally set by the requester) has been reached - - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential (optionally set by the requester with credential type `ACCESSTOKEN`) expiration time has been reached + - SUBSCRIPTION_EXPIRED - Subscription expire time has been reached + - MAX_EVENTS_REACHED - Maximum number of events has been reached + - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential expiration time has been reached - SUBSCRIPTION_DELETED - Subscription was deleted by the requester enum: - MAX_EVENTS_REACHED @@ -726,6 +806,59 @@ components: - ACCESS_TOKEN_EXPIRED - SUBSCRIPTION_DELETED + # ───────────────────────────────────────────────────────────────────────── + # Common value object schemas + # ───────────────────────────────────────────────────────────────────────── + + ErrorInfo: + type: object + description: A structured error response providing details about a failed request. + required: + - status + - code + - message + properties: + status: + type: integer + format: int32 + minimum: 100 + maximum: 599 + description: HTTP response status code + code: + type: string + maxLength: 96 + description: A human-readable code to describe the error + message: + type: string + maxLength: 512 + description: A human-readable description of what the event represents + + XCorrelator: + type: string + description: Correlator string, UUID format recommended but any string matching the pattern can be used + pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ + maxLength: 256 + example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" + + Source: + type: string + format: uri-reference + minLength: 1 + maxLength: 2048 + description: Identifies the context in which an event happened. + example: "https://notificationSendServer12.example.com" + + DateTime: + type: string + format: date-time + maxLength: 64 + description: Timestamp of when the occurrence happened. It must follow RFC 3339 and must have time zone. + example: "2018-04-05T17:31:00Z" + + # ───────────────────────────────────────────────────────────────────────── + # Protocol-specific subscription schemas + # ───────────────────────────────────────────────────────────────────────── + HTTPSubscriptionRequest: allOf: - $ref: "#/components/schemas/SubscriptionRequest" @@ -747,10 +880,7 @@ components: properties: headers: type: object - description: |- - A set of key/value pairs that is copied into the HTTP request as custom headers. - - NOTE: Use/Applicability of this concept has not been discussed in Commonalities. When required by an API project as an option to meet a UC/Requirement, please generate an issue for Commonalities discussion about it. + description: A set of key/value pairs that is copied into the HTTP request as custom headers. additionalProperties: type: string maxLength: 512 @@ -898,6 +1028,7 @@ components: description: NATS subject required: - subject + responses: CreateSubscriptionBadRequest400: description: Problem with the client request @@ -942,7 +1073,7 @@ components: code: INVALID_PROTOCOL message: Only HTTP is supported GENERIC_400_INVALID_CREDENTIAL: - description: Invalid sink credential type + description: Invalid sink credential type value: status: 400 code: INVALID_CREDENTIAL @@ -1029,7 +1160,7 @@ components: - UNAUTHENTICATED examples: GENERIC_401_UNAUTHENTICATED: - description: Request cannot be authenticated and a new authentication is required + description: Request cannot be authenticated value: status: 401 code: UNAUTHENTICATED @@ -1054,11 +1185,11 @@ components: - PERMISSION_DENIED examples: GENERIC_403_PERMISSION_DENIED: - description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + description: Permission denied value: status: 403 code: PERMISSION_DENIED - message: Client does not have sufficient permissions to perform this action. + message: Client does not have sufficient permissions to perform this action. SubscriptionPermissionDenied403: description: Client does not have sufficient permission headers: @@ -1080,7 +1211,7 @@ components: - SUBSCRIPTION_MISMATCH examples: GENERIC_403_PERMISSION_DENIED: - description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + description: Permission denied value: status: 403 code: PERMISSION_DENIED @@ -1137,7 +1268,7 @@ components: - ALREADY_EXISTS examples: GENERIC_409_ABORTED: - description: Concurreny of processes of the same nature/scope + description: Concurrency of processes of the same nature/scope value: status: 409 code: ABORTED @@ -1168,7 +1299,7 @@ components: - GONE examples: GENERIC_410_GONE: - description: Use in notifications flow to allow API Consumer to indicate that its callback is no longer available + description: Use in notifications flow to indicate callback is no longer available value: status: 410 code: GONE @@ -1205,7 +1336,7 @@ components: code: SERVICE_NOT_APPLICABLE message: The service is not available for the provided identifier. GENERIC_422_MISSING_IDENTIFIER: - description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token + description: An identifier is not included in the request value: status: 422 code: MISSING_IDENTIFIER @@ -1217,7 +1348,7 @@ components: code: UNSUPPORTED_IDENTIFIER message: The identifier provided is not supported. GENERIC_422_UNNECESSARY_IDENTIFIER: - description: An explicit identifier is provided when a device or phone number has already been identified from the access token + description: An explicit identifier is provided when device is already identified from the access token value: status: 422 code: UNNECESSARY_IDENTIFIER @@ -1267,7 +1398,7 @@ components: code: QUOTA_EXCEEDED message: Out of resource quota. GENERIC_429_TOO_MANY_REQUESTS: - description: Access to the API has been temporarily blocked due to rate or spike arrest limits being reached + description: Access to the API has been temporarily blocked due to rate or spike arrest limits value: status: 429 code: TOO_MANY_REQUESTS From abbbc0b89103faa95e51ab171e97122c7a216d78 Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:16:57 +0100 Subject: [PATCH 2/6] Update event-subscription-template.yaml --- .../event-subscription-template.yaml | 623 +++++++++--------- 1 file changed, 301 insertions(+), 322 deletions(-) diff --git a/artifacts/camara-cloudevents/event-subscription-template.yaml b/artifacts/camara-cloudevents/event-subscription-template.yaml index b9a67167..07d666ad 100644 --- a/artifacts/camara-cloudevents/event-subscription-template.yaml +++ b/artifacts/camara-cloudevents/event-subscription-template.yaml @@ -5,17 +5,6 @@ info: This file is a template for CAMARA API explicit subscription endpoint and for Notification model. Additional information are provided in [CAMARA API Event Subscription and Notification Guide](https://github.com/camaraproject/Commonalities/blob/main/documentation/CAMARA-API-Event-Subscription-and-Notification-Guide.md). - ## Schema layering - - | Schema | Owner | Responsibility | - |---|---|---| - | `CloudEvent` | Commonalities | CloudEvents 1.0 envelope — no CAMARA-specific constraints | - | `ApiNotificationEvent` | API project | Constrains `type` to `ApiEventType`; owns the discriminator mapping | - | `ApiEventType` | API project | Enum of valid API-specific event type strings | - | `SubscriptionLifecycleEvent` | Commonalities | Constrains `type` to `SubscriptionLifecycleEventType`; owns lifecycle discriminator | - | `SubscriptionLifecycleEventType` | Commonalities | Enum: subscription-started, subscription-updated, subscription-ended | - | `NotificationEvent` | API project | `oneOf` union at the callback endpoint — enumerates valid groups | - Note on event name convention: the event type name MUST follow: ``org.camaraproject...`` Note on ``security`` - ``openId`` scope: The value in this yaml `api-name:event-type1:grant-level` must be replaced accordingly to the format defined in the guideline document. @@ -29,14 +18,14 @@ info: externalDocs: description: Product documentation at CAMARA url: https://github.com/camaraproject/apiRepository - + # {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted. servers: - url: "{apiRoot}/api-name/vx.y" + # api-name and version should be valued accordingly to the CAMARA API versioning guidelines, e.g. for a version x.y.z, put v0.y for x=0 or just vx for x>0 in the url. variables: apiRoot: default: http://localhost:9091 description: API root, defined by the service provider, e.g. `api.example.com` or `api.example.com/somepath` - tags: - name: Subscription description: Operations to manage event subscriptions on event-type event @@ -69,7 +58,7 @@ paths: description: | Important: this endpoint is to be implemented by the API consumer. The apiName server will call this endpoint whenever a apiName event occurs. - `operationId` value will have to be replaced accordingly with WG API specific semantic. + `operationId` value will have to be replaced accordingly with WG API specific semantic operationId: postNotification parameters: - $ref: "#/components/parameters/x-correlator" @@ -78,7 +67,7 @@ paths: content: application/cloudevents+json: schema: - $ref: "#/components/schemas/NotificationEvent" + $ref: "#/components/schemas/CloudEvent" responses: "204": description: Successful notification @@ -130,7 +119,6 @@ paths: $ref: "#/components/responses/CreateSubscriptionUnprocessableEntity422" "429": $ref: "#/components/responses/Generic429" - get: tags: - Subscription @@ -162,7 +150,6 @@ paths: $ref: "#/components/responses/Generic401" "403": $ref: "#/components/responses/Generic403" - /subscriptions/{subscriptionId}: get: tags: @@ -194,7 +181,6 @@ paths: $ref: "#/components/responses/Generic403" "404": $ref: "#/components/responses/Generic404" - delete: tags: - Subscription @@ -230,7 +216,6 @@ paths: $ref: "#/components/responses/Generic403" "404": $ref: "#/components/responses/Generic404" - components: securitySchemes: openId: @@ -240,7 +225,6 @@ components: type: http scheme: bearer bearerFormat: "{$request.body#/sinkCredential.credentialType}" - parameters: SubscriptionId: name: subscriptionId @@ -255,236 +239,41 @@ components: description: Correlation id for the different services schema: $ref: "#/components/schemas/XCorrelator" - headers: x-correlator: description: Correlation id for the different services schema: $ref: "#/components/schemas/XCorrelator" - schemas: - - # ───────────────────────────────────────────────────────────────────────── - # Layer 0 — CloudEvents 1.0 envelope (Commonalities-owned, never modified) - # - # Knows nothing about CAMARA event types, data payloads, or discriminator - # mappings. Any CAMARA API that needs to send a notification starts here. - # This schema MUST NOT be modified regardless of how many APIs or event - # types are added to the platform. - # ───────────────────────────────────────────────────────────────────────── - - CloudEvent: + ErrorInfo: type: object - description: | - CloudEvents 1.0 specification envelope. - This schema is the stable base for all CAMARA event notifications. - It imposes no constraints on `type` values or `data` structure — - those concerns belong to the API-specific and lifecycle group schemas. + description: A structured error response providing details about a failed request, including the HTTP status code, an error code, and a human-readable message required: - - id - - source - - specversion - - type - - time + - status + - code + - message properties: - id: - type: string - maxLength: 256 - description: Identifier of this event, unique within the source context. - source: - $ref: "#/components/schemas/Source" - specversion: - type: string - description: Version of the specification to which this event conforms. - enum: - - "1.0" - type: + status: + type: integer + format: int32 + minimum: 100 + maximum: 599 + description: HTTP response status code + code: type: string - description: | - Identifies the event type. CAMARA APIs use reverse-DNS notation: - org.camaraproject... - The api-name segment makes each type globally unique across API groups. - datacontenttype: + maxLength: 96 + description: A human-readable code to describe the error + message: type: string - description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' - enum: - - application/json - data: - type: object - description: Event details payload. Structure is defined by each concrete event schema. - time: - $ref: "#/components/schemas/DateTime" - - # ───────────────────────────────────────────────────────────────────────── - # Layer 1a — API-specific event group (API project-owned) - # - # Extends CloudEvent via allOf and does exactly two things: - # 1. Constrains `type` to its own ApiEventType enum - # 2. Owns the discriminator mapping from each enum value to a concrete schema - # - # Adding a new event type requires only: adding a value to ApiEventType and - # adding a discriminator mapping entry here. CloudEvent is never touched. - # ───────────────────────────────────────────────────────────────────────── - - ApiNotificationEvent: - description: | - API-specific notification event group. - Extends the CloudEvent envelope and constrains `type` to the set of - event types defined by this API project. - Adding a new event type only requires updating ApiEventType and the - discriminator mapping below — the CloudEvent base never changes. - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - type: - $ref: "#/components/schemas/ApiEventType" - discriminator: - propertyName: type - mapping: - org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" - org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" - - ApiEventType: - type: string - description: | - Enum of API-specific event type strings for this API project. - The reverse-DNS prefix org.camaraproject. makes each value - globally unique, so two different API groups can independently define - identically-named event types without any collision risk. - enum: - - org.camaraproject.api-name.v0.event-type1 - - org.camaraproject.api-name.v0.event-type2 - - # ───────────────────────────────────────────────────────────────────────── - # Layer 1b — Subscription lifecycle event group (Commonalities-owned) - # - # Common to every CAMARA API that supports subscriptions. - # Extends CloudEvent via allOf, constrains `type` to lifecycle values, - # and owns the lifecycle discriminator mapping. - # - # API projects reference this group via NotificationEvent but never modify it. - # In a split-file layout this schema lives in CAMARA_Events_common.yaml. - # ───────────────────────────────────────────────────────────────────────── - - SubscriptionLifecycleEvent: - description: | - Subscription lifecycle event group, common to all CAMARA APIs that - support explicit subscriptions. - Extends the CloudEvent envelope and constrains `type` to the set of - lifecycle event types managed by Commonalities. - API projects include this group via NotificationEvent.oneOf and must - not modify it. - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - type: - $ref: "#/components/schemas/SubscriptionLifecycleEventType" - discriminator: - propertyName: type - mapping: - org.camaraproject.api-name.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" - org.camaraproject.api-name.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" - org.camaraproject.api-name.v0.subscription-ended: "#/components/schemas/EventSubscriptionEnded" + maxLength: 512 + description: A human-readable description of what the event represents - SubscriptionLifecycleEventType: + XCorrelator: type: string - description: | - Enum of subscription lifecycle event type strings. - These are managed by Commonalities and are identical across all CAMARA - APIs that support explicit subscriptions. - Kept as a separate named schema so the set of valid lifecycle type - strings can be referenced independently from the discriminated schema. - enum: - - org.camaraproject.api-name.v0.subscription-started - - org.camaraproject.api-name.v0.subscription-updated - - org.camaraproject.api-name.v0.subscription-ended - - # ───────────────────────────────────────────────────────────────────────── - # Layer 2 — Callback union (API project-owned) - # - # oneOf over all valid event groups at the callback endpoint. - # Owns no discriminator and applies no constraints of its own. - # Its only job is to enumerate which groups are valid for this API. - # - # To add a new event group: add it to the oneOf list. That is the only - # change required at this layer. - # ───────────────────────────────────────────────────────────────────────── - - NotificationEvent: - description: | - Union of all valid notification event groups at the callback endpoint. - This schema owns no discriminator — routing within each group is - handled by ApiNotificationEvent and SubscriptionLifecycleEvent - respectively. Its only responsibility is to enumerate which groups - are valid payloads for this API's notification callback. - oneOf: - - $ref: "#/components/schemas/ApiNotificationEvent" - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - # ───────────────────────────────────────────────────────────────────────── - # Concrete event schemas — API-specific (API project-owned) - # ───────────────────────────────────────────────────────────────────────── - - EventApiSpecific1: - description: Event structure for event-type1 - allOf: - - $ref: "#/components/schemas/ApiNotificationEvent" - - type: object - properties: - data: - type: object - description: | - Event-specific payload for event-type1. - Replace with the actual data schema for this event type. - - EventApiSpecific2: - description: Event structure for event-type2 - allOf: - - $ref: "#/components/schemas/ApiNotificationEvent" - - type: object - properties: - data: - type: object - description: | - Event-specific payload for event-type2. - Replace with the actual data schema for this event type. - - # ───────────────────────────────────────────────────────────────────────── - # Concrete event schemas — Subscription lifecycle (Commonalities-owned) - # ───────────────────────────────────────────────────────────────────────── - - EventSubscriptionStarted: - description: event structure for subscription started - allOf: - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionStarted" - - EventSubscriptionUpdated: - description: event structure for subscription updated - allOf: - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionUpdated" - - EventSubscriptionEnded: - description: event structure for subscription ended - allOf: - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionEnded" - - # ───────────────────────────────────────────────────────────────────────── - # Subscription management schemas - # ───────────────────────────────────────────────────────────────────────── + description: Correlator string, UUID format recommended but any string matching the pattern can be used + pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ + maxLength: 256 + example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" SubscriptionRequest: description: The request for creating a event-type event subscription @@ -539,8 +328,9 @@ components: Config: description: | Implementation-specific configuration parameters needed by the subscription manager for acquiring events. - In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent`. + In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent` Specific event type attributes must be defined in `subscriptionDetail`. + Note: if a request is performed for several event types, all subscribed events will use same `config` parameters. type: object required: - subscriptionDetail @@ -552,19 +342,20 @@ components: format: date-time maxLength: 64 example: 2023-01-17T13:18:23.682Z - description: The subscription expiration time (in date-time format) requested by the API consumer. + description: The subscription expiration time (in date-time format) requested by the API consumer. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. Up to API project decision to keep it. subscriptionMaxEvents: type: integer format: int32 - description: Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer. + description: Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer - Once this number is reached, the subscription ends. Up to API project decision to keep it. minimum: 1 maximum: 1000000 example: 5 initialEvent: type: boolean description: | - Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is - created and current situation reflects event request. + Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is created and current situation reflects event request. + Example: Consumer request Roaming event. If consumer sets initialEvent to true and device is in roaming situation, an event is triggered + Up to API project decision to keep it. SinkCredential: description: A sink credential provides authentication or authorization information necessary to enable delivery of events to a target. @@ -576,7 +367,8 @@ components: - PLAIN - ACCESSTOKEN - PRIVATE_KEY_JWT - description: The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now + description: | + The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now discriminator: propertyName: credentialType mapping: @@ -585,7 +377,6 @@ components: PRIVATE_KEY_JWT: "#/components/schemas/PrivateKeyJWTCredential" required: - credentialType - PlainCredential: type: object description: A plain credential as a combination of an identifier and a secret. @@ -604,10 +395,9 @@ components: description: The secret might be a password or passphrase. type: string maxLength: 512 - AccessTokenCredential: type: object - description: An access token credential. + description: An access token credential. This type of credential is meant to be used by API Consumers that have limited capabilities to handle authorization requests. allOf: - $ref: "#/components/schemas/SinkCredential" - type: object @@ -620,10 +410,14 @@ components: type: string format: date-time maxLength: 64 - description: REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. + description: | + REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. + In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. + If the access token is a JWT and registered "exp" (Expiration Time) claim is present, the two expiry times should match. + It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. example: "2023-07-03T12:27:08.312Z" accessTokenType: - description: REQUIRED. Type of the access token (See OAuth 2.0). + description: REQUIRED. Type of the access token (See [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). type: string enum: - bearer @@ -631,17 +425,71 @@ components: - accessToken - accessTokenExpiresUtc - accessTokenType - PrivateKeyJWTCredential: type: object - description: Use PRIVATE_KEY_JWT to get an access token. + description: Use PRIVATE_KEY_JWT to get an access token. The authorization server information needed for this type of sink credential (token endpoint, client ID, JWKS URL) is shared upfront between the client and the CAMARA entity. This type of credential is to be used by clients that have an authorization server. allOf: - $ref: "#/components/schemas/SinkCredential" - CreateSubscriptionDetail: description: The detail of the requested event subscription. type: object + ApiEventType: + type: string + description: | + Enum of API-specific event type strings for this API project. + The reverse-DNS prefix org.camaraproject. makes each value + globally unique, so two different API groups can independently define + identically-named event types without any collision risk. + enum: + - org.camaraproject.api-name.v0.event-type1 + - org.camaraproject.api-name.v0.event-type2 + + # ───────────────────────────────────────────────────────────────────────── + # Subscription lifecycle event group (Commonalities-owned) + # + # Common to every CAMARA API that supports subscriptions. + # Extends CloudEvent via allOf, constrains `type` to lifecycle values, + # and owns the lifecycle discriminator mapping. + # + # API projects reference this group via NotificationEvent but never modify it. + # In a split-file layout this schema lives in CAMARA_Events_common.yaml. + # ───────────────────────────────────────────────────────────────────────── + + SubscriptionLifecycleEvent: + description: | + Subscription lifecycle event group, common to all CAMARA APIs that + support explicit subscriptions. + Extends the CloudEvent envelope and constrains `type` to the set of + lifecycle event types managed by Commonalities. + API projects include this group via NotificationEvent.oneOf and must + not modify it. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/SubscriptionLifecycleEventType" + discriminator: + propertyName: type + mapping: + org.camaraproject.api-name.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" + org.camaraproject.api-name.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" + org.camaraproject.api-name.v0.subscription-ended: "#/components/schemas/EventSubscriptionEnded" + + SubscriptionLifecycleEventType: + type: string + description: | + Enum of subscription lifecycle event type strings. + These are managed by Commonalities and are identical across all CAMARA + APIs that support explicit subscriptions. + Kept as a separate named schema so the set of valid lifecycle type + strings can be referenced independently from the discriminated schema. + enum: + - org.camaraproject.api-name.v0.subscription-started + - org.camaraproject.api-name.v0.subscription-updated + - org.camaraproject.api-name.v0.subscription-ended + Subscription: description: Represents a event-type subscription. type: object @@ -662,6 +510,9 @@ components: description: The address to which events shall be delivered using the selected protocol. example: "https://endpoint.example.com/sink" types: + description: | + Camara Event types eligible to be delivered by this subscription. + Note: the maximum number of event types per subscription will be decided at API project level type: array minItems: 1 maxItems: 1 @@ -675,23 +526,27 @@ components: type: string format: date-time maxLength: 64 - description: Date when the event subscription will begin/began. + description: | + Date when the event subscription will begin/began + It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. example: "2023-07-03T12:27:08.312Z" expiresAt: type: string format: date-time maxLength: 64 - description: Date when the event subscription will expire. + description: | + Date when the event subscription will expire. Only provided when `subscriptionExpireTime` is indicated by API client or Telco Operator has specific policy about that. + It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. example: "2023-07-03T12:27:08.312Z" status: type: string description: |- - Current status of the subscription. Details: - - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but not finished yet. + Current status of the subscription - Management of Subscription State engine is not mandatory for now. Note not all statuses may be considered to be implemented. Details: + - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but subscription creation process is not finished yet. - `ACTIVE`: Subscription creation process is completed. Subscription is fully operative. - - `INACTIVE`: Subscription is temporarily inactive. - - `EXPIRED`: Subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED`. - - `DELETED`: Subscription is ended as deleted. + - `INACTIVE`: Subscription is temporarily inactive, but its workflow logic is not deleted. + - `EXPIRED`: Subscription is ended (no longer active). This status applies when subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED` event. + - `DELETED`: Subscription is ended as deleted (no longer active). This status applies when subscription information is kept (i.e. subscription workflow is no longer active but its meta-information is kept). enum: - ACTIVATION_REQUESTED - ACTIVE @@ -709,7 +564,7 @@ components: KAFKA: '#/components/schemas/ApacheKafkaSubscriptionResponse' SubscriptionAsync: - description: Response for a event-type subscription request managed asynchronously + description: Response for a event-type subscription request managed asynchronously (Creation or Deletion) type: object required: - id @@ -720,13 +575,166 @@ components: SubscriptionId: type: string maxLength: 256 - description: The unique identifier of the subscription in the scope of the subscription manager. + description: The unique identifier of the subscription in the scope of the subscription manager. When this information is contained within an event notification, it SHALL be referred to as `subscriptionId` as per the Commonalities Event Notification Model. example: qs15-h556-rt89-1298 + CloudEvent: + type: object + description: | + CloudEvents 1.0 specification envelope. + This schema is the stable base for all CAMARA event notifications. + It imposes no constraints on `type` values or `data` structure — + those concerns belong to the API-specific and lifecycle group schemas. + required: + - id + - source + - specversion + - type + - time + properties: + id: + type: string + maxLength: 256 + description: Identifier of this event, unique within the source context. + source: + $ref: "#/components/schemas/Source" + type: + type: string + description: | + Identifies the event type. CAMARA APIs use reverse-DNS notation: + org.camaraproject... + The api-name segment makes each type globally unique across API groups. + specversion: + type: string + description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) + enum: + - "1.0" + datacontenttype: + type: string + description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' + enum: + - application/json + data: + type: object + description: Event details payload. Structure is defined by each concrete event schema. + time: + $ref: "#/components/schemas/DateTime" + # ───────────────────────────────────────────────────────────────────────── + # Extends CloudEvent via allOf and does exactly two things: + # 1. Constrains `type` to its own ApiEventType enum + # 2. Owns the discriminator mapping from each enum value to a concrete schema + # + # Adding a new event type requires only: adding a value to ApiEventType and + # adding a discriminator mapping entry here. CloudEvent is never touched. + # ───────────────────────────────────────────────────────────────────────── + + ApiNotificationEvent: + description: | + API-specific notification event group. + Extends the CloudEvent envelope and constrains `type` to the set of + event types defined by this API project. + Adding a new event type only requires updating ApiEventType and the + discriminator mapping below — the CloudEvent base never changes. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/ApiEventType" + discriminator: + propertyName: "type" + mapping: + org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" + org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" + + + Source: + type: string + format: uri-reference + minLength: 1 + maxLength: 2048 + description: | + Identifies the context in which an event happened - be a non-empty `URI-reference` like: + - URI with a DNS authority: + * https://github.com/cloudevents + * mailto:cncf-wg-serverless@lists.cncf.io + - Universally-unique URN with a UUID: + * urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 + - Application-specific identifier: + * /cloudevents/spec/pull/123 + * 1-555-123-4567 + example: "https://notificationSendServer12.example.com" + + DateTime: + type: string + format: date-time + maxLength: 64 + description: Timestamp of when the occurrence happened. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + example: "2018-04-05T17:31:00Z" + + # ───────────────────────────────────────────────────────────────────────── + # Layer 2 — Callback union (API project-owned) + # + # oneOf over all valid event groups at the callback endpoint. + # Owns no discriminator and applies no constraints of its own. + # Its only job is to enumerate which groups are valid for this API. + # + # To add a new event group: add it to the oneOf list. That is the only + # change required at this layer. + # ───────────────────────────────────────────────────────────────────────── + + NotificationEvent: + description: | + Union of all valid notification event groups at the callback endpoint. + This schema owns no discriminator — routing within each group is + handled by ApiNotificationEvent and SubscriptionLifecycleEvent + respectively. Its only responsibility is to enumerate which groups + are valid payloads for this API's notification callback. + oneOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + # ───────────────────────────────────────────────────────────────────────── - # Subscription lifecycle data payloads (Commonalities-owned) + # Concrete event schemas — API-specific (API project-owned) # ───────────────────────────────────────────────────────────────────────── + EventApiSpecific1: + description: event structure for event-type event 1 + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - type: object + properties: + data: + type: object + description: | + Event-specific payload for event-type1. + Replace with the actual data schema for this event type. + + EventApiSpecific2: + description: event structure for event-type event 2 + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - type: object + properties: + data: + type: object + description: | + Event-specific payload for event-type2. + Replace with the actual data schema for this event type. + + # ───────────────────────────────────────────────────────────────────────── + # Concrete event schemas — Subscription lifecycle (Commonalities-owned) + # ───────────────────────────────────────────────────────────────────────── + + EventSubscriptionStarted: + description: event structure for event subscription started + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionStarted" + SubscriptionStarted: description: Event detail structure for subscription started event type: object @@ -750,6 +758,15 @@ components: enum: - SUBSCRIPTION_CREATED + EventSubscriptionUpdated: + description: event structure for event subscription updated + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionUpdated" + SubscriptionUpdated: description: Event detail structure for subscription updated event type: object @@ -775,6 +792,15 @@ components: - SUBSCRIPTION_ACTIVE - SUBSCRIPTION_INACTIVE + EventSubscriptionEnded: + description: event structure for event subscription ended + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionEnded" + SubscriptionEnded: description: Event detail structure for subscription ended event type: object @@ -795,9 +821,9 @@ components: type: string description: | - NETWORK_TERMINATED - API server stopped sending notification - - SUBSCRIPTION_EXPIRED - Subscription expire time has been reached - - MAX_EVENTS_REACHED - Maximum number of events has been reached - - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential expiration time has been reached + - SUBSCRIPTION_EXPIRED - Subscription expire time (optionally set by the requester) has been reached + - MAX_EVENTS_REACHED - Maximum number of events (optionally set by the requester) has been reached + - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential (optionally set by the requester with credential type `ACCESSTOKEN`) expiration time has been reached - SUBSCRIPTION_DELETED - Subscription was deleted by the requester enum: - MAX_EVENTS_REACHED @@ -805,56 +831,6 @@ components: - SUBSCRIPTION_EXPIRED - ACCESS_TOKEN_EXPIRED - SUBSCRIPTION_DELETED - - # ───────────────────────────────────────────────────────────────────────── - # Common value object schemas - # ───────────────────────────────────────────────────────────────────────── - - ErrorInfo: - type: object - description: A structured error response providing details about a failed request. - required: - - status - - code - - message - properties: - status: - type: integer - format: int32 - minimum: 100 - maximum: 599 - description: HTTP response status code - code: - type: string - maxLength: 96 - description: A human-readable code to describe the error - message: - type: string - maxLength: 512 - description: A human-readable description of what the event represents - - XCorrelator: - type: string - description: Correlator string, UUID format recommended but any string matching the pattern can be used - pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ - maxLength: 256 - example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" - - Source: - type: string - format: uri-reference - minLength: 1 - maxLength: 2048 - description: Identifies the context in which an event happened. - example: "https://notificationSendServer12.example.com" - - DateTime: - type: string - format: date-time - maxLength: 64 - description: Timestamp of when the occurrence happened. It must follow RFC 3339 and must have time zone. - example: "2018-04-05T17:31:00Z" - # ───────────────────────────────────────────────────────────────────────── # Protocol-specific subscription schemas # ───────────────────────────────────────────────────────────────────────── @@ -880,7 +856,10 @@ components: properties: headers: type: object - description: A set of key/value pairs that is copied into the HTTP request as custom headers. + description: |- + A set of key/value pairs that is copied into the HTTP request as custom headers. + + NOTE: Use/Applicability of this concept has not been discussed in Commonalities. When required by an API project as an option to meet a UC/Requirement, please generate an issue for Commonalities discussion about it. additionalProperties: type: string maxLength: 512 @@ -1160,7 +1139,7 @@ components: - UNAUTHENTICATED examples: GENERIC_401_UNAUTHENTICATED: - description: Request cannot be authenticated + description: Request cannot be authenticated and a new authentication is required value: status: 401 code: UNAUTHENTICATED @@ -1185,7 +1164,7 @@ components: - PERMISSION_DENIED examples: GENERIC_403_PERMISSION_DENIED: - description: Permission denied + description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security value: status: 403 code: PERMISSION_DENIED @@ -1211,7 +1190,7 @@ components: - SUBSCRIPTION_MISMATCH examples: GENERIC_403_PERMISSION_DENIED: - description: Permission denied + description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security value: status: 403 code: PERMISSION_DENIED @@ -1299,7 +1278,7 @@ components: - GONE examples: GENERIC_410_GONE: - description: Use in notifications flow to indicate callback is no longer available + description: Use in notifications flow to allow API Consumer to indicate that its callback is no longer available value: status: 410 code: GONE @@ -1336,7 +1315,7 @@ components: code: SERVICE_NOT_APPLICABLE message: The service is not available for the provided identifier. GENERIC_422_MISSING_IDENTIFIER: - description: An identifier is not included in the request + description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token value: status: 422 code: MISSING_IDENTIFIER @@ -1348,7 +1327,7 @@ components: code: UNSUPPORTED_IDENTIFIER message: The identifier provided is not supported. GENERIC_422_UNNECESSARY_IDENTIFIER: - description: An explicit identifier is provided when device is already identified from the access token + description: An explicit identifier is provided when a device or phone number has already been identified from the access token value: status: 422 code: UNNECESSARY_IDENTIFIER @@ -1398,7 +1377,7 @@ components: code: QUOTA_EXCEEDED message: Out of resource quota. GENERIC_429_TOO_MANY_REQUESTS: - description: Access to the API has been temporarily blocked due to rate or spike arrest limits + description: Access to the API has been temporarily blocked due to rate or spike arrest limits being reached value: status: 429 code: TOO_MANY_REQUESTS From 46ab3c57a3a8f457666c4b735b406e9859099e27 Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Wed, 25 Mar 2026 15:41:04 +0100 Subject: [PATCH 3/6] Update event-subscription-template.yaml --- .../camara-cloudevents/event-subscription-template.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/artifacts/camara-cloudevents/event-subscription-template.yaml b/artifacts/camara-cloudevents/event-subscription-template.yaml index 07d666ad..0b192d35 100644 --- a/artifacts/camara-cloudevents/event-subscription-template.yaml +++ b/artifacts/camara-cloudevents/event-subscription-template.yaml @@ -67,7 +67,7 @@ paths: content: application/cloudevents+json: schema: - $ref: "#/components/schemas/CloudEvent" + $ref: "#/components/schemas/NotificationEvent" responses: "204": description: Successful notification @@ -462,8 +462,6 @@ components: support explicit subscriptions. Extends the CloudEvent envelope and constrains `type` to the set of lifecycle event types managed by Commonalities. - API projects include this group via NotificationEvent.oneOf and must - not modify it. allOf: - $ref: "#/components/schemas/CloudEvent" - type: object @@ -673,7 +671,7 @@ components: example: "2018-04-05T17:31:00Z" # ───────────────────────────────────────────────────────────────────────── - # Layer 2 — Callback union (API project-owned) + # Callback union (API project-owned) # # oneOf over all valid event groups at the callback endpoint. # Owns no discriminator and applies no constraints of its own. From a9b839f59ffbeddb18f4a7d61b72bdc90177d477 Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Wed, 25 Mar 2026 18:03:40 +0100 Subject: [PATCH 4/6] Update event-subscription-template.yaml --- .../event-subscription-template.yaml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/artifacts/camara-cloudevents/event-subscription-template.yaml b/artifacts/camara-cloudevents/event-subscription-template.yaml index 0b192d35..9dcf39d6 100644 --- a/artifacts/camara-cloudevents/event-subscription-template.yaml +++ b/artifacts/camara-cloudevents/event-subscription-template.yaml @@ -221,10 +221,14 @@ components: openId: type: openIdConnect openIdConnectUrl: https://example.com/.well-known/openid-configuration + description: OpenID Connect authentication via discovery metadata. notificationsBearerAuth: type: http scheme: bearer bearerFormat: "{$request.body#/sinkCredential.credentialType}" + description: | + Bearer token for notification delivery. Token format is determined + by `sinkCredential.credentialType` in the subscription request. parameters: SubscriptionId: name: subscriptionId @@ -453,7 +457,6 @@ components: # and owns the lifecycle discriminator mapping. # # API projects reference this group via NotificationEvent but never modify it. - # In a split-file layout this schema lives in CAMARA_Events_common.yaml. # ───────────────────────────────────────────────────────────────────────── SubscriptionLifecycleEvent: @@ -576,6 +579,12 @@ components: description: The unique identifier of the subscription in the scope of the subscription manager. When this information is contained within an event notification, it SHALL be referred to as `subscriptionId` as per the Commonalities Event Notification Model. example: qs15-h556-rt89-1298 + # ───────────────────────────────────────────────────────────────────────── + # CloudEvents 1.0 envelope (Commonalities-owned, never modified) + # + # Knows nothing about CAMARA event types, data payloads, or discriminator + # mappings. Any CAMARA API that needs to send a notification starts here. + # ───────────────────────────────────────────────────────────────────────── CloudEvent: type: object description: | @@ -598,6 +607,7 @@ components: $ref: "#/components/schemas/Source" type: type: string + maxLength: 512 description: | Identifies the event type. CAMARA APIs use reverse-DNS notation: org.camaraproject... @@ -617,6 +627,7 @@ components: description: Event details payload. Structure is defined by each concrete event schema. time: $ref: "#/components/schemas/DateTime" + # ───────────────────────────────────────────────────────────────────────── # Extends CloudEvent via allOf and does exactly two things: # 1. Constrains `type` to its own ApiEventType enum @@ -645,7 +656,6 @@ components: org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" - Source: type: string format: uri-reference @@ -834,6 +844,7 @@ components: # ───────────────────────────────────────────────────────────────────────── HTTPSubscriptionRequest: + description: Subscription request for HTTP-based event delivery. allOf: - $ref: "#/components/schemas/SubscriptionRequest" - type: object @@ -842,6 +853,7 @@ components: $ref: "#/components/schemas/HTTPSettings" HTTPSubscriptionResponse: + description: Subscription resource returned for HTTP-based event delivery. allOf: - $ref: "#/components/schemas/Subscription" - type: object @@ -851,6 +863,7 @@ components: HTTPSettings: type: object + description: HTTP protocol settings for event delivery. properties: headers: type: object From 939d6f69a728ac0b81ae37799d0b10f497182477 Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:09:19 +0100 Subject: [PATCH 5/6] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Pedro Díez García Co-authored-by: Herbert Damker --- .../camara-cloudevents/event-subscription-template.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/artifacts/camara-cloudevents/event-subscription-template.yaml b/artifacts/camara-cloudevents/event-subscription-template.yaml index 9dcf39d6..f94677e0 100644 --- a/artifacts/camara-cloudevents/event-subscription-template.yaml +++ b/artifacts/camara-cloudevents/event-subscription-template.yaml @@ -21,7 +21,7 @@ externalDocs: # {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted. servers: - url: "{apiRoot}/api-name/vx.y" - # api-name and version should be valued accordingly to the CAMARA API versioning guidelines, e.g. for a version x.y.z, put v0.y for x=0 or just vx for x>0 in the url. +- url: "{apiRoot}/api-name/vwip" variables: apiRoot: default: http://localhost:9091 @@ -442,7 +442,7 @@ components: type: string description: | Enum of API-specific event type strings for this API project. - The reverse-DNS prefix org.camaraproject. makes each value + The reverse-DNS prefix `org.camaraproject.` makes each value globally unique, so two different API groups can independently define identically-named event types without any collision risk. enum: @@ -610,7 +610,7 @@ components: maxLength: 512 description: | Identifies the event type. CAMARA APIs use reverse-DNS notation: - org.camaraproject... + `org.camaraproject...` The api-name segment makes each type globally unique across API groups. specversion: type: string @@ -629,6 +629,8 @@ components: $ref: "#/components/schemas/DateTime" # ───────────────────────────────────────────────────────────────────────── + # API-specific notification event group + # # Extends CloudEvent via allOf and does exactly two things: # 1. Constrains `type` to its own ApiEventType enum # 2. Owns the discriminator mapping from each enum value to a concrete schema From c67a8eaa07c4b37ab247b322e130a60b038d82cf Mon Sep 17 00:00:00 2001 From: Rafal Artych <121048129+rartych@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:10:00 +0100 Subject: [PATCH 6/6] Update event-subscription-template.yaml --- .../event-subscription-template.yaml | 2792 ++++++++--------- 1 file changed, 1396 insertions(+), 1396 deletions(-) diff --git a/artifacts/camara-cloudevents/event-subscription-template.yaml b/artifacts/camara-cloudevents/event-subscription-template.yaml index f94677e0..f1846bbf 100644 --- a/artifacts/camara-cloudevents/event-subscription-template.yaml +++ b/artifacts/camara-cloudevents/event-subscription-template.yaml @@ -1,1397 +1,1397 @@ -openapi: 3.0.3 -info: - title: Notification Subscription Template - description: | - This file is a template for CAMARA API explicit subscription endpoint and for Notification model. - Additional information are provided in [CAMARA API Event Subscription and Notification Guide](https://github.com/camaraproject/Commonalities/blob/main/documentation/CAMARA-API-Event-Subscription-and-Notification-Guide.md). - - Note on event name convention: the event type name MUST follow: ``org.camaraproject...`` - - Note on ``security`` - ``openId`` scope: The value in this yaml `api-name:event-type1:grant-level` must be replaced accordingly to the format defined in the guideline document. - - license: - name: Apache 2.0 - url: https://www.apache.org/licenses/LICENSE-2.0.html - version: wip - x-camara-commonalities: "0.7" - -externalDocs: - description: Product documentation at CAMARA - url: https://github.com/camaraproject/apiRepository - # {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted. -servers: - - url: "{apiRoot}/api-name/vx.y" +openapi: 3.0.3 +info: + title: Notification Subscription Template + description: | + This file is a template for CAMARA API explicit subscription endpoint and for Notification model. + Additional information are provided in [CAMARA API Event Subscription and Notification Guide](https://github.com/camaraproject/Commonalities/blob/main/documentation/CAMARA-API-Event-Subscription-and-Notification-Guide.md). + + Note on event name convention: the event type name MUST follow: ``org.camaraproject...`` + + Note on ``security`` - ``openId`` scope: The value in this yaml `api-name:event-type1:grant-level` must be replaced accordingly to the format defined in the guideline document. + + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: wip + x-camara-commonalities: 0.7.0 + +externalDocs: + description: Product documentation at CAMARA + url: https://github.com/camaraproject/apiRepository + # {apiRepository} MUST be replaced by the CAMARA Subproject Repository name where the API design based on this template is hosted. +servers: + - url: "{apiRoot}/api-name/vx.y" - url: "{apiRoot}/api-name/vwip" - variables: - apiRoot: - default: http://localhost:9091 - description: API root, defined by the service provider, e.g. `api.example.com` or `api.example.com/somepath` -tags: - - name: Subscription - description: Operations to manage event subscriptions on event-type event - -paths: - /subscriptions: - post: - tags: - - Subscription - summary: "Create a apiName event subscription" - description: Create a apiName event subscription - operationId: createApiNameSubscription - parameters: - - $ref: "#/components/parameters/x-correlator" - security: - - openId: - - api-name:event-type1:grant-level - - api-name:event-type2:grant-level - requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/SubscriptionRequest" - required: true - callbacks: - notifications: - "{$request.body#/sink}": - post: - summary: "notifications callback" - description: | - Important: this endpoint is to be implemented by the API consumer. - The apiName server will call this endpoint whenever a apiName event occurs. - `operationId` value will have to be replaced accordingly with WG API specific semantic - operationId: postNotification - parameters: - - $ref: "#/components/parameters/x-correlator" - requestBody: - required: true - content: - application/cloudevents+json: - schema: - $ref: "#/components/schemas/NotificationEvent" - responses: - "204": - description: Successful notification - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - "400": - $ref: "#/components/responses/Generic400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "410": - $ref: "#/components/responses/Generic410" - "429": - $ref: "#/components/responses/Generic429" - security: - - {} - - notificationsBearerAuth: [] - - responses: - "201": - description: Created - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - $ref: "#/components/schemas/Subscription" - "202": - description: Request accepted to be processed. It applies for async creation process. - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - $ref: "#/components/schemas/SubscriptionAsync" - "400": - $ref: "#/components/responses/CreateSubscriptionBadRequest400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/SubscriptionPermissionDenied403" - "409": - $ref: "#/components/responses/Generic409" - "422": - $ref: "#/components/responses/CreateSubscriptionUnprocessableEntity422" - "429": - $ref: "#/components/responses/Generic429" - get: - tags: - - Subscription - summary: "Retrieve a list of apiName event subscription" - description: Retrieve a list of apiName event subscription(s) - operationId: retrieveApiNameSubscriptionList - parameters: - - $ref: "#/components/parameters/x-correlator" - security: - - openId: - - api-name:read - responses: - "200": - description: List of event subscription details - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - type: array - minItems: 0 - maxItems: 1000 - items: - $ref: '#/components/schemas/Subscription' - "400": - $ref: "#/components/responses/Generic400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - /subscriptions/{subscriptionId}: - get: - tags: - - Subscription - summary: "Retrieve a apiName event subscription" - description: retrieve apiName subscription information for a given subscription. - operationId: retrieveApiNameSubscription - security: - - openId: - - api-name:read - parameters: - - $ref: "#/components/parameters/SubscriptionId" - - $ref: "#/components/parameters/x-correlator" - responses: - "200": - description: OK - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - $ref: "#/components/schemas/Subscription" - "400": - $ref: "#/components/responses/SubscriptionIdRequired400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "404": - $ref: "#/components/responses/Generic404" - delete: - tags: - - Subscription - summary: "Delete a apiName event subscription" - operationId: deleteApiNameSubscription - description: delete a given apiName subscription. - security: - - openId: - - api-name:delete - parameters: - - $ref: "#/components/parameters/SubscriptionId" - - $ref: "#/components/parameters/x-correlator" - responses: - "204": - description: apiName subscription deleted - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - "202": - description: Request accepted to be processed. It applies for async deletion process. - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - $ref: "#/components/schemas/SubscriptionAsync" - "400": - $ref: "#/components/responses/SubscriptionIdRequired400" - "401": - $ref: "#/components/responses/Generic401" - "403": - $ref: "#/components/responses/Generic403" - "404": - $ref: "#/components/responses/Generic404" -components: - securitySchemes: - openId: - type: openIdConnect - openIdConnectUrl: https://example.com/.well-known/openid-configuration - description: OpenID Connect authentication via discovery metadata. - notificationsBearerAuth: - type: http - scheme: bearer - bearerFormat: "{$request.body#/sinkCredential.credentialType}" - description: | - Bearer token for notification delivery. Token format is determined - by `sinkCredential.credentialType` in the subscription request. - parameters: - SubscriptionId: - name: subscriptionId - in: path - description: Subscription identifier that was obtained from the create event subscription operation - required: true - schema: - $ref: "#/components/schemas/SubscriptionId" - x-correlator: - name: x-correlator - in: header - description: Correlation id for the different services - schema: - $ref: "#/components/schemas/XCorrelator" - headers: - x-correlator: - description: Correlation id for the different services - schema: - $ref: "#/components/schemas/XCorrelator" - schemas: - ErrorInfo: - type: object - description: A structured error response providing details about a failed request, including the HTTP status code, an error code, and a human-readable message - required: - - status - - code - - message - properties: - status: - type: integer - format: int32 - minimum: 100 - maximum: 599 - description: HTTP response status code - code: - type: string - maxLength: 96 - description: A human-readable code to describe the error - message: - type: string - maxLength: 512 - description: A human-readable description of what the event represents - - XCorrelator: - type: string - description: Correlator string, UUID format recommended but any string matching the pattern can be used - pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ - maxLength: 256 - example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" - - SubscriptionRequest: - description: The request for creating a event-type event subscription - type: object - required: - - sink - - protocol - - config - - types - properties: - protocol: - $ref: "#/components/schemas/Protocol" - sink: - type: string - format: uri - maxLength: 2048 - pattern: ^https:\/\/.+$ - description: The address to which events shall be delivered using the selected protocol. - example: "https://endpoint.example.com/sink" - sinkCredential: - $ref: "#/components/schemas/SinkCredential" - types: - description: | - Camara Event types eligible to be delivered by this subscription. - References ApiEventType (not the full NotificationEvent union) — - subscription requests target API-specific events only; lifecycle - events are server-initiated and cannot be subscribed to directly. - Note: the maximum number of event types per subscription will be decided at API project level. - type: array - minItems: 1 - maxItems: 1 - items: - $ref: "#/components/schemas/ApiEventType" - config: - $ref: "#/components/schemas/Config" - discriminator: - propertyName: protocol - mapping: - HTTP: "#/components/schemas/HTTPSubscriptionRequest" - MQTT3: "#/components/schemas/MQTTSubscriptionRequest" - MQTT5: "#/components/schemas/MQTTSubscriptionRequest" - AMQP: "#/components/schemas/AMQPSubscriptionRequest" - NATS: "#/components/schemas/NATSSubscriptionRequest" - KAFKA: "#/components/schemas/ApacheKafkaSubscriptionRequest" - - Protocol: - type: string - enum: ["HTTP", "MQTT3", "MQTT5", "AMQP", "NATS", "KAFKA"] - description: Identifier of a delivery protocol. Only HTTP is allowed for now - example: "HTTP" - - Config: - description: | - Implementation-specific configuration parameters needed by the subscription manager for acquiring events. - In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent` - Specific event type attributes must be defined in `subscriptionDetail`. - Note: if a request is performed for several event types, all subscribed events will use same `config` parameters. - type: object - required: - - subscriptionDetail - properties: - subscriptionDetail: - $ref: "#/components/schemas/CreateSubscriptionDetail" - subscriptionExpireTime: - type: string - format: date-time - maxLength: 64 - example: 2023-01-17T13:18:23.682Z - description: The subscription expiration time (in date-time format) requested by the API consumer. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. Up to API project decision to keep it. - subscriptionMaxEvents: - type: integer - format: int32 - description: Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer - Once this number is reached, the subscription ends. Up to API project decision to keep it. - minimum: 1 - maximum: 1000000 - example: 5 - initialEvent: - type: boolean - description: | - Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is created and current situation reflects event request. - Example: Consumer request Roaming event. If consumer sets initialEvent to true and device is in roaming situation, an event is triggered - Up to API project decision to keep it. - - SinkCredential: - description: A sink credential provides authentication or authorization information necessary to enable delivery of events to a target. - type: object - properties: - credentialType: - type: string - enum: - - PLAIN - - ACCESSTOKEN - - PRIVATE_KEY_JWT - description: | - The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now - discriminator: - propertyName: credentialType - mapping: - PLAIN: "#/components/schemas/PlainCredential" - ACCESSTOKEN: "#/components/schemas/AccessTokenCredential" - PRIVATE_KEY_JWT: "#/components/schemas/PrivateKeyJWTCredential" - required: - - credentialType - PlainCredential: - type: object - description: A plain credential as a combination of an identifier and a secret. - allOf: - - $ref: "#/components/schemas/SinkCredential" - - type: object - required: - - identifier - - secret - properties: - identifier: - description: The identifier might be an account or username. - type: string - maxLength: 256 - secret: - description: The secret might be a password or passphrase. - type: string - maxLength: 512 - AccessTokenCredential: - type: object - description: An access token credential. This type of credential is meant to be used by API Consumers that have limited capabilities to handle authorization requests. - allOf: - - $ref: "#/components/schemas/SinkCredential" - - type: object - properties: - accessToken: - description: REQUIRED. An access token is a token granting access to the target resource. - type: string - maxLength: 4096 - accessTokenExpiresUtc: - type: string - format: date-time - maxLength: 64 - description: | - REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. - In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. - If the access token is a JWT and registered "exp" (Expiration Time) claim is present, the two expiry times should match. - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2023-07-03T12:27:08.312Z" - accessTokenType: - description: REQUIRED. Type of the access token (See [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). - type: string - enum: - - bearer - required: - - accessToken - - accessTokenExpiresUtc - - accessTokenType - PrivateKeyJWTCredential: - type: object - description: Use PRIVATE_KEY_JWT to get an access token. The authorization server information needed for this type of sink credential (token endpoint, client ID, JWKS URL) is shared upfront between the client and the CAMARA entity. This type of credential is to be used by clients that have an authorization server. - allOf: - - $ref: "#/components/schemas/SinkCredential" - CreateSubscriptionDetail: - description: The detail of the requested event subscription. - type: object - - ApiEventType: - type: string - description: | - Enum of API-specific event type strings for this API project. - The reverse-DNS prefix `org.camaraproject.` makes each value - globally unique, so two different API groups can independently define - identically-named event types without any collision risk. - enum: - - org.camaraproject.api-name.v0.event-type1 - - org.camaraproject.api-name.v0.event-type2 - - # ───────────────────────────────────────────────────────────────────────── - # Subscription lifecycle event group (Commonalities-owned) - # - # Common to every CAMARA API that supports subscriptions. - # Extends CloudEvent via allOf, constrains `type` to lifecycle values, - # and owns the lifecycle discriminator mapping. - # - # API projects reference this group via NotificationEvent but never modify it. - # ───────────────────────────────────────────────────────────────────────── - - SubscriptionLifecycleEvent: - description: | - Subscription lifecycle event group, common to all CAMARA APIs that - support explicit subscriptions. - Extends the CloudEvent envelope and constrains `type` to the set of - lifecycle event types managed by Commonalities. - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - type: - $ref: "#/components/schemas/SubscriptionLifecycleEventType" - discriminator: - propertyName: type - mapping: - org.camaraproject.api-name.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" - org.camaraproject.api-name.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" - org.camaraproject.api-name.v0.subscription-ended: "#/components/schemas/EventSubscriptionEnded" - - SubscriptionLifecycleEventType: - type: string - description: | - Enum of subscription lifecycle event type strings. - These are managed by Commonalities and are identical across all CAMARA - APIs that support explicit subscriptions. - Kept as a separate named schema so the set of valid lifecycle type - strings can be referenced independently from the discriminated schema. - enum: - - org.camaraproject.api-name.v0.subscription-started - - org.camaraproject.api-name.v0.subscription-updated - - org.camaraproject.api-name.v0.subscription-ended - - Subscription: - description: Represents a event-type subscription. - type: object - required: - - sink - - protocol - - config - - types - - id - properties: - protocol: - $ref: "#/components/schemas/Protocol" - sink: - type: string - format: uri - maxLength: 2048 - pattern: ^https:\/\/.+$ - description: The address to which events shall be delivered using the selected protocol. - example: "https://endpoint.example.com/sink" - types: - description: | - Camara Event types eligible to be delivered by this subscription. - Note: the maximum number of event types per subscription will be decided at API project level - type: array - minItems: 1 - maxItems: 1 - items: - $ref: "#/components/schemas/ApiEventType" - config: - $ref: '#/components/schemas/Config' - id: - $ref: '#/components/schemas/SubscriptionId' - startsAt: - type: string - format: date-time - maxLength: 64 - description: | - Date when the event subscription will begin/began - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2023-07-03T12:27:08.312Z" - expiresAt: - type: string - format: date-time - maxLength: 64 - description: | - Date when the event subscription will expire. Only provided when `subscriptionExpireTime` is indicated by API client or Telco Operator has specific policy about that. - It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2023-07-03T12:27:08.312Z" - status: - type: string - description: |- - Current status of the subscription - Management of Subscription State engine is not mandatory for now. Note not all statuses may be considered to be implemented. Details: - - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but subscription creation process is not finished yet. - - `ACTIVE`: Subscription creation process is completed. Subscription is fully operative. - - `INACTIVE`: Subscription is temporarily inactive, but its workflow logic is not deleted. - - `EXPIRED`: Subscription is ended (no longer active). This status applies when subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED` event. - - `DELETED`: Subscription is ended as deleted (no longer active). This status applies when subscription information is kept (i.e. subscription workflow is no longer active but its meta-information is kept). - enum: - - ACTIVATION_REQUESTED - - ACTIVE - - EXPIRED - - INACTIVE - - DELETED - discriminator: - propertyName: protocol - mapping: - HTTP: '#/components/schemas/HTTPSubscriptionResponse' - MQTT3: '#/components/schemas/MQTTSubscriptionResponse' - MQTT5: '#/components/schemas/MQTTSubscriptionResponse' - AMQP: '#/components/schemas/AMQPSubscriptionResponse' - NATS: '#/components/schemas/NATSSubscriptionResponse' - KAFKA: '#/components/schemas/ApacheKafkaSubscriptionResponse' - - SubscriptionAsync: - description: Response for a event-type subscription request managed asynchronously (Creation or Deletion) - type: object - required: - - id - properties: - id: - $ref: "#/components/schemas/SubscriptionId" - - SubscriptionId: - type: string - maxLength: 256 - description: The unique identifier of the subscription in the scope of the subscription manager. When this information is contained within an event notification, it SHALL be referred to as `subscriptionId` as per the Commonalities Event Notification Model. - example: qs15-h556-rt89-1298 - - # ───────────────────────────────────────────────────────────────────────── - # CloudEvents 1.0 envelope (Commonalities-owned, never modified) - # - # Knows nothing about CAMARA event types, data payloads, or discriminator - # mappings. Any CAMARA API that needs to send a notification starts here. - # ───────────────────────────────────────────────────────────────────────── - CloudEvent: - type: object - description: | - CloudEvents 1.0 specification envelope. - This schema is the stable base for all CAMARA event notifications. - It imposes no constraints on `type` values or `data` structure — - those concerns belong to the API-specific and lifecycle group schemas. - required: - - id - - source - - specversion - - type - - time - properties: - id: - type: string - maxLength: 256 - description: Identifier of this event, unique within the source context. - source: - $ref: "#/components/schemas/Source" - type: - type: string - maxLength: 512 - description: | - Identifies the event type. CAMARA APIs use reverse-DNS notation: - `org.camaraproject...` - The api-name segment makes each type globally unique across API groups. - specversion: - type: string - description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) - enum: - - "1.0" - datacontenttype: - type: string - description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' - enum: - - application/json - data: - type: object - description: Event details payload. Structure is defined by each concrete event schema. - time: - $ref: "#/components/schemas/DateTime" - - # ───────────────────────────────────────────────────────────────────────── - # API-specific notification event group - # - # Extends CloudEvent via allOf and does exactly two things: - # 1. Constrains `type` to its own ApiEventType enum - # 2. Owns the discriminator mapping from each enum value to a concrete schema - # - # Adding a new event type requires only: adding a value to ApiEventType and - # adding a discriminator mapping entry here. CloudEvent is never touched. - # ───────────────────────────────────────────────────────────────────────── - - ApiNotificationEvent: - description: | - API-specific notification event group. - Extends the CloudEvent envelope and constrains `type` to the set of - event types defined by this API project. - Adding a new event type only requires updating ApiEventType and the - discriminator mapping below — the CloudEvent base never changes. - allOf: - - $ref: "#/components/schemas/CloudEvent" - - type: object - properties: - type: - $ref: "#/components/schemas/ApiEventType" - discriminator: - propertyName: "type" - mapping: - org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" - org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" - - Source: - type: string - format: uri-reference - minLength: 1 - maxLength: 2048 - description: | - Identifies the context in which an event happened - be a non-empty `URI-reference` like: - - URI with a DNS authority: - * https://github.com/cloudevents - * mailto:cncf-wg-serverless@lists.cncf.io - - Universally-unique URN with a UUID: - * urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 - - Application-specific identifier: - * /cloudevents/spec/pull/123 - * 1-555-123-4567 - example: "https://notificationSendServer12.example.com" - - DateTime: - type: string - format: date-time - maxLength: 64 - description: Timestamp of when the occurrence happened. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. - example: "2018-04-05T17:31:00Z" - - # ───────────────────────────────────────────────────────────────────────── - # Callback union (API project-owned) - # - # oneOf over all valid event groups at the callback endpoint. - # Owns no discriminator and applies no constraints of its own. - # Its only job is to enumerate which groups are valid for this API. - # - # To add a new event group: add it to the oneOf list. That is the only - # change required at this layer. - # ───────────────────────────────────────────────────────────────────────── - - NotificationEvent: - description: | - Union of all valid notification event groups at the callback endpoint. - This schema owns no discriminator — routing within each group is - handled by ApiNotificationEvent and SubscriptionLifecycleEvent - respectively. Its only responsibility is to enumerate which groups - are valid payloads for this API's notification callback. - oneOf: - - $ref: "#/components/schemas/ApiNotificationEvent" - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - # ───────────────────────────────────────────────────────────────────────── - # Concrete event schemas — API-specific (API project-owned) - # ───────────────────────────────────────────────────────────────────────── - - EventApiSpecific1: - description: event structure for event-type event 1 - allOf: - - $ref: "#/components/schemas/ApiNotificationEvent" - - type: object - properties: - data: - type: object - description: | - Event-specific payload for event-type1. - Replace with the actual data schema for this event type. - - EventApiSpecific2: - description: event structure for event-type event 2 - allOf: - - $ref: "#/components/schemas/ApiNotificationEvent" - - type: object - properties: - data: - type: object - description: | - Event-specific payload for event-type2. - Replace with the actual data schema for this event type. - - # ───────────────────────────────────────────────────────────────────────── - # Concrete event schemas — Subscription lifecycle (Commonalities-owned) - # ───────────────────────────────────────────────────────────────────────── - - EventSubscriptionStarted: - description: event structure for event subscription started - allOf: - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionStarted" - - SubscriptionStarted: - description: Event detail structure for subscription started event - type: object - required: - - initiationReason - - subscriptionId - properties: - initiationReason: - $ref: "#/components/schemas/InitiationReason" - subscriptionId: - $ref: "#/components/schemas/SubscriptionId" - initiationDescription: - type: string - maxLength: 512 - description: Description of subscription initiation - - InitiationReason: - type: string - description: | - - SUBSCRIPTION_CREATED - Subscription created by API Server - enum: - - SUBSCRIPTION_CREATED - - EventSubscriptionUpdated: - description: event structure for event subscription updated - allOf: - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionUpdated" - - SubscriptionUpdated: - description: Event detail structure for subscription updated event - type: object - required: - - updateReason - - subscriptionId - properties: - updateReason: - $ref: "#/components/schemas/UpdateReason" - subscriptionId: - $ref: "#/components/schemas/SubscriptionId" - updateDescription: - type: string - maxLength: 512 - description: Description of subscription update - - UpdateReason: - type: string - description: | - - SUBSCRIPTION_ACTIVE - API server transitioned subscription status to `ACTIVE` - - SUBSCRIPTION_INACTIVE - API server transitioned subscription status to `INACTIVE` - enum: - - SUBSCRIPTION_ACTIVE - - SUBSCRIPTION_INACTIVE - - EventSubscriptionEnded: - description: event structure for event subscription ended - allOf: - - $ref: "#/components/schemas/SubscriptionLifecycleEvent" - - type: object - properties: - data: - $ref: "#/components/schemas/SubscriptionEnded" - - SubscriptionEnded: - description: Event detail structure for subscription ended event - type: object - required: - - terminationReason - - subscriptionId - properties: - terminationReason: - $ref: "#/components/schemas/TerminationReason" - subscriptionId: - $ref: "#/components/schemas/SubscriptionId" - terminationDescription: - type: string - maxLength: 512 - description: Description of subscription termination - - TerminationReason: - type: string - description: | - - NETWORK_TERMINATED - API server stopped sending notification - - SUBSCRIPTION_EXPIRED - Subscription expire time (optionally set by the requester) has been reached - - MAX_EVENTS_REACHED - Maximum number of events (optionally set by the requester) has been reached - - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential (optionally set by the requester with credential type `ACCESSTOKEN`) expiration time has been reached - - SUBSCRIPTION_DELETED - Subscription was deleted by the requester - enum: - - MAX_EVENTS_REACHED - - NETWORK_TERMINATED - - SUBSCRIPTION_EXPIRED - - ACCESS_TOKEN_EXPIRED - - SUBSCRIPTION_DELETED - # ───────────────────────────────────────────────────────────────────────── - # Protocol-specific subscription schemas - # ───────────────────────────────────────────────────────────────────────── - - HTTPSubscriptionRequest: - description: Subscription request for HTTP-based event delivery. - allOf: - - $ref: "#/components/schemas/SubscriptionRequest" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/HTTPSettings" - - HTTPSubscriptionResponse: - description: Subscription resource returned for HTTP-based event delivery. - allOf: - - $ref: "#/components/schemas/Subscription" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/HTTPSettings" - - HTTPSettings: - type: object - description: HTTP protocol settings for event delivery. - properties: - headers: - type: object - description: |- - A set of key/value pairs that is copied into the HTTP request as custom headers. - - NOTE: Use/Applicability of this concept has not been discussed in Commonalities. When required by an API project as an option to meet a UC/Requirement, please generate an issue for Commonalities discussion about it. - additionalProperties: - type: string - maxLength: 512 - method: - type: string - description: The HTTP method to use for sending the message. - enum: - - POST - - MQTTSubscriptionRequest: - allOf: - - $ref: "#/components/schemas/SubscriptionRequest" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/MQTTSettings" - - MQTTSubscriptionResponse: - allOf: - - $ref: "#/components/schemas/Subscription" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/MQTTSettings" - - MQTTSettings: - type: object - properties: - topicName: - type: string - maxLength: 256 - description: MQTT topic name - qos: - type: integer - format: int32 - minimum: 0 - maximum: 2 - description: Quality of Service level (0, 1, or 2) - retain: - type: boolean - expiry: - type: integer - format: int32 - minimum: 0 - maximum: 2147483647 - description: Message expiry interval in seconds - userProperties: - type: object - required: - - topicName - - AMQPSubscriptionRequest: - allOf: - - $ref: "#/components/schemas/SubscriptionRequest" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/AMQPSettings" - - AMQPSubscriptionResponse: - allOf: - - $ref: "#/components/schemas/Subscription" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/AMQPSettings" - - AMQPSettings: - type: object - properties: - address: - type: string - maxLength: 512 - linkName: - type: string - maxLength: 256 - senderSettlementMode: - type: string - enum: ["settled", "unsettled"] - linkProperties: - type: object - additionalProperties: - type: string - maxLength: 1024 - - ApacheKafkaSubscriptionRequest: - allOf: - - $ref: "#/components/schemas/SubscriptionRequest" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/ApacheKafkaSettings" - - ApacheKafkaSubscriptionResponse: - allOf: - - $ref: "#/components/schemas/Subscription" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/ApacheKafkaSettings" - - ApacheKafkaSettings: - type: object - properties: - topicName: - type: string - maxLength: 249 - partitionKeyExtractor: - type: string - maxLength: 512 - clientId: - type: string - maxLength: 256 - ackMode: - type: integer - format: int32 - minimum: 0 - maximum: 2 - description: Acknowledgment mode (0=no ack, 1=leader ack, 2=all replicas ack) - required: - - topicName - - NATSSubscriptionRequest: - allOf: - - $ref: "#/components/schemas/SubscriptionRequest" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/NATSSettings" - - NATSSubscriptionResponse: - allOf: - - $ref: "#/components/schemas/Subscription" - - type: object - properties: - protocolSettings: - $ref: "#/components/schemas/NATSSettings" - - NATSSettings: - type: object - properties: - subject: - type: string - maxLength: 256 - description: NATS subject - required: - - subject - - responses: - CreateSubscriptionBadRequest400: - description: Problem with the client request - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 400 - code: - enum: - - INVALID_ARGUMENT - - OUT_OF_RANGE - - INVALID_PROTOCOL - - INVALID_CREDENTIAL - - INVALID_TOKEN - - INVALID_SINK - examples: - GENERIC_400_INVALID_ARGUMENT: - description: Invalid Argument. Generic Syntax Exception - value: - status: 400 - code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. - GENERIC_400_OUT_OF_RANGE: - description: Out of Range. Specific Syntax Exception used when a given field has a pre-defined range or a invalid filter criteria combination is requested - value: - status: 400 - code: OUT_OF_RANGE - message: Client specified an invalid range. - GENERIC_400_INVALID_PROTOCOL: - description: Invalid protocol for events subscription management - value: - status: 400 - code: INVALID_PROTOCOL - message: Only HTTP is supported - GENERIC_400_INVALID_CREDENTIAL: - description: Invalid sink credential type - value: - status: 400 - code: INVALID_CREDENTIAL - message: Only Access token or Private key JWT are supported - GENERIC_400_INVALID_SINK: - description: Invalid sink value - value: - status: 400 - code: INVALID_SINK - message: sink not valid for the specified protocol - Generic400: - description: Problem with the client request - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 400 - code: - enum: - - INVALID_ARGUMENT - examples: - GENERIC_400_INVALID_ARGUMENT: - description: Invalid Argument. Generic Syntax Exception - value: - status: 400 - code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. - SubscriptionIdRequired400: - description: Problem with the client request - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 400 - code: - enum: - - INVALID_ARGUMENT - examples: - GENERIC_400_INVALID_ARGUMENT: - description: Invalid Argument. Generic Syntax Exception - value: - status: 400 - code: INVALID_ARGUMENT - message: Client specified an invalid argument, request body or query param. - GENERIC_400_SUBSCRIPTION_ID_REQUIRED: - description: subscription id is required - value: - status: 400 - code: INVALID_ARGUMENT - message: "Expected property is missing: subscriptionId" - Generic401: - description: Authentication problem with the client request - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 401 - code: - enum: - - UNAUTHENTICATED - examples: - GENERIC_401_UNAUTHENTICATED: - description: Request cannot be authenticated and a new authentication is required - value: - status: 401 - code: UNAUTHENTICATED - message: Request not authenticated due to missing, invalid, or expired credentials. A new authentication is required. - Generic403: - description: Client does not have sufficient permission - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 403 - code: - enum: - - PERMISSION_DENIED - examples: - GENERIC_403_PERMISSION_DENIED: - description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security - value: - status: 403 - code: PERMISSION_DENIED - message: Client does not have sufficient permissions to perform this action. - SubscriptionPermissionDenied403: - description: Client does not have sufficient permission - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 403 - code: - enum: - - PERMISSION_DENIED - - SUBSCRIPTION_MISMATCH - examples: - GENERIC_403_PERMISSION_DENIED: - description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security - value: - status: 403 - code: PERMISSION_DENIED - message: Client does not have sufficient permissions to perform this action. - GENERIC_403_SUBSCRIPTION_MISMATCH: - description: Inconsistent access token for requested subscription - value: - status: 403 - code: "SUBSCRIPTION_MISMATCH" - message: "Inconsistent access token for requested events subscription" - Generic404: - description: Resource Not Found - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 404 - code: - enum: - - NOT_FOUND - examples: - GENERIC_404_NOT_FOUND: - description: Resource is not found - value: - status: 404 - code: NOT_FOUND - message: The specified resource is not found. - Generic409: - description: Conflict - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 409 - code: - enum: - - ABORTED - - ALREADY_EXISTS - examples: - GENERIC_409_ABORTED: - description: Concurrency of processes of the same nature/scope - value: - status: 409 - code: ABORTED - message: Concurrency conflict. - GENERIC_409_ALREADY_EXISTS: - description: Trying to create an existing resource - value: - status: 409 - code: ALREADY_EXISTS - message: The resource that a client tried to create already exists. - Generic410: - description: Gone - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 410 - code: - enum: - - GONE - examples: - GENERIC_410_GONE: - description: Use in notifications flow to allow API Consumer to indicate that its callback is no longer available - value: - status: 410 - code: GONE - message: Access to the target resource is no longer available. - CreateSubscriptionUnprocessableEntity422: - description: Unprocessable Entity - headers: - x-correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 422 - code: - enum: - - SERVICE_NOT_APPLICABLE - - MISSING_IDENTIFIER - - UNSUPPORTED_IDENTIFIER - - UNNECESSARY_IDENTIFIER - - MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED - - MULTIEVENT_COMBINATION_TEMPORARILY_NOT_SUPPORTED - - PRIVATE_KEY_JWT_NOT_CONFIGURED - examples: - GENERIC_422_SERVICE_NOT_APPLICABLE: - description: Service not applicable for the provided identifier - value: - status: 422 - code: SERVICE_NOT_APPLICABLE - message: The service is not available for the provided identifier. - GENERIC_422_MISSING_IDENTIFIER: - description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token - value: - status: 422 - code: MISSING_IDENTIFIER - message: The device cannot be identified. - GENERIC_422_UNSUPPORTED_IDENTIFIER: - description: None of the provided identifiers is supported by the implementation - value: - status: 422 - code: UNSUPPORTED_IDENTIFIER - message: The identifier provided is not supported. - GENERIC_422_UNNECESSARY_IDENTIFIER: - description: An explicit identifier is provided when a device or phone number has already been identified from the access token - value: - status: 422 - code: UNNECESSARY_IDENTIFIER - message: The device is already identified by the access token. - GENERIC_422_MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED: - description: Multi event types subscription is not supported - value: - status: 422 - code: MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED - message: Multi event types subscription not managed - GENERIC_422_MULTIEVENT_COMBINATION_TEMPORARILY_NOT_SUPPORTED: - description: Combination of multiple event types is temporarily not supported - value: - status: 422 - code: MULTIEVENT_COMBINATION_TEMPORARILY_NOT_SUPPORTED - message: The requested combination of event types is temporarily not supported. - GENERIC_422_PRIVATE_KEY_JWT_NOT_CONFIGURED: - description: Private key JWT sink credential type is used but no configuration was pre-shared - value: - status: 422 - code: PRIVATE_KEY_JWT_NOT_CONFIGURED - message: No JWK Set configured for PRIVATE_KEY_JWT authentication. - Generic429: - description: Too Many Requests - headers: - X-Correlator: - $ref: "#/components/headers/x-correlator" - content: - application/json: - schema: - allOf: - - $ref: "#/components/schemas/ErrorInfo" - - type: object - properties: - status: - enum: - - 429 - code: - enum: - - QUOTA_EXCEEDED - - TOO_MANY_REQUESTS - examples: - GENERIC_429_QUOTA_EXCEEDED: - description: Request is rejected due to exceeding a business quota limit - value: - status: 429 - code: QUOTA_EXCEEDED - message: Out of resource quota. - GENERIC_429_TOO_MANY_REQUESTS: - description: Access to the API has been temporarily blocked due to rate or spike arrest limits being reached - value: - status: 429 - code: TOO_MANY_REQUESTS - message: Rate limit reached. + variables: + apiRoot: + default: http://localhost:9091 + description: API root, defined by the service provider, e.g. `api.example.com` or `api.example.com/somepath` +tags: + - name: Subscription + description: Operations to manage event subscriptions on event-type event + +paths: + /subscriptions: + post: + tags: + - Subscription + summary: "Create a apiName event subscription" + description: Create a apiName event subscription + operationId: createApiNameSubscription + parameters: + - $ref: "#/components/parameters/x-correlator" + security: + - openId: + - api-name:event-type1:grant-level + - api-name:event-type2:grant-level + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SubscriptionRequest" + required: true + callbacks: + notifications: + "{$request.body#/sink}": + post: + summary: "notifications callback" + description: | + Important: this endpoint is to be implemented by the API consumer. + The apiName server will call this endpoint whenever a apiName event occurs. + `operationId` value will have to be replaced accordingly with WG API specific semantic + operationId: postNotification + parameters: + - $ref: "#/components/parameters/x-correlator" + requestBody: + required: true + content: + application/cloudevents+json: + schema: + $ref: "#/components/schemas/NotificationEvent" + responses: + "204": + description: Successful notification + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + "400": + $ref: "#/components/responses/Generic400" + "401": + $ref: "#/components/responses/Generic401" + "403": + $ref: "#/components/responses/Generic403" + "410": + $ref: "#/components/responses/Generic410" + "429": + $ref: "#/components/responses/Generic429" + security: + - {} + - notificationsBearerAuth: [] + + responses: + "201": + description: Created + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/Subscription" + "202": + description: Request accepted to be processed. It applies for async creation process. + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/SubscriptionAsync" + "400": + $ref: "#/components/responses/CreateSubscriptionBadRequest400" + "401": + $ref: "#/components/responses/Generic401" + "403": + $ref: "#/components/responses/SubscriptionPermissionDenied403" + "409": + $ref: "#/components/responses/Generic409" + "422": + $ref: "#/components/responses/CreateSubscriptionUnprocessableEntity422" + "429": + $ref: "#/components/responses/Generic429" + get: + tags: + - Subscription + summary: "Retrieve a list of apiName event subscription" + description: Retrieve a list of apiName event subscription(s) + operationId: retrieveApiNameSubscriptionList + parameters: + - $ref: "#/components/parameters/x-correlator" + security: + - openId: + - api-name:read + responses: + "200": + description: List of event subscription details + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + type: array + minItems: 0 + maxItems: 1000 + items: + $ref: '#/components/schemas/Subscription' + "400": + $ref: "#/components/responses/Generic400" + "401": + $ref: "#/components/responses/Generic401" + "403": + $ref: "#/components/responses/Generic403" + /subscriptions/{subscriptionId}: + get: + tags: + - Subscription + summary: "Retrieve a apiName event subscription" + description: retrieve apiName subscription information for a given subscription. + operationId: retrieveApiNameSubscription + security: + - openId: + - api-name:read + parameters: + - $ref: "#/components/parameters/SubscriptionId" + - $ref: "#/components/parameters/x-correlator" + responses: + "200": + description: OK + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/Subscription" + "400": + $ref: "#/components/responses/SubscriptionIdRequired400" + "401": + $ref: "#/components/responses/Generic401" + "403": + $ref: "#/components/responses/Generic403" + "404": + $ref: "#/components/responses/Generic404" + delete: + tags: + - Subscription + summary: "Delete a apiName event subscription" + operationId: deleteApiNameSubscription + description: delete a given apiName subscription. + security: + - openId: + - api-name:delete + parameters: + - $ref: "#/components/parameters/SubscriptionId" + - $ref: "#/components/parameters/x-correlator" + responses: + "204": + description: apiName subscription deleted + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + "202": + description: Request accepted to be processed. It applies for async deletion process. + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + $ref: "#/components/schemas/SubscriptionAsync" + "400": + $ref: "#/components/responses/SubscriptionIdRequired400" + "401": + $ref: "#/components/responses/Generic401" + "403": + $ref: "#/components/responses/Generic403" + "404": + $ref: "#/components/responses/Generic404" +components: + securitySchemes: + openId: + type: openIdConnect + openIdConnectUrl: https://example.com/.well-known/openid-configuration + description: OpenID Connect authentication via discovery metadata. + notificationsBearerAuth: + type: http + scheme: bearer + bearerFormat: "{$request.body#/sinkCredential.credentialType}" + description: | + Bearer token for notification delivery. Token format is determined + by `sinkCredential.credentialType` in the subscription request. + parameters: + SubscriptionId: + name: subscriptionId + in: path + description: Subscription identifier that was obtained from the create event subscription operation + required: true + schema: + $ref: "#/components/schemas/SubscriptionId" + x-correlator: + name: x-correlator + in: header + description: Correlation id for the different services + schema: + $ref: "#/components/schemas/XCorrelator" + headers: + x-correlator: + description: Correlation id for the different services + schema: + $ref: "#/components/schemas/XCorrelator" + schemas: + ErrorInfo: + type: object + description: A structured error response providing details about a failed request, including the HTTP status code, an error code, and a human-readable message + required: + - status + - code + - message + properties: + status: + type: integer + format: int32 + minimum: 100 + maximum: 599 + description: HTTP response status code + code: + type: string + maxLength: 96 + description: A human-readable code to describe the error + message: + type: string + maxLength: 512 + description: A human-readable description of what the event represents + + XCorrelator: + type: string + description: Correlator string, UUID format recommended but any string matching the pattern can be used + pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ + maxLength: 256 + example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" + + SubscriptionRequest: + description: The request for creating a event-type event subscription + type: object + required: + - sink + - protocol + - config + - types + properties: + protocol: + $ref: "#/components/schemas/Protocol" + sink: + type: string + format: uri + maxLength: 2048 + pattern: ^https:\/\/.+$ + description: The address to which events shall be delivered using the selected protocol. + example: "https://endpoint.example.com/sink" + sinkCredential: + $ref: "#/components/schemas/SinkCredential" + types: + description: | + Camara Event types eligible to be delivered by this subscription. + References ApiEventType (not the full NotificationEvent union) — + subscription requests target API-specific events only; lifecycle + events are server-initiated and cannot be subscribed to directly. + Note: the maximum number of event types per subscription will be decided at API project level. + type: array + minItems: 1 + maxItems: 1 + items: + $ref: "#/components/schemas/ApiEventType" + config: + $ref: "#/components/schemas/Config" + discriminator: + propertyName: protocol + mapping: + HTTP: "#/components/schemas/HTTPSubscriptionRequest" + MQTT3: "#/components/schemas/MQTTSubscriptionRequest" + MQTT5: "#/components/schemas/MQTTSubscriptionRequest" + AMQP: "#/components/schemas/AMQPSubscriptionRequest" + NATS: "#/components/schemas/NATSSubscriptionRequest" + KAFKA: "#/components/schemas/ApacheKafkaSubscriptionRequest" + + Protocol: + type: string + enum: ["HTTP", "MQTT3", "MQTT5", "AMQP", "NATS", "KAFKA"] + description: Identifier of a delivery protocol. Only HTTP is allowed for now + example: "HTTP" + + Config: + description: | + Implementation-specific configuration parameters needed by the subscription manager for acquiring events. + In CAMARA we have predefined attributes like `subscriptionExpireTime`, `subscriptionMaxEvents`, `initialEvent` + Specific event type attributes must be defined in `subscriptionDetail`. + Note: if a request is performed for several event types, all subscribed events will use same `config` parameters. + type: object + required: + - subscriptionDetail + properties: + subscriptionDetail: + $ref: "#/components/schemas/CreateSubscriptionDetail" + subscriptionExpireTime: + type: string + format: date-time + maxLength: 64 + example: 2023-01-17T13:18:23.682Z + description: The subscription expiration time (in date-time format) requested by the API consumer. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. Up to API project decision to keep it. + subscriptionMaxEvents: + type: integer + format: int32 + description: Identifies the maximum number of event reports to be generated (>=1) requested by the API consumer - Once this number is reached, the subscription ends. Up to API project decision to keep it. + minimum: 1 + maximum: 1000000 + example: 5 + initialEvent: + type: boolean + description: | + Set to `true` by API consumer if consumer wants to get an event as soon as the subscription is created and current situation reflects event request. + Example: Consumer request Roaming event. If consumer sets initialEvent to true and device is in roaming situation, an event is triggered + Up to API project decision to keep it. + + SinkCredential: + description: A sink credential provides authentication or authorization information necessary to enable delivery of events to a target. + type: object + properties: + credentialType: + type: string + enum: + - PLAIN + - ACCESSTOKEN + - PRIVATE_KEY_JWT + description: | + The type of the credential - MUST be set to ACCESSTOKEN or PRIVATE_KEY_JWT for now + discriminator: + propertyName: credentialType + mapping: + PLAIN: "#/components/schemas/PlainCredential" + ACCESSTOKEN: "#/components/schemas/AccessTokenCredential" + PRIVATE_KEY_JWT: "#/components/schemas/PrivateKeyJWTCredential" + required: + - credentialType + PlainCredential: + type: object + description: A plain credential as a combination of an identifier and a secret. + allOf: + - $ref: "#/components/schemas/SinkCredential" + - type: object + required: + - identifier + - secret + properties: + identifier: + description: The identifier might be an account or username. + type: string + maxLength: 256 + secret: + description: The secret might be a password or passphrase. + type: string + maxLength: 512 + AccessTokenCredential: + type: object + description: An access token credential. This type of credential is meant to be used by API Consumers that have limited capabilities to handle authorization requests. + allOf: + - $ref: "#/components/schemas/SinkCredential" + - type: object + properties: + accessToken: + description: REQUIRED. An access token is a token granting access to the target resource. + type: string + maxLength: 4096 + accessTokenExpiresUtc: + type: string + format: date-time + maxLength: 64 + description: | + REQUIRED. An absolute (UTC) timestamp at which the token shall be considered expired. + In the case of an ACCESS_TOKEN_EXPIRED termination reason, implementation should notify the client before the expiration date. + If the access token is a JWT and registered "exp" (Expiration Time) claim is present, the two expiry times should match. + It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + example: "2023-07-03T12:27:08.312Z" + accessTokenType: + description: REQUIRED. Type of the access token (See [OAuth 2.0](https://tools.ietf.org/html/rfc6749#section-7.1)). + type: string + enum: + - bearer + required: + - accessToken + - accessTokenExpiresUtc + - accessTokenType + PrivateKeyJWTCredential: + type: object + description: Use PRIVATE_KEY_JWT to get an access token. The authorization server information needed for this type of sink credential (token endpoint, client ID, JWKS URL) is shared upfront between the client and the CAMARA entity. This type of credential is to be used by clients that have an authorization server. + allOf: + - $ref: "#/components/schemas/SinkCredential" + CreateSubscriptionDetail: + description: The detail of the requested event subscription. + type: object + + ApiEventType: + type: string + description: | + Enum of API-specific event type strings for this API project. + The reverse-DNS prefix `org.camaraproject.` makes each value + globally unique, so two different API groups can independently define + identically-named event types without any collision risk. + enum: + - org.camaraproject.api-name.v0.event-type1 + - org.camaraproject.api-name.v0.event-type2 + + # ───────────────────────────────────────────────────────────────────────── + # Subscription lifecycle event group (Commonalities-owned) + # + # Common to every CAMARA API that supports subscriptions. + # Extends CloudEvent via allOf, constrains `type` to lifecycle values, + # and owns the lifecycle discriminator mapping. + # + # API projects reference this group via NotificationEvent but never modify it. + # ───────────────────────────────────────────────────────────────────────── + + SubscriptionLifecycleEvent: + description: | + Subscription lifecycle event group, common to all CAMARA APIs that + support explicit subscriptions. + Extends the CloudEvent envelope and constrains `type` to the set of + lifecycle event types managed by Commonalities. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/SubscriptionLifecycleEventType" + discriminator: + propertyName: type + mapping: + org.camaraproject.api-name.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" + org.camaraproject.api-name.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" + org.camaraproject.api-name.v0.subscription-ended: "#/components/schemas/EventSubscriptionEnded" + + SubscriptionLifecycleEventType: + type: string + description: | + Enum of subscription lifecycle event type strings. + These are managed by Commonalities and are identical across all CAMARA + APIs that support explicit subscriptions. + Kept as a separate named schema so the set of valid lifecycle type + strings can be referenced independently from the discriminated schema. + enum: + - org.camaraproject.api-name.v0.subscription-started + - org.camaraproject.api-name.v0.subscription-updated + - org.camaraproject.api-name.v0.subscription-ended + + Subscription: + description: Represents a event-type subscription. + type: object + required: + - sink + - protocol + - config + - types + - id + properties: + protocol: + $ref: "#/components/schemas/Protocol" + sink: + type: string + format: uri + maxLength: 2048 + pattern: ^https:\/\/.+$ + description: The address to which events shall be delivered using the selected protocol. + example: "https://endpoint.example.com/sink" + types: + description: | + Camara Event types eligible to be delivered by this subscription. + Note: the maximum number of event types per subscription will be decided at API project level + type: array + minItems: 1 + maxItems: 1 + items: + $ref: "#/components/schemas/ApiEventType" + config: + $ref: '#/components/schemas/Config' + id: + $ref: '#/components/schemas/SubscriptionId' + startsAt: + type: string + format: date-time + maxLength: 64 + description: | + Date when the event subscription will begin/began + It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + example: "2023-07-03T12:27:08.312Z" + expiresAt: + type: string + format: date-time + maxLength: 64 + description: | + Date when the event subscription will expire. Only provided when `subscriptionExpireTime` is indicated by API client or Telco Operator has specific policy about that. + It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + example: "2023-07-03T12:27:08.312Z" + status: + type: string + description: |- + Current status of the subscription - Management of Subscription State engine is not mandatory for now. Note not all statuses may be considered to be implemented. Details: + - `ACTIVATION_REQUESTED`: Subscription creation (POST) is triggered but subscription creation process is not finished yet. + - `ACTIVE`: Subscription creation process is completed. Subscription is fully operative. + - `INACTIVE`: Subscription is temporarily inactive, but its workflow logic is not deleted. + - `EXPIRED`: Subscription is ended (no longer active). This status applies when subscription is ended due to `SUBSCRIPTION_EXPIRED` or `ACCESS_TOKEN_EXPIRED` event. + - `DELETED`: Subscription is ended as deleted (no longer active). This status applies when subscription information is kept (i.e. subscription workflow is no longer active but its meta-information is kept). + enum: + - ACTIVATION_REQUESTED + - ACTIVE + - EXPIRED + - INACTIVE + - DELETED + discriminator: + propertyName: protocol + mapping: + HTTP: '#/components/schemas/HTTPSubscriptionResponse' + MQTT3: '#/components/schemas/MQTTSubscriptionResponse' + MQTT5: '#/components/schemas/MQTTSubscriptionResponse' + AMQP: '#/components/schemas/AMQPSubscriptionResponse' + NATS: '#/components/schemas/NATSSubscriptionResponse' + KAFKA: '#/components/schemas/ApacheKafkaSubscriptionResponse' + + SubscriptionAsync: + description: Response for a event-type subscription request managed asynchronously (Creation or Deletion) + type: object + required: + - id + properties: + id: + $ref: "#/components/schemas/SubscriptionId" + + SubscriptionId: + type: string + maxLength: 256 + description: The unique identifier of the subscription in the scope of the subscription manager. When this information is contained within an event notification, it SHALL be referred to as `subscriptionId` as per the Commonalities Event Notification Model. + example: qs15-h556-rt89-1298 + + # ───────────────────────────────────────────────────────────────────────── + # CloudEvents 1.0 envelope (Commonalities-owned, never modified) + # + # Knows nothing about CAMARA event types, data payloads, or discriminator + # mappings. Any CAMARA API that needs to send a notification starts here. + # ───────────────────────────────────────────────────────────────────────── + CloudEvent: + type: object + description: | + CloudEvents 1.0 specification envelope. + This schema is the stable base for all CAMARA event notifications. + It imposes no constraints on `type` values or `data` structure — + those concerns belong to the API-specific and lifecycle group schemas. + required: + - id + - source + - specversion + - type + - time + properties: + id: + type: string + maxLength: 256 + description: Identifier of this event, unique within the source context. + source: + $ref: "#/components/schemas/Source" + type: + type: string + maxLength: 512 + description: | + Identifies the event type. CAMARA APIs use reverse-DNS notation: + `org.camaraproject...` + The api-name segment makes each type globally unique across API groups. + specversion: + type: string + description: Version of the specification to which this event conforms (must be 1.0 if it conforms to cloudevents 1.0.2 version) + enum: + - "1.0" + datacontenttype: + type: string + description: 'media-type that describes the event payload encoding, must be "application/json" for CAMARA APIs' + enum: + - application/json + data: + type: object + description: Event details payload. Structure is defined by each concrete event schema. + time: + $ref: "#/components/schemas/DateTime" + + # ───────────────────────────────────────────────────────────────────────── + # API-specific notification event group + # + # Extends CloudEvent via allOf and does exactly two things: + # 1. Constrains `type` to its own ApiEventType enum + # 2. Owns the discriminator mapping from each enum value to a concrete schema + # + # Adding a new event type requires only: adding a value to ApiEventType and + # adding a discriminator mapping entry here. CloudEvent is never touched. + # ───────────────────────────────────────────────────────────────────────── + + ApiNotificationEvent: + description: | + API-specific notification event group. + Extends the CloudEvent envelope and constrains `type` to the set of + event types defined by this API project. + Adding a new event type only requires updating ApiEventType and the + discriminator mapping below — the CloudEvent base never changes. + allOf: + - $ref: "#/components/schemas/CloudEvent" + - type: object + properties: + type: + $ref: "#/components/schemas/ApiEventType" + discriminator: + propertyName: "type" + mapping: + org.camaraproject.api-name.v0.event-type1: "#/components/schemas/EventApiSpecific1" + org.camaraproject.api-name.v0.event-type2: "#/components/schemas/EventApiSpecific2" + + Source: + type: string + format: uri-reference + minLength: 1 + maxLength: 2048 + description: | + Identifies the context in which an event happened - be a non-empty `URI-reference` like: + - URI with a DNS authority: + * https://github.com/cloudevents + * mailto:cncf-wg-serverless@lists.cncf.io + - Universally-unique URN with a UUID: + * urn:uuid:6e8bc430-9c3a-11d9-9669-0800200c9a66 + - Application-specific identifier: + * /cloudevents/spec/pull/123 + * 1-555-123-4567 + example: "https://notificationSendServer12.example.com" + + DateTime: + type: string + format: date-time + maxLength: 64 + description: Timestamp of when the occurrence happened. It must follow [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339#section-5.6) and must have time zone. + example: "2018-04-05T17:31:00Z" + + # ───────────────────────────────────────────────────────────────────────── + # Callback union (API project-owned) + # + # oneOf over all valid event groups at the callback endpoint. + # Owns no discriminator and applies no constraints of its own. + # Its only job is to enumerate which groups are valid for this API. + # + # To add a new event group: add it to the oneOf list. That is the only + # change required at this layer. + # ───────────────────────────────────────────────────────────────────────── + + NotificationEvent: + description: | + Union of all valid notification event groups at the callback endpoint. + This schema owns no discriminator — routing within each group is + handled by ApiNotificationEvent and SubscriptionLifecycleEvent + respectively. Its only responsibility is to enumerate which groups + are valid payloads for this API's notification callback. + oneOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + + # ───────────────────────────────────────────────────────────────────────── + # Concrete event schemas — API-specific (API project-owned) + # ───────────────────────────────────────────────────────────────────────── + + EventApiSpecific1: + description: event structure for event-type event 1 + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - type: object + properties: + data: + type: object + description: | + Event-specific payload for event-type1. + Replace with the actual data schema for this event type. + + EventApiSpecific2: + description: event structure for event-type event 2 + allOf: + - $ref: "#/components/schemas/ApiNotificationEvent" + - type: object + properties: + data: + type: object + description: | + Event-specific payload for event-type2. + Replace with the actual data schema for this event type. + + # ───────────────────────────────────────────────────────────────────────── + # Concrete event schemas — Subscription lifecycle (Commonalities-owned) + # ───────────────────────────────────────────────────────────────────────── + + EventSubscriptionStarted: + description: event structure for event subscription started + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionStarted" + + SubscriptionStarted: + description: Event detail structure for subscription started event + type: object + required: + - initiationReason + - subscriptionId + properties: + initiationReason: + $ref: "#/components/schemas/InitiationReason" + subscriptionId: + $ref: "#/components/schemas/SubscriptionId" + initiationDescription: + type: string + maxLength: 512 + description: Description of subscription initiation + + InitiationReason: + type: string + description: | + - SUBSCRIPTION_CREATED - Subscription created by API Server + enum: + - SUBSCRIPTION_CREATED + + EventSubscriptionUpdated: + description: event structure for event subscription updated + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionUpdated" + + SubscriptionUpdated: + description: Event detail structure for subscription updated event + type: object + required: + - updateReason + - subscriptionId + properties: + updateReason: + $ref: "#/components/schemas/UpdateReason" + subscriptionId: + $ref: "#/components/schemas/SubscriptionId" + updateDescription: + type: string + maxLength: 512 + description: Description of subscription update + + UpdateReason: + type: string + description: | + - SUBSCRIPTION_ACTIVE - API server transitioned subscription status to `ACTIVE` + - SUBSCRIPTION_INACTIVE - API server transitioned subscription status to `INACTIVE` + enum: + - SUBSCRIPTION_ACTIVE + - SUBSCRIPTION_INACTIVE + + EventSubscriptionEnded: + description: event structure for event subscription ended + allOf: + - $ref: "#/components/schemas/SubscriptionLifecycleEvent" + - type: object + properties: + data: + $ref: "#/components/schemas/SubscriptionEnded" + + SubscriptionEnded: + description: Event detail structure for subscription ended event + type: object + required: + - terminationReason + - subscriptionId + properties: + terminationReason: + $ref: "#/components/schemas/TerminationReason" + subscriptionId: + $ref: "#/components/schemas/SubscriptionId" + terminationDescription: + type: string + maxLength: 512 + description: Description of subscription termination + + TerminationReason: + type: string + description: | + - NETWORK_TERMINATED - API server stopped sending notification + - SUBSCRIPTION_EXPIRED - Subscription expire time (optionally set by the requester) has been reached + - MAX_EVENTS_REACHED - Maximum number of events (optionally set by the requester) has been reached + - ACCESS_TOKEN_EXPIRED - Access Token sinkCredential (optionally set by the requester with credential type `ACCESSTOKEN`) expiration time has been reached + - SUBSCRIPTION_DELETED - Subscription was deleted by the requester + enum: + - MAX_EVENTS_REACHED + - NETWORK_TERMINATED + - SUBSCRIPTION_EXPIRED + - ACCESS_TOKEN_EXPIRED + - SUBSCRIPTION_DELETED + # ───────────────────────────────────────────────────────────────────────── + # Protocol-specific subscription schemas + # ───────────────────────────────────────────────────────────────────────── + + HTTPSubscriptionRequest: + description: Subscription request for HTTP-based event delivery. + allOf: + - $ref: "#/components/schemas/SubscriptionRequest" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/HTTPSettings" + + HTTPSubscriptionResponse: + description: Subscription resource returned for HTTP-based event delivery. + allOf: + - $ref: "#/components/schemas/Subscription" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/HTTPSettings" + + HTTPSettings: + type: object + description: HTTP protocol settings for event delivery. + properties: + headers: + type: object + description: |- + A set of key/value pairs that is copied into the HTTP request as custom headers. + + NOTE: Use/Applicability of this concept has not been discussed in Commonalities. When required by an API project as an option to meet a UC/Requirement, please generate an issue for Commonalities discussion about it. + additionalProperties: + type: string + maxLength: 512 + method: + type: string + description: The HTTP method to use for sending the message. + enum: + - POST + + MQTTSubscriptionRequest: + allOf: + - $ref: "#/components/schemas/SubscriptionRequest" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/MQTTSettings" + + MQTTSubscriptionResponse: + allOf: + - $ref: "#/components/schemas/Subscription" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/MQTTSettings" + + MQTTSettings: + type: object + properties: + topicName: + type: string + maxLength: 256 + description: MQTT topic name + qos: + type: integer + format: int32 + minimum: 0 + maximum: 2 + description: Quality of Service level (0, 1, or 2) + retain: + type: boolean + expiry: + type: integer + format: int32 + minimum: 0 + maximum: 2147483647 + description: Message expiry interval in seconds + userProperties: + type: object + required: + - topicName + + AMQPSubscriptionRequest: + allOf: + - $ref: "#/components/schemas/SubscriptionRequest" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/AMQPSettings" + + AMQPSubscriptionResponse: + allOf: + - $ref: "#/components/schemas/Subscription" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/AMQPSettings" + + AMQPSettings: + type: object + properties: + address: + type: string + maxLength: 512 + linkName: + type: string + maxLength: 256 + senderSettlementMode: + type: string + enum: ["settled", "unsettled"] + linkProperties: + type: object + additionalProperties: + type: string + maxLength: 1024 + + ApacheKafkaSubscriptionRequest: + allOf: + - $ref: "#/components/schemas/SubscriptionRequest" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/ApacheKafkaSettings" + + ApacheKafkaSubscriptionResponse: + allOf: + - $ref: "#/components/schemas/Subscription" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/ApacheKafkaSettings" + + ApacheKafkaSettings: + type: object + properties: + topicName: + type: string + maxLength: 249 + partitionKeyExtractor: + type: string + maxLength: 512 + clientId: + type: string + maxLength: 256 + ackMode: + type: integer + format: int32 + minimum: 0 + maximum: 2 + description: Acknowledgment mode (0=no ack, 1=leader ack, 2=all replicas ack) + required: + - topicName + + NATSSubscriptionRequest: + allOf: + - $ref: "#/components/schemas/SubscriptionRequest" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/NATSSettings" + + NATSSubscriptionResponse: + allOf: + - $ref: "#/components/schemas/Subscription" + - type: object + properties: + protocolSettings: + $ref: "#/components/schemas/NATSSettings" + + NATSSettings: + type: object + properties: + subject: + type: string + maxLength: 256 + description: NATS subject + required: + - subject + + responses: + CreateSubscriptionBadRequest400: + description: Problem with the client request + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 400 + code: + enum: + - INVALID_ARGUMENT + - OUT_OF_RANGE + - INVALID_PROTOCOL + - INVALID_CREDENTIAL + - INVALID_TOKEN + - INVALID_SINK + examples: + GENERIC_400_INVALID_ARGUMENT: + description: Invalid Argument. Generic Syntax Exception + value: + status: 400 + code: INVALID_ARGUMENT + message: Client specified an invalid argument, request body or query param. + GENERIC_400_OUT_OF_RANGE: + description: Out of Range. Specific Syntax Exception used when a given field has a pre-defined range or a invalid filter criteria combination is requested + value: + status: 400 + code: OUT_OF_RANGE + message: Client specified an invalid range. + GENERIC_400_INVALID_PROTOCOL: + description: Invalid protocol for events subscription management + value: + status: 400 + code: INVALID_PROTOCOL + message: Only HTTP is supported + GENERIC_400_INVALID_CREDENTIAL: + description: Invalid sink credential type + value: + status: 400 + code: INVALID_CREDENTIAL + message: Only Access token or Private key JWT are supported + GENERIC_400_INVALID_SINK: + description: Invalid sink value + value: + status: 400 + code: INVALID_SINK + message: sink not valid for the specified protocol + Generic400: + description: Problem with the client request + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 400 + code: + enum: + - INVALID_ARGUMENT + examples: + GENERIC_400_INVALID_ARGUMENT: + description: Invalid Argument. Generic Syntax Exception + value: + status: 400 + code: INVALID_ARGUMENT + message: Client specified an invalid argument, request body or query param. + SubscriptionIdRequired400: + description: Problem with the client request + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 400 + code: + enum: + - INVALID_ARGUMENT + examples: + GENERIC_400_INVALID_ARGUMENT: + description: Invalid Argument. Generic Syntax Exception + value: + status: 400 + code: INVALID_ARGUMENT + message: Client specified an invalid argument, request body or query param. + GENERIC_400_SUBSCRIPTION_ID_REQUIRED: + description: subscription id is required + value: + status: 400 + code: INVALID_ARGUMENT + message: "Expected property is missing: subscriptionId" + Generic401: + description: Authentication problem with the client request + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 401 + code: + enum: + - UNAUTHENTICATED + examples: + GENERIC_401_UNAUTHENTICATED: + description: Request cannot be authenticated and a new authentication is required + value: + status: 401 + code: UNAUTHENTICATED + message: Request not authenticated due to missing, invalid, or expired credentials. A new authentication is required. + Generic403: + description: Client does not have sufficient permission + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 403 + code: + enum: + - PERMISSION_DENIED + examples: + GENERIC_403_PERMISSION_DENIED: + description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + value: + status: 403 + code: PERMISSION_DENIED + message: Client does not have sufficient permissions to perform this action. + SubscriptionPermissionDenied403: + description: Client does not have sufficient permission + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 403 + code: + enum: + - PERMISSION_DENIED + - SUBSCRIPTION_MISMATCH + examples: + GENERIC_403_PERMISSION_DENIED: + description: Permission denied. OAuth2 token access does not have the required scope or when the user fails operational security + value: + status: 403 + code: PERMISSION_DENIED + message: Client does not have sufficient permissions to perform this action. + GENERIC_403_SUBSCRIPTION_MISMATCH: + description: Inconsistent access token for requested subscription + value: + status: 403 + code: "SUBSCRIPTION_MISMATCH" + message: "Inconsistent access token for requested events subscription" + Generic404: + description: Resource Not Found + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 404 + code: + enum: + - NOT_FOUND + examples: + GENERIC_404_NOT_FOUND: + description: Resource is not found + value: + status: 404 + code: NOT_FOUND + message: The specified resource is not found. + Generic409: + description: Conflict + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 409 + code: + enum: + - ABORTED + - ALREADY_EXISTS + examples: + GENERIC_409_ABORTED: + description: Concurrency of processes of the same nature/scope + value: + status: 409 + code: ABORTED + message: Concurrency conflict. + GENERIC_409_ALREADY_EXISTS: + description: Trying to create an existing resource + value: + status: 409 + code: ALREADY_EXISTS + message: The resource that a client tried to create already exists. + Generic410: + description: Gone + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 410 + code: + enum: + - GONE + examples: + GENERIC_410_GONE: + description: Use in notifications flow to allow API Consumer to indicate that its callback is no longer available + value: + status: 410 + code: GONE + message: Access to the target resource is no longer available. + CreateSubscriptionUnprocessableEntity422: + description: Unprocessable Entity + headers: + x-correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 422 + code: + enum: + - SERVICE_NOT_APPLICABLE + - MISSING_IDENTIFIER + - UNSUPPORTED_IDENTIFIER + - UNNECESSARY_IDENTIFIER + - MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED + - MULTIEVENT_COMBINATION_TEMPORARILY_NOT_SUPPORTED + - PRIVATE_KEY_JWT_NOT_CONFIGURED + examples: + GENERIC_422_SERVICE_NOT_APPLICABLE: + description: Service not applicable for the provided identifier + value: + status: 422 + code: SERVICE_NOT_APPLICABLE + message: The service is not available for the provided identifier. + GENERIC_422_MISSING_IDENTIFIER: + description: An identifier is not included in the request and the device or phone number identification cannot be derived from the 3-legged access token + value: + status: 422 + code: MISSING_IDENTIFIER + message: The device cannot be identified. + GENERIC_422_UNSUPPORTED_IDENTIFIER: + description: None of the provided identifiers is supported by the implementation + value: + status: 422 + code: UNSUPPORTED_IDENTIFIER + message: The identifier provided is not supported. + GENERIC_422_UNNECESSARY_IDENTIFIER: + description: An explicit identifier is provided when a device or phone number has already been identified from the access token + value: + status: 422 + code: UNNECESSARY_IDENTIFIER + message: The device is already identified by the access token. + GENERIC_422_MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED: + description: Multi event types subscription is not supported + value: + status: 422 + code: MULTIEVENT_SUBSCRIPTION_NOT_SUPPORTED + message: Multi event types subscription not managed + GENERIC_422_MULTIEVENT_COMBINATION_TEMPORARILY_NOT_SUPPORTED: + description: Combination of multiple event types is temporarily not supported + value: + status: 422 + code: MULTIEVENT_COMBINATION_TEMPORARILY_NOT_SUPPORTED + message: The requested combination of event types is temporarily not supported. + GENERIC_422_PRIVATE_KEY_JWT_NOT_CONFIGURED: + description: Private key JWT sink credential type is used but no configuration was pre-shared + value: + status: 422 + code: PRIVATE_KEY_JWT_NOT_CONFIGURED + message: No JWK Set configured for PRIVATE_KEY_JWT authentication. + Generic429: + description: Too Many Requests + headers: + X-Correlator: + $ref: "#/components/headers/x-correlator" + content: + application/json: + schema: + allOf: + - $ref: "#/components/schemas/ErrorInfo" + - type: object + properties: + status: + enum: + - 429 + code: + enum: + - QUOTA_EXCEEDED + - TOO_MANY_REQUESTS + examples: + GENERIC_429_QUOTA_EXCEEDED: + description: Request is rejected due to exceeding a business quota limit + value: + status: 429 + code: QUOTA_EXCEEDED + message: Out of resource quota. + GENERIC_429_TOO_MANY_REQUESTS: + description: Access to the API has been temporarily blocked due to rate or spike arrest limits being reached + value: + status: 429 + code: TOO_MANY_REQUESTS + message: Rate limit reached.