diff --git a/ovs_hub_ntf/v1/OVS_HUB_NTF_v1.0.0.yaml b/ovs_hub_ntf/v1/OVS_HUB_NTF_v1.0.0.yaml index 8310cbbf..2a0cf991 100644 --- a/ovs_hub_ntf/v1/OVS_HUB_NTF_v1.0.0.yaml +++ b/ovs_hub_ntf/v1/OVS_HUB_NTF_v1.0.0.yaml @@ -10,6 +10,22 @@ info: It is also possible to set up subscriptions. A subscription can be set up to push events to a callbackUrl defined as part of the subscription or by an email. It is not possible to define the email as part of the subscription - the email used is the email address associated with the authenticated user. Subscriptions support sending notifications for all changes the customer is authorized to see. It is possible to only send notifications for specific events - in order to do so - filters must be used when setting up a subscription. See the [subscription](https://app.swaggerhub.com/apis/dcsaorg/DCSA_OVS_NTF/1.0.0#/Subscription) section for more info. + + Two kinds of authentication are supported: + 1. Callback authentication configured: + - OVS Hub authenticates when calling the callback. + - A shared secret is not required. + - When no shared secret is configured, `Request-Id` and `Signature-Timestamp` are optional, and `Notification-Signature` is not sent. + - When a shared secret is also configured, all three headers are sent and validated. + + 2. No callback authentication configured: + - A shared secret is required. + - HMAC signature verification is required. + - `Request-Id`, `Signature-Timestamp` and `Notification-Signature` headers must be sent. + + If no `secret` is provided for a callback subscription, callback authentication **MUST** already be configured. The absence of a secret does not by itself demonstrate that callback authentication is available. + + **Note:** A subscription with neither callback authentication nor a shared secret must not be active for callback delivery. contact: name: Digital Container Shipping Association (DCSA) url: 'https://dcsa.org' @@ -23,7 +39,7 @@ tags: Endpoints implemented by the OVS Hub for the customer to set up subscriptions - name: Secret description: | - Endpoint implemented by the OVS Hub for the customer to update the secret + Endpoint implemented by the OVS Hub for the customer to set, replace, or remove the secret paths: '/{callbackUrl}': post: @@ -31,10 +47,7 @@ paths: - Notification summary: Send notification operationId: post-notification - description: | - Creates a new `Notification`. This endpoint is called whenever a `Service`, `Vessel` or `Location` that a consumer has subscribed to is updated. The `callbackUrl` is defined as part of the subscription. - - **👉 Important:** This endpoint is to be implemented by a **consumer** of the **OVS Hub API** in order to **receive Notifications**. + description: "Creates a new `Notification`. This endpoint is called whenever a `Service`, `Vessel` or `Location` that a consumer has subscribed to is updated. The `callbackUrl` is defined as part of the subscription.\n\n **\U0001F449 Important:** This endpoint is to be implemented by a **consumer** of the **OVS Hub API** in order to **receive Notifications**.\n" parameters: - name: callbackUrl in: path @@ -42,65 +55,60 @@ paths: description: | The endpoint specifying where OVS Hub sends the notification to the customer. The callback can contain customer defined query parameters. - The `callbackUrl` **MUST** be an open endpoint for OVS Hub to call when sending a notification. OVS Hub does not send any authentication information apart from what is in the `callbackUrl`. The receiver **MUST** validate the authenticity of the notification by looking at the `Notification-Signature` header. + The callback endpoint **MAY** require authentication. When callback authentication is configured, OVS Hub authenticates using the configured authentication mechanism. When callback authentication is not configured, the subscription **MUST** contain a shared secret, and the receiver **MUST** validate `Request-Id`, `Signature-Timestamp`, and `Notification-Signature`. schema: type: string format: uri - example: https://myserver.com/send/callback/here?myInternalId=123 + example: 'https://myserver.com/send/callback/here?myInternalId=123' - name: Request-Id in: header - required: true description: | - The `Request-Id` which is included in the encoded `Notification-Signature`. - - When receiving a notification the receiver **MUST** validate the "uniqueness" of the `Request-Id`. If a notification has already been sent with the `Request-Id` then the request **MUST** be rejected. + When a shared secret is configured, this header **MUST** be included, and the receiver **MUST** validate its uniqueness. A request containing a previously received `Request-Id` **MUST** be rejected. - **Note:** It is not necessary to store the `Request-Id` for more than 5 minutes as all other cases are covered by the `Signature-Timestamp` header + When no shared secret is configured, this header is optional. If provided, it may be used for tracing or deduplication, but it does not provide proof of authenticity. schema: type: string format: ulid example: 01KKH4JGKBPT6J9VJX1WXKWPGK - name: Signature-Timestamp in: header - required: true description: | - The `Signature-Timestamp` which is included in the encoded `Notification-Signature`. - - When receiving a notification the receiver **MUST** validate the "freshness" of the timestamp. If it is older than 5 minutes, or too far in the future, it **MUST** be rejected. + When a shared secret is configured, this header **MUST** be included, and the receiver **MUST** validate its freshness. A timestamp older than five minutes or too far in the future **MUST** be rejected: abs(now_utc - timestamp_utc) <= 300 seconds - **Note:** This value is to be used when calculating the `Notification-Signature` on the receiver side. + When no shared secret is configured, this header is optional. If provided, it does not provide proof of authenticity. schema: type: string format: date-time - example: 2025-01-23T01:23:45Z + example: '2025-01-23T01:23:45Z' - name: Notification-Signature in: header - required: true description: | The `Notification-Signature` is used to more confidently verify whether requests from OVS Hub are authentic. The header has the following format: Notification-Signature: sha256= - When OVS Hub sends a notification, the notification **MUST** be checked to make sure it's authentic. This is done by computing a signature. + When a shared secret is configured, OVS Hub **MUST** calculate and include this header, and the receiver **MUST** verify the authenticity of the notification by calculating the expected signature and comparing it with the supplied `Notification-Signature`. + + When no shared secret is configured, callback authentication provides authenticity. OVS Hub **MUST NOT** calculate or include the `Notification-Signature` header. The `signature` is calculated by calculating a **HMAC_SHA256** using the `secret` (defined when setting up a subscription) on the `Signature-Timestamp` header (*unredacted*) concatenated with a dot (`.`) concatenated with the `Request-Id` header concatenated with a dot (`.`) concatenated with the `request body` signature = HMAC_SHA256(secret, Signature-Timestamp + "." + Request-Id + "." + request-body) The signature **MUST** cover the entire request body of the request. Before the signature is created the request body **MUST** be in the [RFC 8785](https://datatracker.ietf.org/doc/html/rfc8785) canonical form. The content **MUST** be decoded into bytes using the UTF-8 encoding before computing the signature. - + **Note:** None of the HTTP headers nor the request URL is covered by the signature. ## Example - + A concrete example of how the `Notification-Signature` header could look like for: * `secret`: OWY4YzdhNGQ= * `Signature-Timestamp`: March 12, 2026 at 14:47:00Z * `Request-Id`: 01KKH4JGKBPT6J9VJX1WXKWPGK * `request-body`: {"lastName":"Doe" , "firstName":"John", "age":40} - + would be: signature = HMAC_SHA256(Base64Decode(OWY4YzdhNGQ=), '2026-03-12T14:47:00Z.01KKH4JGKBPT6J9VJX1WXKWPGK.{"age":40,"firstName":"John","lastName":"Doe"}') @@ -110,7 +118,7 @@ paths: Notification-Signature: sha256=8d3a7837713e319d1466139903ffd5b1b8d96f6a769f6d53c03a29dc5c3f3630 schema: type: string - pattern: ^sha256=[A-Fa-f0-9]{64}$ + pattern: '^sha256=[A-Fa-f0-9]{64}$' maxLength: 71 minLength: 71 example: sha256=8d3a7837713e319d1466139903ffd5b1b8d96f6a769f6d53c03a29dc5c3f3630 @@ -221,7 +229,7 @@ paths: If `callbackUrl` is specified, when setting up a subscription, the notification will be pushed to the POST {{callbackUrl}} - + endpoint of the consumer. If `callbackUrl` is omitted as part of the subscription, a notification will be sent via email to the authenticated user. Email is defined as part of the user-profile. When a notification is sent, it is the responsibility of the consumer to go to OVS Hub, either via the API or the UI, to get more information. @@ -230,19 +238,19 @@ paths: requestBody: description: | The parameters used to configure the subscription and send notifications. - + All values in the subscription (except: `callbackUrl` and `secret`) will be used as filters when sending notifications. All specified filters must be met in order for a notification to be sent. A logical **AND** is used between filters. So specifying - + carrierServiceCode = 'FE1' //in a carrierService object AND vesselIMONumbers = '12345678' - + means that the notifications sent for this subscription **MUST** be for service `FE1` (*carrierServiceCode='FE1'* inside a *carrierService* object) **and** vessel IMO `12345678` (*vesselIMONumber='12345678'*). If all filters are not fulfilled - then the notification will not be sent. - + Filters that are specified as lists use logical **OR** between list values. So - + carrierServices = [{carrierServiceCode: 'FE1'},{carrierServiceCode: 'DR02', carrierSMDGCode: 'YML'}] - + means that notifications sent will match **either** `FE1` carrierServiceCode (from any carrier) **OR** `DR02` carrierServiceCode (belonging to YML). required: true content: @@ -261,12 +269,22 @@ paths: The notification is only triggered when changes occur to `vesselIMONumber`: 9321483 or 9929429 that occur maximum 1 week in the future (`weekRange` = 1) value: notificationChannel: - callbackUrl: https://api.myserver.com/notifications?myId=123 + callbackUrl: 'https://api.myserver.com/notifications?myId=123' secret: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDM2NTc4NjIzODk3NDY5MDgyNzM0OTg3MTIzNzg2NA== weekRange: 1 vesselIMONumbers: - '9321483' - '9929429' + authenticatedCallbackExample: + summary: Authenticated callback without HMAC signing + description: | + Callback authentication is configured separately. No shared secret is provided, so signature headers are not sent. + value: + notificationChannel: + callbackUrl: 'https://api.myserver.com/notifications' + weekRange: 1 + vesselIMONumbers: + - '9321483' emailAllExample: summary: | Subscription using emails to be notified about everything @@ -350,7 +368,7 @@ paths: - errorCode: 7003 errorCodeText: Max number of subscriptions created errorCodeMessage: A maximum of 10 subscriptions can be created per hour - /subscriptions/{subscriptionReference}: + '/subscriptions/{subscriptionReference}': get: tags: - Subscription @@ -404,7 +422,7 @@ paths: **NB**: `errorCode` not yet standardized by DCSA. Value `7003` is just a "random example" value: httpMethod: GET - requestUri: /subscriptions/{subscriptionReference} + requestUri: '/subscriptions/{subscriptionReference}' statusCode: 429 statusCodeText: Too Many Requests statusCodeMessage: | @@ -464,7 +482,7 @@ paths: **NB**: `errorCode` not yet standardized by DCSA. Value `7003` is just a "random example" value: httpMethod: DELETE - requestUri: /subscriptions/{subscriptionReference} + requestUri: '/subscriptions/{subscriptionReference}' statusCode: 429 statusCodeText: Too Many Requests statusCodeMessage: | @@ -535,7 +553,7 @@ paths: **NB**: `errorCode` not yet standardized by DCSA. Value `7003` is just a "random example" value: httpMethod: PUT - requestUri: /subscriptions/{subscriptionReference} + requestUri: '/subscriptions/{subscriptionReference}' statusCode: 429 statusCodeText: Too Many Requests statusCodeMessage: | @@ -546,14 +564,20 @@ paths: - errorCode: 7003 errorCodeText: Maximum number of subscription requests errorCodeMessage: A maximum of 10 subscription update requests can be made per hour - /subscriptions/{subscriptionReference}/secret: + '/subscriptions/{subscriptionReference}/secret': put: tags: - Secret - summary: Resets the Secret on an existing subscription + summary: 'Sets, replaces, or removes the secret on an existing subscription' operationId: put-secret description: | - Updates the secret of subscription with `subscriptionReference`. + Sets, replaces, or removes the subscription's shared secret. + + Supplying a non-null value sets or replaces the shared secret. + + Supplying `null` removes the existing secret. The request **MUST** be rejected with `400 Bad Request` if the subscription uses a `callbackUrl` and callback authentication is not configured. + + After the secret is removed, OVS Hub **MUST NOT** calculate or send `Notification-Signature` for the subscription. `Request-Id` and `Signature-Timestamp` MAY still be sent for tracing or deduplication, but they do not provide proof of authenticity. parameters: - name: subscriptionReference in: path @@ -577,16 +601,58 @@ paths: secret: type: string format: byte + nullable: true + minLength: 1 + maxLength: 1024 description: | - A Base64 encoded secret sent to the OVS Hub from the customer. - It is used to compute the contents of the `Notification-Signature` header every time a notification is sent. - example: 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDM2NTc4NjIzODk3NDY5MDgyNzM0OTg3MTIzNzg2NA==' + A Base64-encoded shared secret used to calculate the `Notification-Signature`. + + Provide a non-null, non-empty value to set or replace the subscription secret. + + Provide `null` to remove the existing secret. + + After the secret is removed, OVS Hub does not calculate or send `Notification-Signature`. + example: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDM2NTc4NjIzODk3NDY5MDgyNzM0OTg3MTIzNzg2NA== + required: + - secret + examples: + setSecretExample: + summary: Set or replace the shared secret + value: + secret: MTIzNDU2Nzg5MDEyMzQ1Njc4OTA= + removeSecretExample: + summary: Remove the shared secret + value: + secret: null responses: '204': - description: Secret updated + description: 'Secret set, replaced, or removed.' headers: API-Version: $ref: '#/components/headers/API-Version' + '400': + description: | + The secret could not be removed because doing so would leave the callback subscription without an authenticity mechanism. + headers: + API-Version: + $ref: '#/components/headers/API-Version' + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + httpMethod: PUT + requestUri: /subscriptions/01KJZDQ1CC6HQYP8V2NE2MPRNC/secret + statusCode: 400 + statusCodeText: Bad Request + statusCodeMessage: | + The shared secret cannot be removed because callback authentication is not configured for this subscription. + providerCorrelationReference: 4426d965-0dd8-4005-8c63-dc68b01c4962 + errorDateTime: '2026-09-23T09:41:00Z' + errors: + - errorCodeText: callbackAuthenticationRequired + errorCodeMessage: | + Configure callback authentication before removing the subscription's shared secret. default: description: | For other errors the error object should be populated with relevant information @@ -611,7 +677,7 @@ paths: **NB**: `errorCode` not yet standardized by DCSA. Value `7003` is just a "random example" value: httpMethod: PUT - requestUri: /subscriptions/{subscriptionReference}/secret + requestUri: '/subscriptions/{subscriptionReference}/secret' statusCode: 429 statusCodeText: Too Many Requests statusCodeMessage: | @@ -622,7 +688,6 @@ paths: - errorCode: 7003 errorCodeText: Max number of subscriptions secret requests errorCodeMessage: A maximum of 10 subscription secret update requests can be made per hour - components: headers: API-Version: @@ -661,8 +726,8 @@ components: type: object description: | Defines the channel where a matched notification is sent. At least one of the possible properties **MUST** be provided: - - `callbackUrl` - - `useEmail` + - `callbackUrl`, together with either callback authentication or an associated shared secret; or + - `useEmail`. properties: callbackUrl: type: string @@ -670,10 +735,16 @@ components: description: | The endpoint where OVS Hub should send the notification to the customer. The callback can contain query parameters uniquely identifying the originator of the events. - The `callbackUrl` **MUST** be an open endpoint for OVS Hub to call when sending a notification. The receiver **MUST** validate the authenticity of the notification by looking at the `Notification-Signature` header. + The callback endpoint **MAY** require authentication. + + If callback authentication is configured, a shared secret is optional. When no shared secret is associated with the subscription, OVS Hub does not calculate or send the `Notification-Signature` header. + + If callback authentication is not configured, a shared secret **MUST** be associated with the subscription. OVS Hub then sends the `Request-Id`, `Signature-Timestamp`, and `Notification-Signature` headers, and the receiver **MUST** validate them. + + A callback subscription **MUST NOT** be used for delivery unless either callback authentication is configured or a shared secret is associated with the subscription. - **Condition:** If `callbackUrl` is provided, the `secret` property must also be provided. It can be updated via the [update-secret](https://app.swaggerhub.com/apis/dcsaorg/DCSA_OVS_NTF/1.0.0#/Secret/put-secret) endpoint. - example: https://myserver.com/send/callback/here?shipperRef=myID123 + The shared secret can be set, replaced, or removed using the [secret endpoint](https://app.swaggerhub.com/apis/dcsaorg/DCSA_OVS_NTF/1.0.0#/Secret/put-secret). + example: 'https://myserver.com/send/callback/here?shipperRef=myID123' useEmail: type: boolean description: | @@ -701,7 +772,7 @@ components: properties: carrierServiceCode: type: string - pattern: ^\S(?:.*\S)?$ + pattern: '^\S(?:.*\S)?$' maxLength: 11 description: | The carrier-specific code of the service for which the schedule details are published. @@ -728,7 +799,7 @@ components: If this property is empty, you will be notified for all `universalServiceReferences` that have changes you are authorized to see. items: type: string - pattern: ^SR\d{5}[A-Z]$ + pattern: '^SR\d{5}[A-Z]$' maxLength: 8 minLength: 8 example: SR12345A @@ -749,7 +820,7 @@ components: The name of the Vessel given by the Vessel Operator and registered with IMO. **Note:** In case the vessel is a "dummy vessel" (`isDummyVessel='true'`) then the following recommendations should be followed: - + Dummy vessel names should begin with the **SMDG Operating Carrier Code** to ensure uniqueness across carriers. The suffix can be **alphanumeric** and up to **10 characters long**, allowing each carrier to use internal naming conventions (e.g., `MSKTBN1`, `CMATEMP01`, `MSCX01A`). @@ -770,7 +841,7 @@ components: If this property is empty, you will be notified for all `vesselIMONumbers` that have changes you are authorized to see. items: type: string - pattern: ^\d{7,8}$ + pattern: '^\d{7,8}$' minLength: 7 maxLength: 8 description: | @@ -789,7 +860,7 @@ components: If this property is empty, you will be notified for all `MMSINumbers` that have changes you are authorized to see. items: type: string - pattern: ^\d{9}$ + pattern: '^\d{9}$' minLength: 9 maxLength: 9 description: | @@ -816,7 +887,7 @@ components: properties: UNLocationCode: type: string - pattern: ^[A-Z]{2}[A-Z2-9]{3}$ + pattern: '^[A-Z]{2}[A-Z2-9]{3}$' minLength: 5 maxLength: 5 description: | @@ -848,10 +919,9 @@ components: - subscriptionReference - notificationChannel - weekRange - SubscriptionBodyWithSecret: type: object - title: Subscription with Secret + title: Subscription Create description: | Subscription containing all information needed in order to create a subscription: notificationChannel, filters, range, etc properties: @@ -860,29 +930,35 @@ components: title: Notification Channel description: | Defines the channel where a matched notification is sent. At least one of the possible properties **MUST** be provided: - - `callbackUrl` and `secret` + - `callbackUrl`, together with either callback authentication or a shared `secret`; or - `useEmail` properties: callbackUrl: type: string format: uri description: | - The endpoint where OVS Hub should send the notification to the customer. The callback can contain query parameters uniquely identifying the originator of the events. + The endpoint where OVS Hub sends notifications to the customer. The callback URL can contain query parameters that uniquely identify the originator of the events. + + The callback endpoint **MAY** require authentication. - The `callbackUrl` **MUST** be an open endpoint for OVS Hub to call when sending a notification. The receiver **MUST** validate the authenticity of the notification by looking at the `Notification-Signature` header. + If callback authentication is configured, the `secret` property is optional. When `secret` is omitted, OVS Hub does not calculate or send the `Notification-Signature` header. - **Condition:** If `callbackUrl` is provided then `secret` property is mandatory to provide also. - example: https://myserver.com/send/callback/here?shipperRef=myID123 + If callback authentication is not configured, the `secret` property **MUST** be provided. OVS Hub then sends the `Request-Id`, `Signature-Timestamp`, and `Notification-Signature` headers, and the receiver **MUST** validate them. + + A callback subscription **MUST NOT** be created unless either callback authentication is configured or the `secret` property is provided. + example: 'https://myserver.com/send/callback/here?shipperRef=myID123' secret: type: string format: byte + minLength: 1 maxLength: 1024 description: | - A Base64 encoded secret sent to the OVS Hub from the customer. - It is used to compute the contents of the `Notification-Signature` header every time a notification is sent. + A Base64-encoded shared secret used to calculate the `Notification-Signature` header. + + This property is required when `callbackUrl` is provided and callback authentication is not configured (this is defined outside scope of the API). - **Condition:** If `callbackUrl` is provided then this property is mandatory to provide. - example: 'MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDM2NTc4NjIzODk3NDY5MDgyNzM0OTg3MTIzNzg2NA==' + When callback authentication is configured, this property may be omitted. In that case, OVS Hub does not calculate or send a `Notification-Signature`. + example: MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDM2NTc4NjIzODk3NDY5MDgyNzM0OTg3MTIzNzg2NA== useEmail: type: boolean description: | @@ -910,7 +986,7 @@ components: properties: carrierServiceCode: type: string - pattern: ^\S(?:.*\S)?$ + pattern: '^\S(?:.*\S)?$' maxLength: 11 description: | The carrier-specific code of the service for which the schedule details are published. @@ -940,7 +1016,7 @@ components: If this property is empty, you will be notified for all `universalServiceReferences` that have changes you are authorized to see. items: type: string - pattern: ^SR\d{5}[A-Z]$ + pattern: '^SR\d{5}[A-Z]$' maxLength: 8 minLength: 8 example: SR12345A @@ -961,7 +1037,7 @@ components: The name of the Vessel given by the Vessel Operator and registered with IMO. **Note:** In case the vessel is a "dummy vessel" (`isDummyVessel='true'`) then the following recommendations should be followed: - + Dummy vessel names should begin with the **SMDG Operating Carrier Code** to ensure uniqueness across carriers. The suffix can be **alphanumeric** and up to **10 characters long**, allowing each carrier to use internal naming conventions (e.g., `MSKTBN1`, `CMATEMP01`, `MSCX01A`). @@ -982,7 +1058,7 @@ components: If this property is empty, you will be notified for all `vesselIMONumbers` that have changes you are authorized to see. items: type: string - pattern: ^\d{7,8}$ + pattern: '^\d{7,8}$' minLength: 7 maxLength: 8 description: | @@ -1001,7 +1077,7 @@ components: If this property is empty, you will be notified for all `MMSINumbers` that have changes you are authorized to see. items: type: string - pattern: ^\d{9}$ + pattern: '^\d{9}$' minLength: 9 maxLength: 9 description: | @@ -1027,7 +1103,7 @@ components: properties: UNLocationCode: type: string - pattern: ^[A-Z]{2}[A-Z2-9]{3}$ + pattern: '^[A-Z]{2}[A-Z2-9]{3}$' minLength: 5 maxLength: 5 description: | @@ -1055,20 +1131,19 @@ components: required: - notificationChannel - weekRange - - ###################### - # Notification - ###################### + ###################### + # Notification + ###################### Notification: type: object title: Notification description: | `CloudEvent` specific properties for the `Notification`. - + The `type` property will contain the origin causing the notification to be sent: e.g. if a **Terminal** update is the trigger for a notification then the type will be: - + 'type': 'org.dcsa.ovs-hub.schedules.terminal' - + If the `type` is from a Terminal - then the GET endpoint of the [**Terminal Timestamp API**](https://app.swaggerhub.com/apis/dcsaorg/DCSA_OVS_TER) should be used to get more information. If the `type` is from a Service - then the GET endpoint of [**Operational Vessel Schedules API**](https://app.swaggerhub.com/apis/dcsaorg/DCSA_OVS) should be used to get more information @@ -1102,7 +1177,7 @@ components: An application MAY assign a unique `source` to each distinct producer, which makes it easy to produce unique IDs since no other producer will have the same source. The application MAY use UUIDs, URNs, DNS authorities or an application-specific scheme to create unique `source` identifiers. A source MAY include more than one producer. In that case the producers MUST collaborate to ensure that `source` + `id` is unique for each distinct event. - example: 'ovs-hub.dcsa.org' + example: ovs-hub.dcsa.org type: type: string description: | @@ -1151,10 +1226,9 @@ components: - datacontenttype - subscriptionreference - data - - ############################### - # Data for Notification - ############################### + ############################### + # Data for Notification + ############################### NotificationData: type: object title: Data @@ -1169,7 +1243,7 @@ components: - a port is `OMIT` (omitted), `ADHO` (visited ad hoc) or any other `statusCode` has been changed or added. - the vessel has changed, or a new flag or vesselOperator has been assigned - the location of a port has changed, a new location has been added or a location has been removed from a schedule - + The notification will only be sent to authorized parties. To get more details, fetch the updated schedule data to see what changed. This is done by calling the OVS Hub @@ -1178,14 +1252,14 @@ components: properties: carrierServiceCode: type: string - pattern: ^\S(?:.*\S)?$ + pattern: '^\S(?:.*\S)?$' maxLength: 11 description: | The carrier-specific code of the service for which the schedule details are published. In combination with `carrierSMDGCode` this uniquely identifies the service. example: FE1 universalServiceReference: type: string - pattern: ^SR\d{5}[A-Z]$ + pattern: '^SR\d{5}[A-Z]$' maxLength: 8 minLength: 8 description: | @@ -1213,14 +1287,14 @@ components: carrierImportVoyageNumber: type: string maxLength: 50 - pattern: ^\S(?:.*\S)?$ + pattern: '^\S(?:.*\S)?$' description: | The identifier of an import voyage. The carrier-specific identifier of the import Voyage. In combination with `carrierSMDGCode` and `carrierServiceCode` this uniquely identifies the import voyage. example: 2103N carrierExportVoyageNumber: type: string maxLength: 50 - pattern: ^\S(?:.*\S)?$ + pattern: '^\S(?:.*\S)?$' description: | The identifier of an export voyage. The carrier-specific identifier of the export Voyage. In combination with `carrierSMDGCode` and `carrierServiceCode` this uniquely identifies the export voyage. example: 2103S @@ -1228,23 +1302,22 @@ components: type: string minLength: 5 maxLength: 5 - pattern: ^\d{2}[0-9A-Z]{2}[NEWSR]$ + pattern: '^\d{2}[0-9A-Z]{2}[NEWSR]$' description: | A globally unique voyage reference for the import Voyage, as per DCSA standard, agreed by VSA partners for the voyage. The voyage reference must match the regular expression pattern: `\d{2}[0-9A-Z]{2}[NEWSR]` - + - `2 digits` for the year - `2 alphanumeric characters` for the sequence number of the voyage - `1 character` for the direction/haul (`N`orth, `E`ast, `W`est, `S`outh or `R`oundtrip). - example: 2103N universalExportVoyageReference: type: string minLength: 5 maxLength: 5 - pattern: ^\d{2}[0-9A-Z]{2}[NEWSR]$ + pattern: '^\d{2}[0-9A-Z]{2}[NEWSR]$' description: | A globally unique voyage reference for the export Voyage, as per DCSA standard, agreed by VSA partners for the voyage. The voyage reference must match the regular expression pattern: `\d{2}[0-9A-Z]{2}[NEWSR]` - + - `2 digits` for the year - `2 alphanumeric characters` for the sequence number of the voyage - `1 character` for the direction/haul (`N`orth, `E`ast, `W`est, `S`outh or `R`oundtrip). @@ -1252,12 +1325,12 @@ components: vesselName: type: string maxLength: 50 - pattern: ^\S(?:.*\S)?$ + pattern: '^\S(?:.*\S)?$' description: | The name of the Vessel given by the Vessel Operator and registered with IMO. **Note:** In case the vessel is a "dummy vessel" (`isDummyVessel='true'`) then the following recommendations should be followed: - + Dummy vessel names should begin with the **SMDG Operating Carrier Code** to ensure uniqueness across carriers. The suffix can be **alphanumeric** and up to **10 characters long**, allowing each carrier to use internal naming conventions (e.g., `MSKTBN1`, `CMATEMP01`, `MSCX01A`). @@ -1269,7 +1342,7 @@ components: example: King of the Seas vesselIMONumber: type: string - pattern: ^\d{7,8}$ + pattern: '^\d{7,8}$' minLength: 7 maxLength: 8 description: | @@ -1279,7 +1352,7 @@ components: example: '9321483' MMSINumber: type: string - pattern: ^\d{9}$ + pattern: '^\d{9}$' minLength: 9 maxLength: 9 description: | @@ -1295,7 +1368,6 @@ components: When `true`, the `vesselName` must be used as a unique identifier for the dummy vessel. See the `vesselName` field description for the recommended naming convention. location: $ref: '#/components/schemas/Location' - Location: title: Location type: object @@ -1304,7 +1376,7 @@ components: properties: UNLocationCode: type: string - pattern: ^[A-Z]{2}[A-Z2-9]{3}$ + pattern: '^[A-Z]{2}[A-Z2-9]{3}$' minLength: 5 maxLength: 5 description: | @@ -1325,11 +1397,9 @@ components: example: ACT required: - UNLocationCode - - - ################# - # Error Responses - ################# + ################# + # Error Responses + ################# ErrorResponse: title: Error Response type: object @@ -1397,7 +1467,6 @@ components: - statusCodeText - errorDateTime - errors - DetailedError: type: object title: Detailed Error