openapi: 3.0.3 info: title: Sim Swap Subscriptions description: | This API provides the customer with the ability to subscribe to event related to a sim swap operation performed on an associated phone number. # Introduction This API empowers service providers and network operators with a seamless mechanism for managing and monitoring SIM card swaps, a process often used in legitimate device upgrades or replacements but also susceptible to abuse in fraudulent activities. # Relevant terms and definitions * **SIM swap**: A SIM swap is a process in which a mobile phone user's current SIM card is deactivated or replaced with a new one. This is typically done by contacting the user's mobile service provider and requesting a new SIM card for various reasons, such as a lost or damaged SIM card, upgrading to a new phone, or changing phone numbers while keeping the same device. # API Functionality The API exposes following capabilities: * **/subscriptions**: This endpoint has two operations, one that allows to retrieve the list of Sim Swap event subscriptions and another one to create new event subscriptions. * **/subscriptions/{subscriptionId}**: This endpoint also has two operations, one that allows to retrieve a particular event subscription by id and another one to delete an event subscription also using the id. ## Sim Swap notification subscription Theses endpoints allow to manage notification subscription on Sim Swap event. The CAMARA subscription model is detailed in the CAMARA API design guideline document and follows Cloudevents specification. It is mandatory in the subscription to provide the event `types` subscribed are several are managed in this API. Only one event ``types`` is managed for this API: - ``org.camaraproject.sim-swap-subscriptions.v0.swapped`` - Event triggered when a sim swap occurs on the associated phoneNumber Note: Additionally to these list, ``org.camaraproject.sim-swap-subscriptions.v0.subscription-ended`` notification `types` is sent when the subscription ends. This notification does not require dedicated subscription. It is used when: - the subscription expiration time (optionally set by the requester) has been reached - the maximum number of subscription events (optionally set by the requester) has been reached - the subscription was deleted by the requester - the API server has to stop sending notification prematurely - the Access Token sinkCredential expiration time (set by the requester) has been reached ### Notification callback This endpoint describes the event notification received on subscription listener side when the event occurred. As for subscription, detailed description of the event notification is provided in the CAMARA API design guideline document. **WARNING**: This callback endpoint must be exposed on the listener side as `POST /{$request.body#/sink}` will be posted by the sim swap resource server to the webhook url provided by notification listener. ### Data Minimization #### phoneNumber presence: These rules apply for subscription: - If 3-legged access token is used, the POST and GET{id} requests & responses must NOT provide the ``phoneNumber``. For GET (list) only subscription(s) for this exactly phone number is/are retrieved (implicit filtering). - If 2-legged access token is used, for POST and GET{id}, the presence of ``phoneNumber`` in the request & response is mandatory. For GET (list) the device identifier (``phoneNumber``) could be used as filtering criteria. #### sinkCredential presence: ``sinkCredential`` is only present in POST request and not provided in POST or GET response. # Authorization and authentication The "Camara Security and Interoperability Profile" provides details of how an API consumer requests an access token. Please refer to Identity and Consent Management (https://github.com/camaraproject/IdentityAndConsentManagement/) for the released version of the profile. The specific authorization flows to be used will be agreed upon during the onboarding process, happening between the provider of the application consuming the API and the operator's API exposure platform, taking into account the declared purpose for accessing the API, whilst also being subject to the prevailing legal framework dictated by local legislation. In cases where personal data is processed by the API and users can exercise their rights through mechanisms such as opt-in and/or opt-out, the use of three-legged access tokens is mandatory. This ensures that the API remains in compliance with privacy regulations, upholding the principles of transparency and user-centric privacy-by-design. # Identifying the device from the access token This API requires the API consumer to identify a device as the subject of the API as follows: - When the API is invoked using a two-legged access token, the subject will be identified from the optional `phoneNumber` identifier, which therefore MUST be provided. - When a three-legged access token is used however, this optional `phoneNumber` identifier MUST NOT be provided, as the subject will be uniquely identified from the access token. This approach simplifies API usage for API consumers using a three-legged access token to invoke the API by relying on the information that is associated with the access token and was identified during the authentication process. ## Error handling: - If the subject cannot be identified from the access token and the optional `phoneNumber` identifier is not included in the request, then the server will return an error with the `422 MISSING_IDENTIFIER` error code. - If the subject can be identified from the access token and the optional `phoneNumber` identifier is also included in the request, then the server will return an error with the `422 UNNECESSARY_IDENTIFIER` error code. This will be the case even if the same device is identified by these two methods, as the server is unable to make this comparison. # Additional CAMARA error responses The list of error codes in this API specification is not exhaustive. Therefore the API specification may not document some non-mandatory error statuses as indicated in `CAMARA API Design Guide`. Please refer to the `CAMARA_common.yaml` of the Commonalities Release associated to this API version for a complete list of error responses. The applicable Commonalities Release can be identified in the `API Readiness Checklist` document associated to this API version. As a specific rule, error `501 - NOT_IMPLEMENTED` can be only a possible error response if it is explicitly documented in the API. # Further info and support (FAQs will be added in a later version of the documentation) license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html version: wip x-camara-commonalities: 0.6 externalDocs: description: Product documentation at CAMARA url: https://github.com/camaraproject/ servers: - url: '{apiRoot}/sim-swap-subscriptions/vwip' variables: apiRoot: default: http://localhost:9091 description: API root tags: - name: Sim Swap Subscription description: Operation to manage event subscription on sim swap event (swapped) paths: /subscriptions: post: tags: - Sim Swap Subscription summary: 'Create a sim swap event subscription for a phone number' description: Create a sim swap event subscription for a phone number operationId: createSimSwapSubscription parameters: - $ref: "#/components/parameters/x-correlator" security: - openId: - sim-swap-subscriptions:org.camaraproject.sim-swap-subscriptions.v0.swapped:create requestBody: content: application/json: schema: $ref: "#/components/schemas/SubscriptionRequest" examples: SUBSCRIPTION_REQUEST: $ref: '#/components/examples/SUBSCRIPTION_REQUEST' SUBSCRIPTION_REQUEST_3LEGS: $ref: '#/components/examples/SUBSCRIPTION_REQUEST_3LEGS' required: true callbacks: notifications: "{$request.body#/sink}": post: summary: "notifications callback" description: | Important: this endpoint is to be implemented by the API consumer. The sim swap server will call this endpoint whenever a swapped event occurs. operationId: postNotification parameters: - $ref: "#/components/parameters/x-correlator" requestBody: required: true content: application/cloudevents+json: schema: $ref: "#/components/schemas/CloudEvent" examples: SWAPPED: $ref: '#/components/examples/SWAPPED' SUBSCRIPTION_ENDS: $ref: '#/components/examples/SUBSCRIPTION_ENDS' 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" examples: SUBSCRIPTION_RESPONSE: $ref: '#/components/examples/SUBSCRIPTION_RESPONSE' SUBSCRIPTION_RESPONSE_3LEGS: $ref: '#/components/examples/SUBSCRIPTION_RESPONSE_3LEGS' "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: - Sim Swap Subscription summary: 'Retrieve a list of sim swap event subscription' description: Retrieve a list of sim swap event subscription(s) operationId: retrieveSubscriptionList parameters: - $ref: "#/components/parameters/x-correlator" security: - openId: - sim-swap-subscriptions: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 items: $ref: '#/components/schemas/Subscription' examples: SUBSCRIPTIONS: $ref: '#/components/examples/SUBSCRIPTIONS' SUBSCRIPTIONS_3LEGS: $ref: '#/components/examples/SUBSCRIPTIONS_3LEGS' "400": $ref: "#/components/responses/Generic400" "401": $ref: "#/components/responses/Generic401" "403": $ref: "#/components/responses/Generic403" /subscriptions/{subscriptionId}: get: tags: - Sim Swap Subscription summary: 'Retrieve a sim swap event subscription for a phone number' description: retrieve event subscription information for a given subscription. operationId: retrieveSubscription security: - openId: - sim-swap-subscriptions: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" examples: SUBSCRIPTION: $ref: '#/components/examples/SUBSCRIPTION_RESPONSE' SUBSCRIPTION_3LEGS: $ref: '#/components/examples/SUBSCRIPTION_RESPONSE_3LEGS' "400": $ref: "#/components/responses/SubscriptionIdRequired400" "401": $ref: "#/components/responses/Generic401" "403": $ref: "#/components/responses/Generic403" "404": $ref: "#/components/responses/Generic404" delete: tags: - Sim Swap Subscription summary: 'Delete a sim swap event subscription' operationId: deleteSubscription description: delete a given event subscription. security: - openId: - sim-swap-subscriptions:delete parameters: - $ref: "#/components/parameters/SubscriptionId" - $ref: "#/components/parameters/x-correlator" responses: "204": description: Sim swap notification 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 notificationsBearerAuth: type: http scheme: bearer bearerFormat: "{$request.body#/sinkCredential.credentialType}" 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: XCorrelator: type: string pattern: ^[a-zA-Z0-9-_:;.\/<>{}]{0,256}$ example: "b4333c46-49c0-4f62-80d7-f0ef930f1c46" PhoneNumber: type: string pattern: '^\+[1-9][0-9]{4,14}$' example: '+123456789' description: A public identifier addressing a telephone subscription. In mobile networks it corresponds to the MSISDN (Mobile Station International Subscriber Directory Number). In order to be globally unique it has to be formatted in international format, according to E.164 standard, prefixed with '+'. ErrorInfo: type: object required: - status - code - message properties: status: type: integer description: HTTP response status code code: type: string description: A human-readable code to describe the error message: type: string description: A human-readable description of what the event represents SubscriptionRequest: description: The request for creating a sim swap event subscription type: object required: - sink - protocol - config - types properties: protocol: $ref: "#/components/schemas/Protocol" sink: type: string format: uri 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 for subscription: - org.camaraproject.sim-swap-subscriptions.v0.swapped: receive a notification when a sim swap is performed on the line. type: array minItems: 1 maxItems: 1 items: $ref: "#/components/schemas/SubscriptionEventType" 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" SubscriptionEventType: type: string description: | swapped - Event triggered when a sim swap occurs on the line enum: - org.camaraproject.sim-swap-subscriptions.v0.swapped 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` or `subscriptionMaxEvents` to limit subscription lifetime. Event type attributes must be defined in `subscriptionDetail` type: object required: - subscriptionDetail properties: subscriptionDetail: $ref: "#/components/schemas/CreateSubscriptionDetail" subscriptionExpireTime: type: string format: date-time example: 2025-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. subscriptionMaxEvents: type: integer 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. minimum: 1 example: 5 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 - REFRESHTOKEN description: "The type of the credential. With the current API version the type MUST be set to ACCESSTOKEN." discriminator: propertyName: credentialType mapping: PLAIN: "#/components/schemas/PlainCredential" ACCESSTOKEN: "#/components/schemas/AccessTokenCredential" REFRESHTOKEN: "#/components/schemas/RefreshTokenCredential" 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 secret: description: The secret might be a password or passphrase. type: string AccessTokenCredential: type: object description: An access token credential. allOf: - $ref: "#/components/schemas/SinkCredential" - type: object properties: accessToken: description: REQUIRED. An access token is a previously acquired token granting access to the target resource. type: string accessTokenExpiresUtc: type: string format: date-time 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. 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 RefreshTokenCredential: type: object description: An access token credential with a refresh token. allOf: - $ref: "#/components/schemas/SinkCredential" - type: object properties: accessToken: description: REQUIRED. An access token is a previously acquired token granting access to the target resource. type: string accessTokenExpiresUtc: type: string format: date-time 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. 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 refreshToken: description: REQUIRED. An refresh token credential used to acquire access tokens. type: string refreshTokenEndpoint: type: string format: uri description: REQUIRED. A URL at which the refresh token can be traded for an access token. required: - accessToken - accessTokenExpiresUtc - accessTokenType - refreshToken - refreshTokenEndpoint SubscriptionDetail: description: The detail of the requested event subscription type: object required: - phoneNumber properties: phoneNumber: $ref: '#/components/schemas/PhoneNumber' CreateSubscriptionDetail: description: The detail of the requested event subscription type: object properties: phoneNumber: $ref: '#/components/schemas/PhoneNumber' SimSwapNotificationEventType: type: string description: | swapped - Event triggered when a sim swap was performed for this phone number - 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.sim-swap-subscriptions.v0.swapped - org.camaraproject.api-name.v0.subscription-started - org.camaraproject.api-name.v0.subscription-updated - org.camaraproject.sim-swap-subscriptions.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 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 for subscription: - org.camaraproject.sim-swap-subscriptions.v0.swapped: receive a notification when a sim swap is performed on the line. Note: for the Commonalities meta-release v0.4 we enforce to have only event type per subscription then for following meta-release use of array MUST be decided at API project level. type: array minItems: 1 maxItems: 1 items: $ref: "#/components/schemas/SubscriptionEventType" config: $ref: '#/components/schemas/Config' id: $ref: "#/components/schemas/SubscriptionId" startsAt: 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. type: string format: date-time example: "2023-07-03T12:27:08.312Z" expiresAt: type: string format: date-time 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` 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 metainformation 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 properties: id: $ref: "#/components/schemas/SubscriptionId" SubscriptionId: type: string description: The unique identifier of the subscription in the scope of the subscription manager. When this information is contained within an event notification, this concept SHALL be referred as subscriptionId as per Commonalities Event Notification Model. example: qs15-h556-rt89-1298 CloudEvent: description: The notification callback required: - id - source - specversion - type - time properties: id: type: string description: identifier of this event, that must be unique in the source context. source: $ref: "#/components/schemas/Source" type: $ref: "#/components/schemas/SimSwapNotificationEventType" 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.sim-swap-subscriptions.v0.swapped: '#/components/schemas/EventSimSwap' org.camaraproject.sim-swap-subscriptions.v0.subscription-started: "#/components/schemas/EventSubscriptionStarted" org.camaraproject.sim-swap-subscriptions.v0.subscription-updated: "#/components/schemas/EventSubscriptionUpdated" org.camaraproject.sim-swap-subscriptions.v0.subscription-ended: '#/components/schemas/EventSubscriptionEnded' Source: type: string format: uri-reference minLength: 1 description: | Identifies the context in which an event happened, as 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.supertelco.com" DateTime: type: string format: date-time 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" EventSimSwap: description: event structure for event sim swapped allOf: - $ref: "#/components/schemas/CloudEvent" - type: object properties: data: $ref: "#/components/schemas/Swapped" EventSubscriptionStarted: description: event structure for event subscription started allOf: - $ref: "#/components/schemas/CloudEvent" - 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 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/CloudEvent" - 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 UpdateReason: type: string description: | - SUBSCRIPTION_ACTIVE - API server transitioned susbcription status to `ACTIVE` - SUBSCRIPTION_INACTIVE - API server transitioned susbcription 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" Swapped: description: Event detail structure for ROAMING_ON & ROAMING_OFF event type: object required: - subscriptionId properties: phoneNumber: $ref: '#/components/schemas/PhoneNumber' subscriptionId: $ref: "#/components/schemas/SubscriptionId" 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: description: Explanation why a subscription ended or had to end. type: string 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) 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 HTTPSubscriptionRequest: allOf: - $ref: "#/components/schemas/SubscriptionRequest" - type: object properties: protocolSettings: $ref: "#/components/schemas/HTTPSettings" HTTPSubscriptionResponse: allOf: - $ref: "#/components/schemas/Subscription" - type: object properties: protocolSettings: $ref: "#/components/schemas/HTTPSettings" HTTPSettings: type: object 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 under the scope of Meta Release v0.4. 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 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 qos: type: integer format: int32 retain: type: boolean expiry: type: integer format: int32 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 linkName: type: string senderSettlementMode: type: string enum: ["settled", "unsettled"] linkProperties: type: object additionalProperties: type: string 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 partitionKeyExtractor: type: string clientId: type: string ackMode: type: integer 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 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 is supported GENERIC_400_INVALID_TOKEN: description: Invalid token type for sink credential of type ACCESSTOKEN value: status: 400 code: INVALID_TOKEN message: Only bearer token is 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 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. 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: Concurreny 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 - UNNECESSARY_IDENTIFIER 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_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. 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. examples: SWAPPED: value: id: "123655" source: supertelco.notificationSendServer12 type: org.camaraproject.sim-swap-subscriptions.v0.swapped specversion: "1.0" datacontenttype: application/json data: phoneNumber: "+123456788" subscriptionId: 2ghy-55gg-7iup-yuo9 time: 2023-01-18T13:18:23.682Z SUBSCRIPTION_ENDS: value: id: "123658" source: supertelco.notificationSendServer12 type: org.camaraproject.sim-swap-subscriptions.v0.subscription-ended specversion: "1.0" datacontenttype: application/json data: phoneNumber: "+123456789" terminationReason: SUBSCRIPTION_EXPIRED subscriptionId: 2ghy-55gg-7iup-yuo9 terminationDescription: subscription expire time reached time: 2023-01-19T13:18:23.682Z SUBSCRIPTION_REQUEST: value: protocol: HTTP sink: https://endpoint.example.com/sink sinkCredential: credentialType: ACCESSTOKEN accessToken: "yJ2ZXIiOiIxLjAiLCJ0eXAiO..." accessTokenExpiresUtc: "1717753038" accessTokenType: "bearer" types: - org.camaraproject.sim-swap-subscriptions.v0.swapped config: subscriptionDetail: phoneNumber: "+123456789" subscriptionMaxEvents: 10 subscriptionExpireTime: '2025-01-17T13:18:23.682Z' SUBSCRIPTION_REQUEST_3LEGS: value: protocol: HTTP sink: https://endpoint.example.com/sink sinkCredential: credentialType: ACCESSTOKEN accessToken: "yJ2ZXIiOiIxLjAiLCJ0eXAiO..." accessTokenExpiresUtc: "1717753038" accessTokenType: "bearer" types: - org.camaraproject.sim-swap-subscriptions.v0.swapped config: subscriptionDetail: {} subscriptionExpireTime: '2025-01-17T13:18:23.682Z' SUBSCRIPTION_RESPONSE: value: protocol: HTTP sink: https://endpoint.example.com/sink types: - org.camaraproject.sim-swap-subscriptions.v0.swapped config: subscriptionDetail: phoneNumber: "+123456789" subscriptionExpireTime: '2025-01-17T13:18:23.682Z' id: '1119920371' startsAt: '2024-06-07T16:10:15.302Z' expiresAt: '2024-06-07T16:10:15.302Z' status: ACTIVATION_REQUESTED SUBSCRIPTION_RESPONSE_3LEGS: value: protocol: HTTP sink: https://endpoint.example.com/sink types: - org.camaraproject.sim-swap-subscriptions.v0.swapped config: subscriptionDetail: {} subscriptionExpireTime: '2025-01-17T13:18:23.682Z' id: '1119920371' startsAt: '2024-06-07T16:10:15.302Z' expiresAt: '2024-06-07T16:10:15.302Z' status: ACTIVATION_REQUESTED SUBSCRIPTIONS: value: - protocol: HTTP sink: https://endpoint.example.com/sink types: - org.camaraproject.sim-swap-subscriptions.v0.swapped config: subscriptionDetail: phoneNumber: "+123456789" subscriptionExpireTime: '2025-01-17T13:18:23.682Z' id: '1119920371' startsAt: '2024-06-07T16:10:15.302Z' expiresAt: '2024-06-07T16:10:15.302Z' status: ACTIVATION_REQUESTED SUBSCRIPTIONS_3LEGS: value: - protocol: HTTP sink: https://endpoint.example.com/sink types: - org.camaraproject.sim-swap-subscriptions.v0.swapped config: subscriptionDetail: {} subscriptionExpireTime: '2025-01-17T13:18:23.682Z' id: '1119920371' startsAt: '2024-06-07T16:10:15.302Z' expiresAt: '2024-06-07T16:10:15.302Z' status: ACTIVATION_REQUESTED