From b0d5c6e2f7695c05a831088cedb9a63232764155 Mon Sep 17 00:00:00 2001 From: emarsys-ziyad <117644157+emarsys-ziyad@users.noreply.github.com> Date: Wed, 1 Feb 2023 11:47:34 +0100 Subject: [PATCH] Partner API spec refactor and stoplight markdown instructions SMSDEV-2486 (#2) Co-authored-by: matusekma --------- Co-authored-by: matusekma --- openapi/sms/v1/common.yaml | 119 ++++++++ openapi/sms/v1/docs/readme.md | 249 +++++++++++++++++ openapi/sms/v1/partner-callbacks.yaml | 291 +++++++------------- openapi/sms/v1/partner-service.yaml | 374 ++++++++++++-------------- 4 files changed, 633 insertions(+), 400 deletions(-) create mode 100644 openapi/sms/v1/common.yaml create mode 100644 openapi/sms/v1/docs/readme.md diff --git a/openapi/sms/v1/common.yaml b/openapi/sms/v1/common.yaml new file mode 100644 index 0000000..25f6daf --- /dev/null +++ b/openapi/sms/v1/common.yaml @@ -0,0 +1,119 @@ +components: + schemas: + ReceivedAt: + type: object + properties: + receivedAt: + type: string + format: date-time + example: '2017-07-21T17:32:28Z' + required: + - receivedAt + EmarsysMessageId: + type: object + properties: + emarsysMessageId: + type: string + example: 'WI0ksjocu3b8W8kQU26M' + description: 'Unique identifier for an individual message send. This is used to map outbound message to the delivery report.' + required: + - emarsysMessageId + Error: + type: object + properties: + message: + type: string + example: 'Unable to connect to the Partner service.' + description: 'Description of the error' + required: + - message + InvalidFormatError: + allOf: + - $ref: '#/components/schemas/Error' + - type: object + properties: + keyword: + type: string + example: 'Required' + dataPath: + type: string + example: '.someArray[0]' + params: + type: object + example: { 'missingProperty': 'messageId' } + message: + type: string + example: "should have required property 'messageId'" + InvalidFormatErrorBatch: + type: object + properties: + errors: + type: array + items: + $ref: '#/components/schemas/InvalidFormatError' + minItems: 1 + Message: + type: object + properties: + source: + type: string + pattern: '^[A-Za-z0-9]+$' + example: '436771234567' + description: 'Source (Sender ID) of the message' + destination: + type: string + pattern: '^\d+$' + example: '381641234567' + description: 'MSISDN of the receiver of the message' + message: + type: string + example: 'Hello world!' + description: 'Message content (body)' + required: + - source + - destination + - message + IdentifiableMessage: + allOf: + - $ref: '#/components/schemas/Message' + - type: object + properties: + messageId: + type: string + example: 'WI0ksjocu3b8W8kQU26M' + description: 'Unique message identifier' + required: + - messageId + parameters: + clientIdPathParam: + name: clientId + in: path + required: true + description: Ths is the ID used to reference the client user's integration with the Partner service. It is generated when the client user completes the onboarding. + example: 39a281c7-942f-49a9-91c2-8f0dba750f7f + schema: + type: string + format: uuid + responses: + AcceptedResponse: + description: Request was accepted + InvalidFormatResponse: + description: Request body is invalid and does not follow API specification + content: + application/json: + schema: + $ref: './common.yaml#/components/schemas/InvalidFormatErrorBatch' + AuthenticationFailedResponse: + description: Authentication failed - Invalid or missing OAuth token + AuthorizationFailedResponse: + description: Authorization failed - OAuth client ID does not have access to this resource + ClientDoesNotExistResponse: + description: Client does not exists + TooManyRequestsResponse: + description: Too many requests + ServerErrorResponse: + description: Server error occurred + content: + application/json: + schema: + $ref: './common.yaml#/components/schemas/Error' \ No newline at end of file diff --git a/openapi/sms/v1/docs/readme.md b/openapi/sms/v1/docs/readme.md new file mode 100644 index 0000000..f91a8fb --- /dev/null +++ b/openapi/sms/v1/docs/readme.md @@ -0,0 +1,249 @@ +# Instructions + +SAP Emarsys empowers marketers around the world to create a truly personalized omnichannel experiences that delivers business outcomes. The Emarsys SMS Partner API allows partners to integrate onto the Emarsys SMS channel. The Partner API is [RESTful](https://todo-link.com). + +## API Specification + +The API specification has been created using OpenAPI 3.0.3. It is available to be viewed and exported using the links below: + +- [Partner Service Specification](../partner-service.yaml) +- [Partner Callbacks Specification](../partner-callbacks.yaml) + +The current functionality supported is: + +- [Self-service on-boarding for the client end user.](#client-onboarding). +- [Sending SMS messages triggered by the Emarsys platform.](#outbound-messages) +- [Recording delivery reports of sent messages.](#outbound-messages) +- [Ingesting inbound SMS messages.](#inbound-messages) + +## Glossary + +| Term | Definition | +| ---- | --------- | +| Client | This is the client user utilising the Partner service for the SMS channel. | +| Client ID | Ths is the ID used to reference the client user's integration with the Partner service. It is generated when the client user completes the onboarding | +--- +## Setup + +This section describes the steps required to use the SAP Emarsys SMS Partner API. + +### Partner Onboarding + +To onboard we require: + +- Display name of the partner +- Base URL for the partner service +- Supported countries (ideally a list of ISO-3 country codes) +- Custom Fields for the self-service customer on-boarding + - ##### Field properties: + | Property | Description | + | --------------- | ------------------------------------------------------ | + | Field Name (ID) | Uniquely identifies the field | + | Type | Either `text`, `select` or `password` | + | Label | Label shown during on-boarding | + | Allowed Values | A list of possible values to offer in the select field | + - ##### Example custom fields: + | ID | Type | Label | Allowed Values | + | -------- | ---------- | ------- | --------------- | + | `apiKey` | `password` | API Key | N/A | + | `region` | `select` | Region | `Asia`,`Europe` | +- Features enabled: + - Whether your platform supports inbound messages + +And we subsequently provide: + +- Emarsys SMS Oauth client ID to verify the Emarsys SMS channel requests +- Callback Oauth client ID and secret to sign callback requests + +### Authorization + +Requests sent and received by Emarsys will have an OAuth 2 token. This token should be validated by the Partner service. + +| URI | Description | +| --------------------------------------------------------- | ---------------------------------------------------------------- | +| `https://anrjzyscq.accounts400.ondemand.com` | SAP token issuer host | +| `https://anrjzyscq.accounts400.ondemand.com/oauth2/token` | SAP IAS access token endpoint | +| `https://anrjzyscq.accounts400.ondemand.com/oauth2/certs` | SAP IAS JSON Web Key Set (JWKS) certificate information endpoint | + +--- + +## Workflows + +Below are the supported workflows of a partner service + +| Workflow | Required | +| ----------------- | ------------------- | +| Client onboarding |
| +| Outbound messages |
| +| Inbound Messages |
| + +### Client Onboarding + +```mermaid +sequenceDiagram + autonumber + participant Client as Client User + participant Emarsys as Emarsys SMS + participant Partner as Partner Service + Note right of Client: Onboarding + Client->>Emarsys: Client Configuration + Emarsys->>Partner: Client configuration + Note right of Partner: Partner stores the configuration used + +``` + +A partner service requires the following endpoints to support client onboarding: + +--- + +- #### [Create/Update Client Config](../partner-service.yaml/paths/~1clients~1{clientId}~1configuration/get) + +##### Request Schema: + +```yaml json_schema +$ref: '../partner-service.yaml#/components/schemas/CreateOrUpdateClientConfigurationRequest' +``` + +##### Response Schema: + +```yaml json_schema +$ref: '../partner-service.yaml#/components/schemas/CreateOrUpdateClientConfigurationResponse' +``` + +--- + +- [Get Client Config](../partner-service.yaml/paths/~1clients~1{clientId}~1configuration/get) + +##### Response Schema: + +```yaml json_schema +$ref: '../partner-service.yaml#/components/schemas/GetClientConfigurationResponse' +``` + +--- + +- [Delete Client Config](../partner-service.yaml/paths/~1clients~1{clientId}~1configuration/delete) + +--- + +### Outbound Messaging and Reporting + +#### Overview + +```mermaid +sequenceDiagram + autonumber + participant Client as Client User + participant Emarsys as Emarsys SMS + participant Partner as Partner Service + participant Vendor as SMS Vendor API + loop Each SMS campaign trigger + Client-->Emarsys: Triggers Campaign + Emarsys->>Partner: Outbound Messages + Partner->>Vendor: Outbound SMS Messages + loop Each Delivery Report + Vendor->>Partner: SMS Delivery Receipt + Partner->>Emarsys: Message Delivery Report + Emarsys->>Client: Message Reporting + Note left of Client: User views reports via UI + end + end +``` + +#### Outbound Messages + +```mermaid +sequenceDiagram + autonumber + participant Client as Client User + participant Emarsys as Emarsys SMS + participant Partner as Partner Service + participant Vendor as SMS Vendor API + loop Each SMS campaign trigger + Client-->Emarsys: Triggers Campaign + Emarsys->>Partner: Outbound Messages + Partner->>Vendor: Outbound SMS Messages + end +``` + +- [Create Outbound Message Batch](../partner-service.yaml/paths/~1clients~1{clientId}~1messages/post) + - Request Payload + ```yaml json_schema + $ref: '../partner-service.yaml#/components/schemas/OutboundMessageBatch' + ``` + +#### Delivery Reports + +Delivery reports are communicated via a callback to Emarsys SMS: + +```mermaid +sequenceDiagram + autonumber + participant Client as Client User + participant Emarsys as Emarsys SMS + participant Partner as Partner Service + participant Vendor as SMS Vendor API + loop Each Delivery Report + Vendor->>Partner: SMS Delivery Receipt + Partner->>Emarsys: Message Delivery Report + Emarsys->>Client: Message Reporting + Note left of Client: User views reports via UI + end +``` + +--- + +- [Create Delivery Report Batch](../partner-callbacks.yaml/paths/~1clients~1{clientId}~1deliveryReports) + + *** + + - ##### Request + *** + - Delivery Report: + ```yaml json_schema + $ref: '../partner-callbacks.yaml#/components/schemas/DeliveryReport' + ``` + *** + - ##### Response + *** + - Delivery Report Error: + ```yaml json_schema + $ref: '../partner-callbacks.yaml#/components/schemas/DeliveryReportError' + ``` + *** + - Invalid Format Error Batch Response Payload: + ```yaml json_schema + $ref: '../common.yaml#/components/schemas/InvalidFormatErrorBatch' + ``` + *** + +--- + +### Inbound Messages + +```mermaid +sequenceDiagram + autonumber + participant Client as Client User + participant Emarsys as Emarsys SMS + participant Partner as Partner Service + participant Vendor as SMS Vendor API + loop Each inbound message + Vendor->>Partner: Mobile Originated SMS Message + Partner->>Emarsys: Inbound Message + Emarsys->>Client: Inbound Messages + Note left of Client: Messages used in automations + end +``` + +- [Create Inbound Messages Batch](../partner-callbacks.yaml/paths/~1clients~1{clientId}~1inboundMessages) + - Inbound Message Batch Request Payload: + ```yaml json_schema + $ref: '../partner-callbacks.yaml#/components/schemas/InboundMessageBatch' + ``` + - Invalid Format Error Batch Response Payload: + ```yaml json_schema + $ref: '../common.yaml#/components/schemas/InvalidFormatErrorBatch' + ``` + +--- diff --git a/openapi/sms/v1/partner-callbacks.yaml b/openapi/sms/v1/partner-callbacks.yaml index 50d77ba..a8cfe07 100644 --- a/openapi/sms/v1/partner-callbacks.yaml +++ b/openapi/sms/v1/partner-callbacks.yaml @@ -4,53 +4,46 @@ info: title: Provider callbacks description: | An SAP Emarsys SMS Partner Service allows partners to host SMS message sends that are triggered - by an SAP Emarsys SMS campaign launch. + by an SAP Emarsys SMS campaign launch. This OpenAPI specification describes the possible callback endpoints. contact: name: SAP Emarsys SMS Team email: team-sms@emarsys.com -x-sap-shortText: Process delivery reports and inbound messages. +x-sap-shortText: Process Partner service callbacks for the Emarsys SMS Partner API. Expected callbacks contain outbound message delivery reports and inbound messages. servers: - url: https://api.emarsys.net/sms/partner/v1 paths: /clients/{clientId}/deliveryReports: post: summary: Send multiple delivery reports + description: operationId: sendDeliveryReports tags: [delivery-reports] security: - oAuthAuthorization: [] parameters: - - $ref: '#/components/parameters/clientIdPathParam' + - $ref: './common.yaml#/components/parameters/clientIdPathParam' requestBody: description: The body of the delivery reports in JSON format required: true content: application/json: schema: - $ref: '#/components/schemas/DeliveryReports' + $ref: '#/components/schemas/DeliveryReportBatch' responses: '202': - description: Null response + $ref: './common.yaml#/components/responses/AcceptedResponse' '400': - description: Delivery report body schema is invalid - content: - application/json: - schema: - $ref: '#/components/schemas/InvalidDeliveryReportRequestErrors' + $ref: './common.yaml#/components/responses/InvalidFormatResponse' '401': - description: Authentication failed - Invalid or missing OAuth token + $ref: './common.yaml#/components/responses/AuthenticationFailedResponse' '403': - description: Authorization failed - OAuth client ID does not belong to a registered partner + $ref: './common.yaml#/components/responses/AuthorizationFailedResponse' '404': - description: Client does not exists + $ref: './common.yaml#/components/responses/ClientDoesNotExistResponse' '429': - description: Too many requests + $ref: './common.yaml#/components/responses/TooManyRequestsResponse' '5XX': - description: Server error occurred - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: './common.yaml#/components/responses/ServerErrorResponse' /clients/{clientId}/inboundMessages: post: summary: Record received inbound messages @@ -59,225 +52,123 @@ paths: security: - oAuthAuthorization: [] parameters: - - $ref: '#/components/parameters/clientIdPathParam' + - $ref: './common.yaml#/components/parameters/clientIdPathParam' requestBody: - description: The body of the inbound messages in JSON 145078format + description: The body of the inbound messages in JSON 145078 format required: true content: application/json: schema: - $ref: '#/components/schemas/InboundMessages' + $ref: '#/components/schemas/InboundMessageBatch' responses: '202': - description: Null response + $ref: './common.yaml#/components/responses/AcceptedResponse' '400': - description: Inbound message body schema is invalid. If one inbound message is wrong, all messages will be refused (the whole array from the request must be valid) and all valid messages should be resent in another request - content: - application/json: - schema: - $ref: '#/components/schemas/InvalidInboundMessagesRequestErrors' + $ref: './common.yaml#/components/responses/InvalidFormatResponse' '401': - description: Authentication failed - Invalid or missing OAuth token + $ref: './common.yaml#/components/responses/AuthenticationFailedResponse' '403': - description: Authorization failed - OAuth client ID does not belong to a registered partner + $ref: './common.yaml#/components/responses/AuthorizationFailedResponse' '404': - description: Client does not exists + $ref: './common.yaml#/components/responses/ClientDoesNotExistResponse' '429': - description: Too many requests + $ref: './common.yaml#/components/responses/TooManyRequestsResponse' '5XX': - description: Server error occurred - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: './common.yaml#/components/responses/ServerErrorResponse' components: schemas: - DeliveryReports: + # -- Delivery Reports + DeliveryReport: + allOf: + - $ref: './common.yaml#/components/schemas/ReceivedAt' + - $ref: './common.yaml#/components/schemas/EmarsysMessageId' + - type: object + properties: + status: + type: string + enum: ['ACCEPTED', 'DELIVERED', 'SOFTBOUNCE', 'HARDBOUNCE', 'UNKNOWN', 'ERROR'] + example: 'DELIVERED' + details: + description: 'This property can be used to provide extra details about the status of the delivery' + type: object + example: { providerStatus: 'HARDBOUNCE', providerCode: 5001 } + providerMessageIds: + type: array + items: + type: string + example: 'yqqKUsSSvr' + description: 'Original provider (vendor) message ID, used for troubleshooting directly with the vendor' + minItems: 1 + description: 'Original message IDs from the provider (vendor) can be used to aid troubleshooting with the provider' + messageParts: + type: integer + example: 3 + minimum: 0 + DeliveryReportSuccess: + allOf: + - $ref: '#/components/schemas/DeliveryReport' + - type: object + properties: + status: + type: string + enum: [ 'ACCEPTED', 'DELIVERED', 'SOFTBOUNCE', 'HARDBOUNCE', 'UNKNOWN' ] + example: 'DELIVERED' + required: + - status + DeliveryReportError: + allOf: + - $ref: '#/components/schemas/DeliveryReport' + - type: object + properties: + status: + type: string + enum: ['ERROR'] + example: 'ERROR' + errorType: + type: string + enum: ['AUTHENTICATION', 'INVALID_SENDER_ID', 'INSUFFICIENT_CREDIT', 'UNKNOWN'] + example: 'AUTHENTICATION' + description: 'Type of the error. Used to determine how the user is notified.' + required: + - status + - errorType + DeliveryReportBatch: type: object properties: deliveryReports: type: array items: oneOf: - - $ref: '#/components/schemas/DeliveryReport' + - $ref: '#/components/schemas/DeliveryReportSuccess' - $ref: '#/components/schemas/DeliveryReportError' - minimum: 1 - maximum: 1000 + minItems: 1 + maxItems: 1000 required: - deliveryReports - DeliveryReport: - type: object - properties: - status: - type: string - enum: ['ACCEPTED', 'DELIVERED', 'SOFTBOUNCE', 'HARDBOUNCE', 'UNKNOWN'] - example: 'DELIVERED' - emarsysMessageId: - type: string - example: 'MfWrPoFGyn' - receivedAt: - type: string - format: date-time - example: '2017-07-21T17:32:28Z' - details: - description: 'This property can be used to provide extra details about the report' - type: object - example: { providerStatus: 'HARDBOUNCE', providerCode: 5001 } - providerMessageIds: - type: array - items: - type: string - example: 'yqqKUsSSvr' - minimum: 1 - messageParts: - type: integer - example: 3 - minimum: 0 - required: - - status - - emarsysMessageId - - receivedAt - DeliveryReportError: - type: object - properties: - status: - type: string - enum: ['ERROR'] - emarsysMessageId: - type: string - example: 'MfWrPoFGyn' - receivedAt: - type: string - format: date-time - example: '2017-07-21T17:32:28Z' - details: - description: 'This property can be used to provide extra details about the report' - type: object - example: { providerStatus: 'HARDBOUNCE', providerCode: 5001 } - providerMessageIds: - type: array - items: - type: string - example: 'yqqKUsSSvr' - minimum: 1 - messageParts: - type: integer - example: 3 - minimum: 0 - errorType: - type: string - enum: ['AUTHENTICATION', 'INVALID_SENDER_ID', 'INSUFFICIENT_CREDIT', 'UNKNOWN'] - example: 'AUTHENTICATION' - required: - - status - - emarsysMessageId - - receivedAt - - errorType - InboundMessages: + # -- Inbound Messages + InboundMessage: + allOf: + - $ref: './common.yaml#/components/schemas/IdentifiableMessage' + - $ref: './common.yaml#/components/schemas/ReceivedAt' + InboundMessageBatch: type: object properties: inboundMessages: type: array items: $ref: '#/components/schemas/InboundMessage' - minimum: 1 - maximum: 1000 + minItems: 1 + maxItems: 1000 required: - inboundMessages - InboundMessage: - type: object - properties: - messageId: - type: string - example: 'kzO6Z1FVbn' - description: 'Unique ID. This is used for deduplication and troubleshooting.' - from: - type: string - pattern: '^\+?\d+$' - example: '381651234567' - to: - type: string - pattern: '^\+?\d+$' - example: '4367712345678' - message: - type: string - example: 'STOP' - receivedAt: - type: string - format: date-time - example: '2017-07-21T17:32:28Z' - required: - - messageId - - from - - to - - message - - receivedAt - Error: - type: object - properties: - message: - type: string - example: 'Description of the error' - required: - - message - InvalidDeliveryReportRequestErrors: - type: object - properties: - errors: - type: array - items: - $ref: '#/components/schemas/InvalidDeliveryReportRequestError' - minimum: 1 - maximum: 1000 - InvalidDeliveryReportRequestError: - type: object - properties: - keyword: - type: string - example: 'Required' - dataPath: - type: string - example: '.deliveryReports[0]' - params: - type: object - example: { 'missingProperty': 'messageId' } - message: - type: string - example: "should have required property 'messageId'" - InvalidInboundMessagesRequestErrors: - type: object - properties: - errors: - type: array - items: - $ref: '#/components/schemas/InvalidInboundMessageRequestError' - minimum: 1 - maximum: 1000 - InvalidInboundMessageRequestError: - type: object - properties: - message: - type: string - example: 'Error description of for the specific item' - payload: - type: object - $ref: '#/components/schemas/InboundMessage' - parameters: - clientIdPathParam: - name: clientId - in: path - required: true - description: Identifies a client using the Partner service in the UUID format. UUID should mask how Emarsys sees the clientId - example: 39a281c7-942f-49a9-91c2-8f0dba750f7f - schema: - type: string + securitySchemes: oAuthAuthorization: type: oauth2 description: OAuth client credentials grant type authorization flows: clientCredentials: - tokenUrl: https://authorization-server/oauth2/token/ + tokenUrl: https://anrjzyscq.accounts400.ondemand.com/oauth2/token scopes: {} security: - oAuthAuthorization: [] diff --git a/openapi/sms/v1/partner-service.yaml b/openapi/sms/v1/partner-service.yaml index dbccd76..e229e8e 100644 --- a/openapi/sms/v1/partner-service.yaml +++ b/openapi/sms/v1/partner-service.yaml @@ -3,7 +3,7 @@ info: title: SAP Emarsys SMS Partner Service description: | An SAP Emarsys SMS Partner Service allows partners to host SMS message sends that are triggered - by an SAP Emarsys SMS campaign launch. + by an SAP Emarsys SMS campaign launch. This OpenAPI specification describes the required Partner service endpoints. version: 0.0.1 contact: name: SAP Emarsys SMS Team @@ -15,9 +15,9 @@ paths: /clients/{clientId}/configuration: summary: Manage a client configuration within a Partner service parameters: - - $ref: '#/components/parameters/clientIdPathParam' + - $ref: './common.yaml#/components/parameters/clientIdPathParam' put: - tags: [client-configuration] + tags: [Client Configuration] operationId: createOrUpdateClientConfiguration summary: Create or update a single client's configuration requestBody: @@ -35,21 +35,15 @@ paths: schema: $ref: '#/components/schemas/CreateOrUpdateClientConfigurationResponse' '400': - description: Request body was not as expected - content: - application/json: - schema: - $ref: '#/components/schemas/ClientConfigurationErrors' + $ref: './common.yaml#/components/responses/InvalidFormatResponse' + '401': + $ref: './common.yaml#/components/responses/AuthenticationFailedResponse' '403': - description: Authentication failed. + $ref: './common.yaml#/components/responses/AuthorizationFailedResponse' '5XX': - description: Server error occurred - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: './common.yaml#/components/responses/ServerErrorResponse' get: - tags: [client-configuration] + tags: [Client Configuration] operationId: getClientConfiguration summary: Get a client's configuration by their ID responses: @@ -69,9 +63,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: './common.yaml#/components/schemas/Error' delete: - tags: [client-configuration] + tags: [Client Configuration] operationId: deleteClientConfiguration summary: Delete a client's configuration by their ID responses: @@ -87,45 +81,10 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Error' - /clients/{clientId}/messages: - parameters: - - $ref: '#/components/parameters/clientIdPathParam' - post: - tags: [message-sending] - operationId: sendMessages - summary: Send SMS messages to the Partner API - requestBody: - description: Messages to be sent - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/Messages' - responses: - '202': - description: Receiving empty response in the case all messages were accepted. - '400': - description: Returns error type and error context globally, for all messages, or per message - content: - application/json: - schema: - $ref: '#/components/schemas/SMSSendingPartnerError' - '403': - description: Authentication failed. - '404': - description: Client does not have a configuration recorded within the Partner service. All messages will be marked as failed. - '429': - description: Too many requests. Messages will be retried later. - '5XX': - description: Server error occurred. Messages will be retried later - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: './common.yaml#/components/schemas/Error' /testConnection: post: - tags: [connection-test] + tags: [Client Configuration Test] operationId: testConnection summary: Test connection with the provided custom fields with the provider requestBody: @@ -142,13 +101,13 @@ paths: application/json: schema: oneOf: - - $ref: '#/components/schemas/TestConnectionResponseOK' - - $ref: '#/components/schemas/TestConnectionResponseKO' + - $ref: '#/components/schemas/TestConnectionSuccessResponse' + - $ref: '#/components/schemas/TestConnectionFailureResponse' discriminator: propertyName: state mapping: - success: '#/components/schemas/TestConnectionResponseOK' - error: '#/components/schemas/TestConnectionResponseKO' + success: '#/components/schemas/TestConnectionSuccessResponse' + error: '#/components/schemas/TestConnectionFailureResponse' examples: # examples are not used from the schema ok: summary: Test connection was success @@ -157,91 +116,80 @@ paths: summary: Test connection failed value: { state: 'error', description: 'There was an error', errorType: 'temporary' } '400': - description: Request body is wrong - content: - application/json: - schema: - $ref: '#/components/schemas/TestConnectionErrors' + $ref: './common.yaml#/components/responses/InvalidFormatResponse' + '401': + $ref: './common.yaml#/components/responses/AuthenticationFailedResponse' '403': - description: Authentication failed. + $ref: './common.yaml#/components/responses/AuthorizationFailedResponse' '5XX': - description: Server error occurred. Messages will be retried later + $ref: './common.yaml#/components/responses/ServerErrorResponse' + /clients/{clientId}/messages: + parameters: + - $ref: './common.yaml#/components/parameters/clientIdPathParam' + post: + tags: [Outbound Message Sending] + operationId: sendMessages + summary: Send SMS messages to the Partner API + requestBody: + description: Messages to be sent + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OutboundMessageBatch' + responses: + '202': + $ref: './common.yaml#/components/responses/AcceptedResponse' + '400': + description: Returns error type and error context globally, for all messages, or per message content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/OutboundMessageBatchError' + '401': + $ref: './common.yaml#/components/responses/AuthenticationFailedResponse' + '403': + $ref: './common.yaml#/components/responses/AuthorizationFailedResponse' + '404': + $ref: './common.yaml#/components/responses/ClientDoesNotExistResponse' + '429': + $ref: './common.yaml#/components/responses/TooManyRequestsResponse' + '5XX': + $ref: './common.yaml#/components/responses/ServerErrorResponse' components: schemas: - Error: - type: object - properties: - message: - type: string - description: Message to describe the error - example: 'Description of the error' - required: - - message - ClientConfigurationErrors: - type: object - properties: - errors: - type: array - items: - $ref: '#/components/schemas/ClientConfigurationError' - minimum: 1 - ClientConfigurationError: - type: object - properties: - fieldName: - type: string - example: 'servicePlanId' - description: - type: string - example: 'servicePlanId can only contain numbers.' - errorType: - type: string - enum: [missing, invalid] - example: invalid - required: - - fieldName - - description - - errorType - ClientCallbackUrls: + CustomFieldValues: type: object - properties: - inboundMessages: - $ref: '#/components/schemas/InboundMessageConfiguration' - deliveryReports: - $ref: '#/components/schemas/DeliveryReportsConfiguration' - InboundMessageConfiguration: + description: Object containing the values the client entered during onboarding mapped by their custom field name as key. + minProperties: 1 + example: + apiKey: 'abc123' + servicePlanId: '123abc' + baseUrl: 'https://api.sms.provider.io' + CallbackUrl: type: object properties: url: type: string format: uri - description: The inbound message URL, that is generated by the Partner.' - example: 'https://api.partner.io/inbound-messages/unique-id' + description: A callback URL, provided by the Partner.' + example: 'https://api.partner.io/callback-path/unique-id' required: - url - DeliveryReportsConfiguration: + ClientCallbackUrls: type: object properties: - url: - type: string - format: uri - description: The delivery report URL, that is generated by the Partner. - example: 'https://api.partner.io/delivery-reports/unique-id' - required: - - url - CustomFieldValues: - type: object - description: Object of the values the client entered during on-boarding mapped by the field key - minProperties: 1 - example: - apiKey: 'abc123' - servicePlanId: '123abc' - baseUrl: 'https://api.sms.provider.io' + inboundMessages: + allOf: + - $ref: '#/components/schemas/CallbackUrl' + - description: 'The inbound message callback URL, provided by the Partner.' + example: 'https://api.partner.io/inboundMessages/unique-id' + deliveryReports: + allOf: + - $ref: '#/components/schemas/CallbackUrl' + - description: 'The delivery report callback URL, provided by the Partner.' + example: 'https://api.partner.io/deliveryReports/unique-id' GetClientConfigurationResponse: type: object properties: @@ -266,43 +214,34 @@ components: $ref: '#/components/schemas/CustomFieldValues' required: - customFieldValues - Messages: - type: object - properties: - messages: - type: array - items: - $ref: '#/components/schemas/Message' - minimum: 1 - maximum: 1000 - required: - - messages - Message: + ClientConfigurationError: type: object properties: - source: - type: string - pattern: '^[A-Za-z0-9]+$' - example: '436771234567' - destination: + fieldName: type: string - pattern: '^\d+$' - example: '381641234567' - message: + example: 'servicePlanId' + description: 'Key to uniquely identify the field.' + description: type: string - example: 'Hello world!' - emarsysMessageId: + example: 'servicePlanId can only contain numbers.' + description: 'Description of the error.' + errorType: type: string - example: 'WI0ksjocu3b8W8kQU26M' - isTransactional: - type: boolean - example: true + enum: [missing, invalid] + example: invalid + description: 'Type of the error.' required: - - source - - destination - - message - - emarsysMessageId - - isTransactional + - fieldName + - description + - errorType + ClientConfigurationErrors: + type: object + properties: + errors: + type: array + items: + $ref: '#/components/schemas/ClientConfigurationError' + minItems: 1 TestConnectionRequest: type: object properties: @@ -310,105 +249,140 @@ components: $ref: '#/components/schemas/CustomFieldValues' required: - customFieldValues - TestConnectionResponseOK: + TestConnectionSuccessResponse: type: object properties: state: type: string enum: [success] example: 'success' + description: 'Connection test was successful when state is "success".' required: - state - TestConnectionResponseKO: + TestConnectionFailureResponse: type: object properties: state: type: string enum: [error] example: 'error' + description: 'Connection test was unsuccessful when state is "error".' description: type: string example: 'There was an error' + description: 'Description of the error.' errorType: type: string enum: [temporary, credential, integration] example: temporary + description: | + | Value | Description | + |---|---| + | temporary | There was a temporary issue whilst performing the request so try again later | + | credential | There was a problem authorizing the client on the vendor platform | + | integration | There is an issue related to the integration between Emarsys and the Partner service | discriminator: propertyName: state required: - state - description - - isTemporary + - errorType TestConnectionErrors: type: object properties: errors: type: array items: - $ref: '#/components/schemas/ClientConfigurationError' - minimum: 1 - SMSTestConnectionError: + $ref: '#/components/schemas/TestConnectionError' + minItems: 1 + TestConnectionError: type: object properties: fieldName: type: string example: 'servicePlanId' + description: 'Key to uniquely identify the field.' description: type: string example: 'servicePlanId can only contain numbers.' + description: 'Description of the error.' required: - fieldName - description - SMSSendingPartnerError: + OutboundMessage: + allOf: + - $ref: './common.yaml#/components/schemas/Message' + - $ref: './common.yaml#/components/schemas/EmarsysMessageId' + - type: object + properties: + isTransactional: + type: boolean + example: true + description: 'A transactional SMS is typically an automated SMS message sent in response to an event or action triggered by a contact.' + required: + - isTransactional + OutboundMessageBatch: type: object properties: - globalError: + messages: + type: array + items: + $ref: '#/components/schemas/OutboundMessage' + minItems: 1 + maxItems: 1000 + required: + - messages + OutboundMessageError: + type: object + properties: + errorType: + type: string + enum: [emarsys, client, partner, provider, unknown] + example: partner + description: | + | Value | Description | + |---|---| + | emarsys | There was a a problem with the message send payload | + | client | There was a problem with the client setup | + | partner | There was a problem at the partner | + | provider | There was a problem at the provider | + | unknown | There was an unknown problem | + errorContext: type: object - properties: - errorType: - type: string - enum: [emarsys, client, partner, provider, unknown] - example: integration - errorContext: - type: object - description: whatever seems to be useful - isErrorTransient: - type: boolean - example: false + description: whatever seems to be useful + isErrorTransient: + type: boolean + example: false + required: + - errorType + - isErrorTransient + OutboundMessageBatchGlobalError: + type: object + properties: + globalError: + allOf: # Combines the BasicErrorModel and the inline model + - $ref: '#/components/schemas/OutboundMessageError' + - type: object + OutboundMessageBatchMessageSpecificError: + type: object + properties: messageSpecificErrors: type: array items: - type: object - properties: - emarsysMessageId: - type: string - example: fb9ef4ce-ecbe-4787-85ab-d10cbed18533 - errorType: - type: string - enum: [emarsys, client, partner, provider, unknown] - example: client - errorContext: - type: object - description: whatever seems to be useful - isErrorTransient: - type: boolean - example: false - parameters: - clientIdPathParam: - name: clientId - in: path - required: true - description: Identifies a client using the Partner service in the UUID format. UUID should mask how Emarsys sees the clientId - example: 39a281c7-942f-49a9-91c2-8f0dba750f7f - schema: - type: string + allOf: # Combines the BasicErrorModel and the inline model + - $ref: '#/components/schemas/OutboundMessageError' + - $ref: './common.yaml#/components/schemas/EmarsysMessageId' + OutboundMessageBatchError: + oneOf: + - $ref: '#/components/schemas/OutboundMessageBatchGlobalError' + - $ref: '#/components/schemas/OutboundMessageBatchMessageSpecificError' securitySchemes: oAuthAuthorization: type: oauth2 description: OAuth client credentials grant type authorization flows: clientCredentials: - tokenUrl: https://authorization-server/oAuthAuthorization/token/ + tokenUrl: https://anrjzyscq.accounts400.ondemand.com/oauth2/token scopes: {} # TODO do we need scopes? security: - oAuthAuthorization: []