From a38b69b7315e03ec316d67b4f1c935e91b20677e Mon Sep 17 00:00:00 2001
From: Jean-Pierre Portier <141755467+JPPortier@users.noreply.github.com>
Date: Wed, 8 Nov 2023 15:28:25 +0100
Subject: [PATCH] SMS: webhooks (#5)
* feat: WebHooks
---
.../com/sinch/sdk/domains/sms/SMSService.java | 8 +
.../sdk/domains/sms/WebHooksService.java | 103 ++++++++++++
.../sdk/domains/sms/adapters/SMSService.java | 10 ++
.../domains/sms/adapters/WebHooksService.java | 39 +++++
.../sms/models/DeliveryReportStatus.java | 85 ++++++++++
.../models/webhooks/BaseDeliveryReport.java | 72 +++++++++
.../sms/models/webhooks/BaseIncomingSMS.java | 98 ++++++++++++
.../sms/models/webhooks/DeliveryReport.java | 59 +++++++
.../models/webhooks/DeliveryReportMMS.java | 35 ++++
.../webhooks/DeliveryReportRecipient.java | 151 ++++++++++++++++++
.../webhooks/DeliveryReportRecipientMMS.java | 70 ++++++++
.../webhooks/DeliveryReportRecipientSMS.java | 70 ++++++++
.../models/webhooks/DeliveryReportSMS.java | 35 ++++
.../webhooks/DeliveryReportStatusDetails.java | 75 +++++++++
.../models/webhooks/IncomingSMSBinary.java | 58 +++++++
.../sms/models/webhooks/IncomingSMSText.java | 48 ++++++
.../sms/models/webhooks/package-info.java | 6 +
.../sms/adapters/WebHKooksServiceTest.java | 134 ++++++++++++++++
.../sdk/core/exceptions/ApiException.java | 4 +
.../core/exceptions/ApiMappingException.java | 8 +
.../v1/webhooks/DeliveryReportDtoTest.java | 53 ++++++
.../DeliveryReportRecipientDtoTest.java | 62 +++++++
.../v1/webhooks/IncomingSMSBinaryDtoTest.java | 34 ++++
.../v1/webhooks/IncomingSMSTextDtoTest.java | 33 ++++
.../sample/sms/webhooks/DeliveryReport.java | 46 ++++++
.../sample/sms/webhooks/IncomingSMS.java | 40 +++++
.../sms/v1/webhooks/DeliveryReportMMS.json | 15 ++
.../webhooks/DeliveryReportRecipientMMS.json | 15 ++
.../webhooks/DeliveryReportRecipientSMS.json | 15 ++
.../sms/v1/webhooks/DeliveryReportSMS.json | 15 ++
.../sms/v1/webhooks/IncomingSMSBinary.json | 11 ++
.../sms/v1/webhooks/IncomingSMSText.json | 9 ++
32 files changed, 1516 insertions(+)
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/DeliveryReportStatus.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseDeliveryReport.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseIncomingSMS.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReport.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportMMS.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipient.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientMMS.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientSMS.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportSMS.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportStatusDetails.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSBinary.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSText.java
create mode 100644 client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java
create mode 100644 client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHKooksServiceTest.java
create mode 100644 core/src/main/com/sinch/sdk/core/exceptions/ApiMappingException.java
create mode 100644 openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportDtoTest.java
create mode 100644 openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportRecipientDtoTest.java
create mode 100644 openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSBinaryDtoTest.java
create mode 100644 openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSTextDtoTest.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java
create mode 100644 sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java
create mode 100644 test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportMMS.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientMMS.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientSMS.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportSMS.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSBinary.json
create mode 100644 test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSText.json
diff --git a/client/src/main/com/sinch/sdk/domains/sms/SMSService.java b/client/src/main/com/sinch/sdk/domains/sms/SMSService.java
index 2947577e..daa31986 100644
--- a/client/src/main/com/sinch/sdk/domains/sms/SMSService.java
+++ b/client/src/main/com/sinch/sdk/domains/sms/SMSService.java
@@ -16,4 +16,12 @@ public interface SMSService {
* @since 1.0
*/
BatchesService batches();
+
+ /**
+ * WebHooksService Service instance
+ *
+ * @return service instance for project
+ * @since 1.0
+ */
+ WebHooksService webHooks();
}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java b/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java
new file mode 100644
index 00000000..5dbfe23e
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/WebHooksService.java
@@ -0,0 +1,103 @@
+package com.sinch.sdk.domains.sms;
+
+import com.sinch.sdk.core.exceptions.ApiMappingException;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseDeliveryReport;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseIncomingSMS;
+
+/**
+ * WebHooks
+ *
+ *
Callbacks
+ *
+ *
A callback is an HTTP POST request with a notification made by the Sinch SMS REST API to a URI
+ * of your choosing.
+ *
+ *
The REST API expects the receiving server to respond with a response code within the 2xx
+ *
success range. For 5xx
the callback will be retried. For 429
+ * the callback will be retried and the throughput will be lowered. For other status codes in the
+ * 4xx
range the callback will not be retried. The first initial retry will happen 5
+ * seconds after the first try. The next attempt is after 10 seconds, then after 20 seconds, after
+ * 40 seconds, after 80 seconds, doubling on every attempt. The last retry will be at 81920 seconds
+ * (or 22 hours 45 minutes) after the initial failed attempt.
+ *
+ *
The SMS REST API offers the following callback options which can be configured for your
+ * account upon request to your account manager.
+ *
+ *
+ * - Callback with mutual authentication over TLS (HTTPS) connection by provisioning the
+ * callback URL with client keystore and password.
+ *
- Callback with basic authentication by provisioning the callback URL with username and
+ * password.
+ *
- Callback with OAuth 2.0 by provisioning the callback URL with username, password and the
+ * URL to fetch OAuth access token.
+ *
- Callback using AWS SNS by provisioning the callback URL with an Access Key ID, Secret Key
+ * and Region.
+ *
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/
+ * @since 1.0
+ */
+public interface WebHooksService {
+
+ /**
+ * Incoming SMS WebHook
+ *
+ * An inbound message is a message sent to one of your short codes or long numbers from a
+ * mobile phone. To receive inbound message callbacks, a URL needs to be added to your REST API.
+ * This URL can be specified in your Dashboard.
+ *
+ * @param jsonPayload The incoming message to your sinch number
+ * @return Decoded payload
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/incomingSMS
+ * @since 1.0
+ */
+ BaseIncomingSMS> incomingSMS(String jsonPayload) throws ApiMappingException;
+
+ /**
+ * Delivery Report WebHook
+ *
+ *
A delivery report contains the status and status code for each recipient of a batch. To get
+ * a delivery report callback for a message or batch of messages, set the delivery_report
+ *
field accordingly when creating a batch.
+ *
+ *
The following is provided so you can better understand our webhooks/callbacks. Configuration
+ * of both webhooks and the type of delivery report requested happens when sending a batch.
+ *
+ *
Callback URL
+ *
+ *
The callback URL can either be provided for each batch or provisioned globally for your
+ * account in your Sinch Customer
+ * Dashboard. Learn how to configure a webhook/callback here
+ *
+ *
Type
+ *
+ *
The type
is the type of delivery report webhook. The response will vary
+ * depending on the webhook delivery report you selected when the batch was sent, so choose the
+ * appropriate selection under "One of".
+ *
+ *
+ * - The
delivery_report_sms
and delivery_report_mms
types are
+ * documented under Delivery report. These are reports containing either
+ * a full report or summary report, depending on your selection at the time the batch
+ * was sent.
+ * - The
recipient_delivery_report_sms
and recipient_delivery_report_mms
+ *
delivery report types are documented under Recipient delivery report.
+ * These are delivery reports for recipient phone numbers. If you set per_recipient
+ *
for the delivery_report
parameter when sending the batch, a
+ * recipient report gets sent to you for each status change for each recipient in your
+ * batch. If you set per_recipient_final
, a recipient report gets sent to you
+ * for the final status of each recipient in your batch.
+ *
+ *
+ * @param jsonPayload The incoming delivery report
+ * @return Decoded payload
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Webhooks/#tag/Webhooks/operation/deliveryReport
+ * @since 1.0
+ */
+ BaseDeliveryReport deliveryReport(String jsonPayload) throws ApiMappingException;
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java b/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java
index fd2f3a26..bbc23470 100644
--- a/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java
+++ b/client/src/main/com/sinch/sdk/domains/sms/adapters/SMSService.java
@@ -2,6 +2,7 @@
import com.sinch.sdk.core.http.HttpClient;
import com.sinch.sdk.domains.sms.BatchesService;
+import com.sinch.sdk.domains.sms.WebHooksService;
import com.sinch.sdk.models.Configuration;
public class SMSService implements com.sinch.sdk.domains.sms.SMSService {
@@ -9,6 +10,7 @@ public class SMSService implements com.sinch.sdk.domains.sms.SMSService {
private final Configuration configuration;
private final HttpClient httpClient;
private BatchesService batches;
+ private WebHooksService webHooks;
public SMSService(Configuration configuration, HttpClient httpClient) {
this.configuration = configuration;
@@ -23,4 +25,12 @@ public BatchesService batches() {
}
return this.batches;
}
+
+ @Override
+ public WebHooksService webHooks() {
+ if (null == this.webHooks) {
+ this.webHooks = new com.sinch.sdk.domains.sms.adapters.WebHooksService();
+ }
+ return this.webHooks;
+ }
}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java b/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java
new file mode 100644
index 00000000..858ace2e
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/adapters/WebHooksService.java
@@ -0,0 +1,39 @@
+package com.sinch.sdk.domains.sms.adapters;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.sinch.sdk.core.exceptions.ApiMappingException;
+import com.sinch.sdk.core.utils.StringUtil;
+import com.sinch.sdk.core.utils.databind.Mapper;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseDeliveryReport;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseIncomingSMS;
+
+public class WebHooksService implements com.sinch.sdk.domains.sms.WebHooksService {
+
+ @Override
+ public BaseIncomingSMS> incomingSMS(String jsonPayload) throws ApiMappingException {
+ try {
+ BaseIncomingSMS> generic =
+ Mapper.getInstance().readValue(jsonPayload, BaseIncomingSMS.class);
+ if (null == generic && !StringUtil.isEmpty(jsonPayload)) {
+ throw new ApiMappingException(jsonPayload, null);
+ }
+ return generic;
+ } catch (JsonProcessingException e) {
+ throw new ApiMappingException(jsonPayload, e);
+ }
+ }
+
+ @Override
+ public BaseDeliveryReport deliveryReport(String jsonPayload) throws ApiMappingException {
+ try {
+ BaseDeliveryReport generic =
+ Mapper.getInstance().readValue(jsonPayload, BaseDeliveryReport.class);
+ if (null == generic && !StringUtil.isEmpty(jsonPayload)) {
+ throw new ApiMappingException(jsonPayload, null);
+ }
+ return generic;
+ } catch (JsonProcessingException e) {
+ throw new ApiMappingException(jsonPayload, e);
+ }
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/DeliveryReportStatus.java b/client/src/main/com/sinch/sdk/domains/sms/models/DeliveryReportStatus.java
new file mode 100644
index 00000000..d411ae1f
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/DeliveryReportStatus.java
@@ -0,0 +1,85 @@
+package com.sinch.sdk.domains.sms.models;
+
+import com.sinch.sdk.core.utils.EnumDynamic;
+import com.sinch.sdk.core.utils.EnumSupportDynamic;
+import java.util.Arrays;
+import java.util.stream.Stream;
+
+/**
+ * The status field describes which state a particular message is in. Note that statuses of type
+ * Intermediate will only be reported if you request a status per_recipient
or
+ * per_recipient_final
( @see Retrieve
+ * a recipient delivery report).
+ *
+ * @see https://developers.sinch.com/docs/sms/api-reference/sms/tag/Delivery-reports/#tag/Delivery-reports/section/Delivery-report-statuses
+ * @since 1.0
+ */
+public class DeliveryReportStatus extends EnumDynamic {
+
+ /**
+ * Message is queued within REST API system and will be dispatched according to the rate of the
+ * account.
+ */
+ public static final DeliveryReportStatus QUEUED = new DeliveryReportStatus("Queued");
+ /** Message has been dispatched and accepted for delivery by the SMSC. */
+ public static final DeliveryReportStatus DISPATCHED = new DeliveryReportStatus("Dispatched");
+ /** Message was aborted before reaching the SMSC. */
+ public static final DeliveryReportStatus ABORTED = new DeliveryReportStatus("Aborted");
+ /** Message was cancelled by user before reaching SMSC. */
+ public static final DeliveryReportStatus CANCELLED = new DeliveryReportStatus("Cancelled");
+ /** Message was rejected by the SMSC. */
+ public static final DeliveryReportStatus REJECTED = new DeliveryReportStatus("Rejected");
+ /**
+ * Message has been deleted. Message was deleted by a remote SMSC. This may happen if the
+ * destination is an invalid MSISDN or opted out subscriber.
+ */
+ public static final DeliveryReportStatus DELETED = new DeliveryReportStatus("Deleted");
+ /** Message has been delivered. */
+ public static final DeliveryReportStatus DELIVERED = new DeliveryReportStatus("Delivered");
+ /** Message failed to be delivered. */
+ public static final DeliveryReportStatus FAILED = new DeliveryReportStatus("Failed");
+ /**
+ * Message expired before delivery to the SMSC. This may happen if the expiry time for the message
+ * was very short.
+ */
+ public static final DeliveryReportStatus EXPIRED = new DeliveryReportStatus("Expired");
+ /**
+ * Message was delivered to the SMSC but no Delivery Receipt has been received or a Delivery
+ * Receipt that couldn't be interpreted was received.
+ */
+ public static final DeliveryReportStatus UNKNOWN = new DeliveryReportStatus("Unknown");
+
+ private static final EnumSupportDynamic ENUM_SUPPORT =
+ new EnumSupportDynamic<>(
+ DeliveryReportStatus.class,
+ DeliveryReportStatus::new,
+ Arrays.asList(
+ QUEUED,
+ DISPATCHED,
+ ABORTED,
+ CANCELLED,
+ REJECTED,
+ DELETED,
+ DELIVERED,
+ FAILED,
+ EXPIRED,
+ UNKNOWN));
+
+ private DeliveryReportStatus(String value) {
+ super(value);
+ }
+
+ public static Stream values() {
+ return ENUM_SUPPORT.values();
+ }
+
+ public static DeliveryReportStatus from(String value) {
+ return ENUM_SUPPORT.from(value);
+ }
+
+ public static String valueOf(DeliveryReportStatus e) {
+ return ENUM_SUPPORT.valueOf(e);
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseDeliveryReport.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseDeliveryReport.java
new file mode 100644
index 00000000..767b1c11
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseDeliveryReport.java
@@ -0,0 +1,72 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Base class for Delivery Report WebHook
+ *
+ * @since 1.0
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.EXISTING_PROPERTY,
+ property = "type",
+ visible = true)
+@JsonSubTypes({
+ @JsonSubTypes.Type(
+ value = DeliveryReportRecipientSMS.class,
+ name = "recipient_delivery_report_sms"),
+ @JsonSubTypes.Type(
+ value = DeliveryReportRecipientMMS.class,
+ name = "recipient_delivery_report_mms"),
+ @JsonSubTypes.Type(value = DeliveryReportSMS.class, name = "delivery_report_sms"),
+ @JsonSubTypes.Type(value = DeliveryReportMMS.class, name = "delivery_report_mms")
+})
+public abstract class BaseDeliveryReport {
+
+ static final String JSON_PROPERTY_BATCH_ID = "batch_id";
+ private final String batchId;
+ static final String JSON_PROPERTY_CLIENT_REFERENCE = "client_reference";
+ private final String clientReference;
+
+ /**
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ */
+ @JsonCreator
+ public BaseDeliveryReport(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference) {
+ Objects.requireNonNull(batchId);
+ this.batchId = batchId;
+ this.clientReference = clientReference;
+ }
+
+ public String getBatchId() {
+ return batchId;
+ }
+
+ public Optional getClientReference() {
+ return Optional.ofNullable(clientReference);
+ }
+
+ @Override
+ public String toString() {
+ return "BaseDeliveryReport{"
+ + "batchId='"
+ + batchId
+ + '\''
+ + ", clientReference='"
+ + clientReference
+ + '\''
+ + '}';
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseIncomingSMS.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseIncomingSMS.java
new file mode 100644
index 00000000..608e7073
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/BaseIncomingSMS.java
@@ -0,0 +1,98 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.util.Optional;
+
+/**
+ * Base class for Incoming SMS Webhook
+ *
+ * @param Type of SMS body
+ * @since 1.0
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.EXISTING_PROPERTY,
+ property = "type",
+ visible = true)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = IncomingSMSBinary.class, name = "mo_binary"),
+ @JsonSubTypes.Type(value = IncomingSMSText.class, name = "mo_text")
+})
+public abstract class BaseIncomingSMS {
+
+ static final String JSON_PROPERTY_BODY = "body";
+ private final T body;
+ static final String JSON_PROPERTY_FROM = "from";
+ private final String from;
+ static final String JSON_PROPERTY_ID = "id";
+ private final String id;
+ static final String JSON_PROPERTY_RECEIVED_AT = "received_at";
+ private final Instant receivedAt;
+ static final String JSON_PROPERTY_TO = "to";
+ private final String to;
+ static final String JSON_PROPERTY_CLIENT_REFERENCE = "client_reference";
+ private final String clientReference;
+ static final String JSON_PROPERTY_OPERATOR_ID = "operator_id";
+ private final String operatorId;
+ static final String JSON_PROPERTY_SENT_AT = "sent_at";
+ private final Instant sentAt;
+
+ @JsonCreator
+ public BaseIncomingSMS(
+ @JsonProperty(JSON_PROPERTY_BODY) T body,
+ @JsonProperty(JSON_PROPERTY_FROM) String from,
+ @JsonProperty(JSON_PROPERTY_ID) String id,
+ @JsonProperty(JSON_PROPERTY_RECEIVED_AT) OffsetDateTime receivedAt,
+ @JsonProperty(JSON_PROPERTY_TO) String to,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_OPERATOR_ID) String operatorId,
+ @JsonProperty(JSON_PROPERTY_SENT_AT) OffsetDateTime sentAt) {
+ this.body = body;
+ this.from = from;
+ this.id = id;
+ this.receivedAt = receivedAt.toInstant();
+ this.to = to;
+ this.clientReference = clientReference;
+ this.operatorId = operatorId;
+ this.sentAt = null != sentAt ? sentAt.toInstant() : null;
+ }
+
+ public T getBody() {
+ return body;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public Instant getReceivedAt() {
+ return receivedAt;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public Optional getClientReference() {
+ return Optional.ofNullable(clientReference);
+ }
+
+ public Optional getOperatorId() {
+ return Optional.ofNullable(operatorId);
+ }
+
+ public Optional getSentAt() {
+ return Optional.ofNullable(sentAt);
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReport.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReport.java
new file mode 100644
index 00000000..7f87aa0a
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReport.java
@@ -0,0 +1,59 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * Common Definition to Delivery Report
+ *
+ * @since 1.0
+ */
+public abstract class DeliveryReport extends BaseDeliveryReport {
+
+ static final String JSON_PROPERTY_STATUSES = "statuses";
+ private final Collection statuses;
+ static final String JSON_PROPERTY_TOTAL_MESSAGE_COUNT = "total_message_count";
+ private final Integer totalMessageCount;
+
+ /**
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ * @param statuses Required.
Array with status objects. Only status codes with at
+ * least one recipient will be listed.
+ * @param totalMessageCount Required.
The total number of messages in the batch.
+ */
+ @JsonCreator
+ public DeliveryReport(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_STATUSES) Collection statuses,
+ @JsonProperty(JSON_PROPERTY_TOTAL_MESSAGE_COUNT) Integer totalMessageCount) {
+ super(batchId, clientReference);
+ Objects.requireNonNull(statuses);
+ Objects.requireNonNull(totalMessageCount);
+ this.statuses = statuses;
+ this.totalMessageCount = totalMessageCount;
+ }
+
+ public Collection getStatuses() {
+ return statuses;
+ }
+
+ public Integer getTotalMessageCount() {
+ return totalMessageCount;
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReport{"
+ + "statuses="
+ + statuses
+ + ", totalMessageCount="
+ + totalMessageCount
+ + "} "
+ + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportMMS.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportMMS.java
new file mode 100644
index 00000000..a98b4673
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportMMS.java
@@ -0,0 +1,35 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+
+/**
+ * MMS delivery Report
+ *
+ * @since 1.0
+ */
+public class DeliveryReportMMS extends DeliveryReport {
+
+ /**
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ * @param statuses Required.
Array with status objects. Only status codes with at
+ * least one recipient will be listed.
+ * @param totalMessageCount Required.
The total number of messages in the batch.
+ */
+ @JsonCreator
+ public DeliveryReportMMS(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_STATUSES) Collection statuses,
+ @JsonProperty(JSON_PROPERTY_TOTAL_MESSAGE_COUNT) Integer totalMessageCount) {
+ super(batchId, clientReference, statuses, totalMessageCount);
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReportMMS{} " + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipient.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipient.java
new file mode 100644
index 00000000..d4a42b0b
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipient.java
@@ -0,0 +1,151 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.sinch.sdk.domains.sms.models.DeliveryReportStatus;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.util.Optional;
+
+/**
+ * Common Definition to Delivery Report
+ *
+ * @since 1.0
+ */
+public abstract class DeliveryReportRecipient extends BaseDeliveryReport {
+
+ static final String JSON_PROPERTY_AT = "at";
+ private final Instant at;
+ static final String JSON_PROPERTY_CODE = "code";
+ private final Integer code;
+ static final String JSON_PROPERTY_RECIPIENT = "recipient";
+ private final String recipient;
+ static final String JSON_PROPERTY_STATUS = "status";
+ private final DeliveryReportStatus status;
+ static final String JSON_PROPERTY_APPLIED_ORIGINATOR = "applied_originator";
+ private final String appliedOriginator;
+ static final String JSON_PROPERTY_ENCODING = "encoding";
+ private final String encoding;
+ static final String JSON_PROPERTY_NUMBER_OF_MESSAGE_PARTS = "number_of_message_parts";
+ private final Integer numberOfMessageParts;
+ static final String JSON_PROPERTY_OPERATOR = "operator";
+ private final String operator;
+ static final String JSON_PROPERTY_OPERATOR_STATUS_AT = "operator_status_at";
+ private final Instant operatorStatusAt;
+
+ /**
+ * Recipient Delivery Report Recipient
+ *
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ * @param at Required.
A timestamp of when the Delivery Report was created in the
+ * Sinch service
+ * @param code Required.
The detailed status
+ * code.
+ * @param recipient Required.
Phone number that was queried.
+ * @param status Required.
The simplified status as described in Delivery Report
+ * Statuses
+ * @param appliedOriginator The default originator used for the recipient this delivery report
+ * belongs to, if default originator pool configured and no originator set when submitting
+ * batch.
+ * @param encoding Applied encoding for message. Present only if smart encoding is enabled.
+ * @param numberOfMessageParts The number of parts the message was split into. Present only if
+ * max_number_of_message_parts
parameter was set.
+ * @param operator The operator that was used for delivering the message to this recipient, if
+ * enabled on the account by Sinch.
+ * @param operatorStatusAt A timestamp extracted from the Delivery Receipt from the originating
+ * SMSC
+ */
+ @JsonCreator
+ public DeliveryReportRecipient(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_AT) OffsetDateTime at,
+ @JsonProperty(JSON_PROPERTY_CODE) Integer code,
+ @JsonProperty(JSON_PROPERTY_RECIPIENT) String recipient,
+ @JsonProperty(JSON_PROPERTY_STATUS) String status,
+ @JsonProperty(JSON_PROPERTY_APPLIED_ORIGINATOR) String appliedOriginator,
+ @JsonProperty(JSON_PROPERTY_ENCODING) String encoding,
+ @JsonProperty(JSON_PROPERTY_NUMBER_OF_MESSAGE_PARTS) Integer numberOfMessageParts,
+ @JsonProperty(JSON_PROPERTY_OPERATOR) String operator,
+ @JsonProperty(JSON_PROPERTY_OPERATOR_STATUS_AT) OffsetDateTime operatorStatusAt) {
+ super(batchId, clientReference);
+ this.at = null != at ? at.toInstant() : null;
+ this.code = code;
+ this.recipient = recipient;
+ this.status = DeliveryReportStatus.from(status);
+ this.appliedOriginator = appliedOriginator;
+ this.encoding = encoding;
+ this.numberOfMessageParts = numberOfMessageParts;
+ this.operator = operator;
+ this.operatorStatusAt = null != operatorStatusAt ? operatorStatusAt.toInstant() : null;
+ }
+
+ public Instant getAt() {
+ return at;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getRecipient() {
+ return recipient;
+ }
+
+ public DeliveryReportStatus getStatus() {
+ return status;
+ }
+
+ public Optional getAppliedOriginator() {
+ return Optional.ofNullable(appliedOriginator);
+ }
+
+ public Optional getEncoding() {
+ return Optional.ofNullable(encoding);
+ }
+
+ public Optional getNumberOfMessageParts() {
+ return Optional.ofNullable(numberOfMessageParts);
+ }
+
+ public Optional getOperator() {
+ return Optional.ofNullable(operator);
+ }
+
+ public Optional getOperatorStatusAt() {
+ return Optional.ofNullable(operatorStatusAt);
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReportRecipient{"
+ + "at="
+ + at
+ + ", code='"
+ + code
+ + '\''
+ + ", recipient='"
+ + recipient
+ + '\''
+ + ", status="
+ + status
+ + ", appliedOriginator='"
+ + appliedOriginator
+ + '\''
+ + ", encoding='"
+ + encoding
+ + '\''
+ + ", numberOfMessageParts="
+ + numberOfMessageParts
+ + ", operator='"
+ + operator
+ + '\''
+ + ", operatorStatusAt="
+ + operatorStatusAt
+ + "} "
+ + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientMMS.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientMMS.java
new file mode 100644
index 00000000..09508a32
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientMMS.java
@@ -0,0 +1,70 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.OffsetDateTime;
+
+/**
+ * SMS Delivery Report Recipient for MMS
+ *
+ * @since 1.0
+ */
+public class DeliveryReportRecipientMMS extends DeliveryReportRecipient {
+
+ /**
+ * Recipient Delivery Report for MMS
+ *
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ * @param at Required.
A timestamp of when the Delivery Report was created in the
+ * Sinch service
+ * @param code Required.
The detailed status
+ * code.
+ * @param recipient Required.
Phone number that was queried.
+ * @param status Required.
The simplified status as described in Delivery Report
+ * Statuses
+ * @param appliedOriginator The default originator used for the recipient this delivery report
+ * belongs to, if default originator pool configured and no originator set when submitting
+ * batch.
+ * @param encoding Applied encoding for message. Present only if smart encoding is enabled.
+ * @param numberOfMessageParts The number of parts the message was split into. Present only if
+ * max_number_of_message_parts
parameter was set.
+ * @param operator The operator that was used for delivering the message to this recipient, if
+ * enabled on the account by Sinch.
+ * @param operatorStatusAt A timestamp extracted from the Delivery Receipt from the originating
+ * SMSC
+ */
+ @JsonCreator
+ public DeliveryReportRecipientMMS(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_AT) OffsetDateTime at,
+ @JsonProperty(JSON_PROPERTY_CODE) Integer code,
+ @JsonProperty(JSON_PROPERTY_RECIPIENT) String recipient,
+ @JsonProperty(JSON_PROPERTY_STATUS) String status,
+ @JsonProperty(JSON_PROPERTY_APPLIED_ORIGINATOR) String appliedOriginator,
+ @JsonProperty(JSON_PROPERTY_ENCODING) String encoding,
+ @JsonProperty(JSON_PROPERTY_NUMBER_OF_MESSAGE_PARTS) Integer numberOfMessageParts,
+ @JsonProperty(JSON_PROPERTY_OPERATOR) String operator,
+ @JsonProperty(JSON_PROPERTY_OPERATOR_STATUS_AT) OffsetDateTime operatorStatusAt) {
+ super(
+ batchId,
+ clientReference,
+ at,
+ code,
+ recipient,
+ status,
+ appliedOriginator,
+ encoding,
+ numberOfMessageParts,
+ operator,
+ operatorStatusAt);
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReportRecipientMMS{} " + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientSMS.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientSMS.java
new file mode 100644
index 00000000..1399d503
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportRecipientSMS.java
@@ -0,0 +1,70 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.OffsetDateTime;
+
+/**
+ * SMS Delivery Report Recipient for SMS
+ *
+ * @since 1.0
+ */
+public class DeliveryReportRecipientSMS extends DeliveryReportRecipient {
+
+ /**
+ * Recipient Delivery Report for SMS
+ *
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ * @param at Required.
A timestamp of when the Delivery Report was created in the
+ * Sinch service
+ * @param code Required.
The detailed status
+ * code.
+ * @param recipient Required.
Phone number that was queried.
+ * @param status Required.
The simplified status as described in Delivery Report
+ * Statuses
+ * @param appliedOriginator The default originator used for the recipient this delivery report
+ * belongs to, if default originator pool configured and no originator set when submitting
+ * batch.
+ * @param encoding Applied encoding for message. Present only if smart encoding is enabled.
+ * @param numberOfMessageParts The number of parts the message was split into. Present only if
+ * max_number_of_message_parts
parameter was set.
+ * @param operator The operator that was used for delivering the message to this recipient, if
+ * enabled on the account by Sinch.
+ * @param operatorStatusAt A timestamp extracted from the Delivery Receipt from the originating
+ * SMSC
+ */
+ @JsonCreator
+ public DeliveryReportRecipientSMS(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_AT) OffsetDateTime at,
+ @JsonProperty(JSON_PROPERTY_CODE) Integer code,
+ @JsonProperty(JSON_PROPERTY_RECIPIENT) String recipient,
+ @JsonProperty(JSON_PROPERTY_STATUS) String status,
+ @JsonProperty(JSON_PROPERTY_APPLIED_ORIGINATOR) String appliedOriginator,
+ @JsonProperty(JSON_PROPERTY_ENCODING) String encoding,
+ @JsonProperty(JSON_PROPERTY_NUMBER_OF_MESSAGE_PARTS) Integer numberOfMessageParts,
+ @JsonProperty(JSON_PROPERTY_OPERATOR) String operator,
+ @JsonProperty(JSON_PROPERTY_OPERATOR_STATUS_AT) OffsetDateTime operatorStatusAt) {
+ super(
+ batchId,
+ clientReference,
+ at,
+ code,
+ recipient,
+ status,
+ appliedOriginator,
+ encoding,
+ numberOfMessageParts,
+ operator,
+ operatorStatusAt);
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReportRecipientSMS{} " + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportSMS.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportSMS.java
new file mode 100644
index 00000000..86f59969
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportSMS.java
@@ -0,0 +1,35 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Collection;
+
+/**
+ * SMS delivery Report
+ *
+ * @since 1.0
+ */
+public class DeliveryReportSMS extends DeliveryReport {
+
+ /**
+ * @param batchId Required.
The ID of the batch this delivery report belongs to.
+ * @param clientReference The client identifier of the batch this delivery report belongs to, if
+ * set when submitting batch.
+ * @param statuses Required.
Array with status objects. Only status codes with at
+ * least one recipient will be listed.
+ * @param totalMessageCount Required.
The total number of messages in the batch.
+ */
+ @JsonCreator
+ public DeliveryReportSMS(
+ @JsonProperty(JSON_PROPERTY_BATCH_ID) String batchId,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_STATUSES) Collection statuses,
+ @JsonProperty(JSON_PROPERTY_TOTAL_MESSAGE_COUNT) Integer totalMessageCount) {
+ super(batchId, clientReference, statuses, totalMessageCount);
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReportSMS{} " + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportStatusDetails.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportStatusDetails.java
new file mode 100644
index 00000000..fd1e9724
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/DeliveryReportStatusDetails.java
@@ -0,0 +1,75 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.sinch.sdk.domains.sms.models.DeliveryReportStatus;
+import java.util.Collection;
+
+/**
+ * Details related to a delivery report status
+ *
+ * @since 1.0
+ */
+public class DeliveryReportStatusDetails {
+
+ static final String JSON_PROPERTY_CODE = "code";
+ private final Integer code;
+ static final String JSON_PROPERTY_COUNT = "count";
+ private final Integer count;
+ static final String JSON_PROPERTY_RECIPIENTS = "recipients";
+ private final Collection recipients;
+ static final String JSON_PROPERTY_STATUS = "status";
+ private final DeliveryReportStatus status;
+
+ /**
+ * @param code Required.
The detailed status
+ * code.
+ * @param count Required.
The number of messages that currently has this code
+ * @param recipients Required.
Only for full report. A list of the phone number
+ * recipients which messages has this status code
+ * @param status Required.
The simplified status as described in Delivery Report
+ * Statuses
+ */
+ @JsonCreator
+ public DeliveryReportStatusDetails(
+ @JsonProperty(JSON_PROPERTY_CODE) Integer code,
+ @JsonProperty(JSON_PROPERTY_COUNT) Integer count,
+ @JsonProperty(JSON_PROPERTY_RECIPIENTS) Collection recipients,
+ @JsonProperty(JSON_PROPERTY_STATUS) String status) {
+ this.code = code;
+ this.count = count;
+ this.recipients = recipients;
+ this.status = DeliveryReportStatus.from(status);
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public Integer getCount() {
+ return count;
+ }
+
+ public Collection getRecipients() {
+ return recipients;
+ }
+
+ public DeliveryReportStatus getStatus() {
+ return status;
+ }
+
+ @Override
+ public String toString() {
+ return "DeliveryReportStatusDetails{"
+ + "code="
+ + code
+ + ", count="
+ + count
+ + ", recipients="
+ + recipients
+ + ", status="
+ + status
+ + '}';
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSBinary.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSBinary.java
new file mode 100644
index 00000000..764647eb
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSBinary.java
@@ -0,0 +1,58 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.OffsetDateTime;
+
+/**
+ * Incoming SMS Binary
+ *
+ * @since 1.0
+ */
+public class IncomingSMSBinary extends BaseIncomingSMS {
+
+ static final String JSON_PROPERTY_UDH = "udh";
+ private final String udh;
+
+ /**
+ * Binary MO class
+ *
+ * @param body The message content Base64 encoded. Max 140 bytes together with udh.
+ * @param from The phone number that sent the message. @see https://community.sinch.com/t5/Glossary/MSISDN/ta-p/7628
+ * @param id The ID of this inbound message.
+ * @param receivedAt When the system received the message.
+ * @param to The Sinch phone number or short code to which the message was sent.
+ * @param clientReference If this inbound message is in response to a previously sent message that
+ * contained a client reference, then this field contains that client reference. Utilizing
+ * this feature requires additional setup on your account. Contact your account manager to
+ * enable this feature.
+ * @param operatorId The MCC/MNC of the sender's operator if known.
+ * @param sendAt When the message left the originating device. Only available if provided by
+ * operator.
+ * @param udh The UDH header of a binary message HEX encoded. Max 140 bytes together with body.
+ */
+ @JsonCreator
+ public IncomingSMSBinary(
+ @JsonProperty(JSON_PROPERTY_BODY) String body,
+ @JsonProperty(JSON_PROPERTY_FROM) String from,
+ @JsonProperty(JSON_PROPERTY_ID) String id,
+ @JsonProperty(JSON_PROPERTY_RECEIVED_AT) OffsetDateTime receivedAt,
+ @JsonProperty(JSON_PROPERTY_TO) String to,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_OPERATOR_ID) String operatorId,
+ @JsonProperty(JSON_PROPERTY_SENT_AT) OffsetDateTime sendAt,
+ @JsonProperty(JSON_PROPERTY_UDH) String udh) {
+ super(body, from, id, receivedAt, to, clientReference, operatorId, sendAt);
+ this.udh = udh;
+ }
+
+ public String getUdh() {
+ return udh;
+ }
+
+ @Override
+ public String toString() {
+ return "IncomingSMSBinary{" + "udh='" + udh + '\'' + "} " + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSText.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSText.java
new file mode 100644
index 00000000..b560119e
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/IncomingSMSText.java
@@ -0,0 +1,48 @@
+package com.sinch.sdk.domains.sms.models.webhooks;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.time.OffsetDateTime;
+
+/**
+ * Incoming SMS Text
+ *
+ * @since 1.0
+ */
+public class IncomingSMSText extends BaseIncomingSMS {
+
+ /**
+ * Text MO class
+ *
+ * @param body The message content Base64 encoded. Max 140 bytes together with udh.
+ * @param from The phone number that sent the message. @see https://community.sinch.com/t5/Glossary/MSISDN/ta-p/7628
+ * @param id The ID of this inbound message.
+ * @param receivedAt When the system received the message.
+ * @param to The Sinch phone number or short code to which the message was sent.
+ * @param clientReference If this inbound message is in response to a previously sent message that
+ * contained a client reference, then this field contains that client reference. Utilizing
+ * this feature requires additional setup on your account. Contact your account manager to
+ * enable this feature.
+ * @param operatorId The MCC/MNC of the sender's operator if known.
+ * @param sendAt When the message left the originating device. Only available if provided by
+ * operator.
+ */
+ @JsonCreator
+ public IncomingSMSText(
+ @JsonProperty(JSON_PROPERTY_BODY) String body,
+ @JsonProperty(JSON_PROPERTY_FROM) String from,
+ @JsonProperty(JSON_PROPERTY_ID) String id,
+ @JsonProperty(JSON_PROPERTY_RECEIVED_AT) OffsetDateTime receivedAt,
+ @JsonProperty(JSON_PROPERTY_TO) String to,
+ @JsonProperty(JSON_PROPERTY_CLIENT_REFERENCE) String clientReference,
+ @JsonProperty(JSON_PROPERTY_OPERATOR_ID) String operatorId,
+ @JsonProperty(JSON_PROPERTY_SENT_AT) OffsetDateTime sendAt) {
+ super(body, from, id, receivedAt, to, clientReference, operatorId, sendAt);
+ }
+
+ @Override
+ public String toString() {
+ return "IncomingSMSText{} " + super.toString();
+ }
+}
diff --git a/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java
new file mode 100644
index 00000000..daf15120
--- /dev/null
+++ b/client/src/main/com/sinch/sdk/domains/sms/models/webhooks/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * SMS WebHooks models
+ *
+ * @since 1.0
+ */
+package com.sinch.sdk.domains.sms.models.webhooks;
diff --git a/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHKooksServiceTest.java b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHKooksServiceTest.java
new file mode 100644
index 00000000..29f47415
--- /dev/null
+++ b/client/src/test/java/com/sinch/sdk/domains/sms/adapters/WebHKooksServiceTest.java
@@ -0,0 +1,134 @@
+package com.sinch.sdk.domains.sms.adapters;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import com.adelean.inject.resources.junit.jupiter.GivenTextResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.core.exceptions.ApiException;
+import com.sinch.sdk.core.exceptions.ApiMappingException;
+import com.sinch.sdk.domains.sms.models.dto.v1.webhooks.DeliveryReportDtoTest;
+import com.sinch.sdk.domains.sms.models.dto.v1.webhooks.DeliveryReportRecipientDtoTest;
+import com.sinch.sdk.domains.sms.models.dto.v1.webhooks.IncomingSMSBinaryDtoTest;
+import com.sinch.sdk.domains.sms.models.dto.v1.webhooks.IncomingSMSTextDtoTest;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseDeliveryReport;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseIncomingSMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportMMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportRecipientMMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportRecipientSMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportSMS;
+import com.sinch.sdk.domains.sms.models.webhooks.IncomingSMSBinary;
+import com.sinch.sdk.domains.sms.models.webhooks.IncomingSMSText;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+
+@TestWithResources
+public class WebHKooksServiceTest extends BaseTest {
+
+ @GivenTextResource("/domains/sms/v1/webhooks/IncomingSMSBinary.json")
+ String incomingSMSBinaryJsonString;
+
+ @GivenTextResource("/domains/sms/v1/webhooks/IncomingSMSText.json")
+ String incomingSMSTextJsonString;
+
+ @GivenTextResource("/domains/sms/v1/webhooks/DeliveryReportRecipientSMS.json")
+ String deliveryReportRecipientSMSJsonString;
+
+ @GivenTextResource("/domains/sms/v1/webhooks/DeliveryReportRecipientMMS.json")
+ String deliveryReportRecipientMMSJsonString;
+
+ @GivenTextResource("/domains/sms/v1/webhooks/DeliveryReportSMS.json")
+ String deliveryReportSMSJsonString;
+
+ @GivenTextResource("/domains/sms/v1/webhooks/DeliveryReportMMS.json")
+ String deliveryReportMMSJsonString;
+
+ @InjectMocks WebHooksService service;
+
+ @Test
+ void incomingSMSBinary() throws ApiException {
+
+ BaseIncomingSMS> response = service.incomingSMS(incomingSMSBinaryJsonString);
+
+ Assertions.assertThat(response).isInstanceOf(IncomingSMSBinary.class);
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(IncomingSMSBinaryDtoTest.incomingSMSBinary);
+ }
+
+ @Test
+ void incomingSMSText() throws ApiException {
+
+ BaseIncomingSMS> response = service.incomingSMS(incomingSMSTextJsonString);
+
+ Assertions.assertThat(response).isInstanceOf(IncomingSMSText.class);
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(IncomingSMSTextDtoTest.incomingSMSText);
+ }
+
+ @Test
+ void handleExceptionIncomingSMS() throws ApiException {
+
+ String jsonPayload = incomingSMSBinaryJsonString.replace("mo_binary", "foo type");
+ ApiMappingException thrown =
+ assertThrows(ApiMappingException.class, () -> service.incomingSMS(jsonPayload));
+ assertTrue(thrown.getMessage().contains(jsonPayload));
+ }
+
+ @Test
+ void deliveryReportRecipientDeliveryReportSms() throws ApiException {
+
+ BaseDeliveryReport response = service.deliveryReport(deliveryReportRecipientSMSJsonString);
+
+ Assertions.assertThat(response).isInstanceOf(DeliveryReportRecipientSMS.class);
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(DeliveryReportRecipientDtoTest.deliveryReportRecipientSMS);
+ }
+
+ @Test
+ void deliveryReportRecipientDeliveryReportMms() throws ApiException {
+
+ BaseDeliveryReport response = service.deliveryReport(deliveryReportRecipientMMSJsonString);
+
+ Assertions.assertThat(response).isInstanceOf(DeliveryReportRecipientMMS.class);
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(DeliveryReportRecipientDtoTest.deliveryReportRecipientMMS);
+ }
+
+ @Test
+ void deliveryReportDeliveryReportSms() throws ApiException {
+
+ BaseDeliveryReport response = service.deliveryReport(deliveryReportSMSJsonString);
+
+ Assertions.assertThat(response).isInstanceOf(DeliveryReportSMS.class);
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(DeliveryReportDtoTest.deliveryReportSMS);
+ }
+
+ @Test
+ void deliveryReportDeliveryReportMms() throws ApiException {
+
+ BaseDeliveryReport response = service.deliveryReport(deliveryReportMMSJsonString);
+
+ Assertions.assertThat(response).isInstanceOf(DeliveryReportMMS.class);
+ Assertions.assertThat(response)
+ .usingRecursiveComparison()
+ .isEqualTo(DeliveryReportDtoTest.deliveryReportMMS);
+ }
+
+ @Test
+ void handleExceptionDeliveryReport() throws ApiException {
+
+ String jsonPayload =
+ deliveryReportRecipientMMSJsonString.replace("recipient_delivery_report_mms", "foo type");
+ ApiMappingException thrown =
+ assertThrows(ApiMappingException.class, () -> service.deliveryReport(jsonPayload));
+ assertTrue(thrown.getMessage().contains(jsonPayload));
+ }
+}
diff --git a/core/src/main/com/sinch/sdk/core/exceptions/ApiException.java b/core/src/main/com/sinch/sdk/core/exceptions/ApiException.java
index d7b31989..883fb3fa 100644
--- a/core/src/main/com/sinch/sdk/core/exceptions/ApiException.java
+++ b/core/src/main/com/sinch/sdk/core/exceptions/ApiException.java
@@ -15,6 +15,10 @@ public ApiException(String message) {
super(message);
}
+ public ApiException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
public ApiException(String message, Throwable throwable, int code) {
super(message, throwable);
this.code = code;
diff --git a/core/src/main/com/sinch/sdk/core/exceptions/ApiMappingException.java b/core/src/main/com/sinch/sdk/core/exceptions/ApiMappingException.java
new file mode 100644
index 00000000..426aedcd
--- /dev/null
+++ b/core/src/main/com/sinch/sdk/core/exceptions/ApiMappingException.java
@@ -0,0 +1,8 @@
+package com.sinch.sdk.core.exceptions;
+
+public class ApiMappingException extends ApiException {
+
+ public ApiMappingException(String payload, Throwable throwable) {
+ super(String.format("Unable to map string '%s'", payload), throwable);
+ }
+}
diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportDtoTest.java
new file mode 100644
index 00000000..3295dc2e
--- /dev/null
+++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportDtoTest.java
@@ -0,0 +1,53 @@
+package com.sinch.sdk.domains.sms.models.dto.v1.webhooks;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportMMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportSMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportStatusDetails;
+import java.util.Collections;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@TestWithResources
+public class DeliveryReportDtoTest extends BaseTest {
+
+ @GivenJsonResource("/domains/sms/v1/webhooks/DeliveryReportSMS.json")
+ DeliveryReportSMS deliveryReportSMSClient;
+
+ @GivenJsonResource("/domains/sms/v1/webhooks/DeliveryReportMMS.json")
+ DeliveryReportMMS deliveryReportMMSClient;
+
+ public static DeliveryReportSMS deliveryReportSMS =
+ new DeliveryReportSMS(
+ "01FC66621XXXXX119Z8PMV1QPQ",
+ null,
+ Collections.singletonList(
+ new DeliveryReportStatusDetails(
+ 0, 1, Collections.singletonList("44231235674"), "Delivered")),
+ 1);
+
+ public static DeliveryReportMMS deliveryReportMMS =
+ new DeliveryReportMMS(
+ "01FC66621XXXXX119Z8PMV1QPQ",
+ null,
+ Collections.singletonList(
+ new DeliveryReportStatusDetails(
+ 0, 1, Collections.singletonList("44231235674"), "Delivered")),
+ 1);
+
+ @Test
+ void deserializeDeliveryReportRecipientSMS() {
+ Assertions.assertThat(deliveryReportSMS)
+ .usingRecursiveComparison()
+ .isEqualTo(deliveryReportSMSClient);
+ }
+
+ @Test
+ void deserializeDeliveryReportRecipientMMS() {
+ Assertions.assertThat(deliveryReportMMS)
+ .usingRecursiveComparison()
+ .isEqualTo(deliveryReportMMSClient);
+ }
+}
diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportRecipientDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportRecipientDtoTest.java
new file mode 100644
index 00000000..03778ca9
--- /dev/null
+++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/DeliveryReportRecipientDtoTest.java
@@ -0,0 +1,62 @@
+package com.sinch.sdk.domains.sms.models.dto.v1.webhooks;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportRecipientMMS;
+import com.sinch.sdk.domains.sms.models.webhooks.DeliveryReportRecipientSMS;
+import java.time.OffsetDateTime;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@TestWithResources
+public class DeliveryReportRecipientDtoTest extends BaseTest {
+
+ @GivenJsonResource("/domains/sms/v1/webhooks/DeliveryReportRecipientSMS.json")
+ DeliveryReportRecipientSMS deliveryReportRecipientSMSClient;
+
+ @GivenJsonResource("/domains/sms/v1/webhooks/DeliveryReportRecipientMMS.json")
+ DeliveryReportRecipientMMS deliveryReportRecipientMMSClient;
+
+ public static DeliveryReportRecipientSMS deliveryReportRecipientSMS =
+ new DeliveryReportRecipientSMS(
+ "01FC66621XXXXX119Z8PMV1QPQ",
+ "client reference",
+ OffsetDateTime.parse("2022-08-30T08:16:08.930Z"),
+ 401,
+ "+44231235674",
+ "Dispatched",
+ "applied originator",
+ "encoding",
+ 123,
+ "operator",
+ OffsetDateTime.parse("2022-08-30T08:16:08.150Z"));
+
+ public static DeliveryReportRecipientMMS deliveryReportRecipientMMS =
+ new DeliveryReportRecipientMMS(
+ "01FC66621XXXXX119Z8PMV1QPQ",
+ "client reference",
+ OffsetDateTime.parse("2022-08-30T08:16:08.930Z"),
+ 401,
+ "+44231235674",
+ "Dispatched",
+ "applied originator",
+ "encoding",
+ 123,
+ "operator",
+ OffsetDateTime.parse("2022-08-30T08:16:08.150Z"));
+
+ @Test
+ void deserializeDeliveryReportRecipientSMS() {
+ Assertions.assertThat(deliveryReportRecipientSMS)
+ .usingRecursiveComparison()
+ .isEqualTo(deliveryReportRecipientSMSClient);
+ }
+
+ @Test
+ void deserializeDeliveryReportRecipientMMS() {
+ Assertions.assertThat(deliveryReportRecipientMMS)
+ .usingRecursiveComparison()
+ .isEqualTo(deliveryReportRecipientMMSClient);
+ }
+}
diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSBinaryDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSBinaryDtoTest.java
new file mode 100644
index 00000000..c4427793
--- /dev/null
+++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSBinaryDtoTest.java
@@ -0,0 +1,34 @@
+package com.sinch.sdk.domains.sms.models.dto.v1.webhooks;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.domains.sms.models.webhooks.IncomingSMSBinary;
+import java.time.OffsetDateTime;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@TestWithResources
+public class IncomingSMSBinaryDtoTest extends BaseTest {
+
+ @GivenJsonResource("/domains/sms/v1/webhooks/IncomingSMSBinary.json")
+ IncomingSMSBinary client;
+
+ public static IncomingSMSBinary incomingSMSBinary =
+ new IncomingSMSBinary(
+ "VGV4dCBtZXNzYWdl",
+ "16051234567",
+ "01XXXXX21XXXXX119Z8P1XXXXX",
+ OffsetDateTime.parse("2022-08-24T14:15:22Z"),
+ "13185551234",
+ null,
+ "operator",
+ OffsetDateTime.parse("2022-08-24T14:15:44Z"),
+ "10010203040506070809000a0b0c0d0e0f");
+
+ @Test
+ void deserialize() {
+
+ Assertions.assertThat(incomingSMSBinary).usingRecursiveComparison().isEqualTo(client);
+ }
+}
diff --git a/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSTextDtoTest.java b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSTextDtoTest.java
new file mode 100644
index 00000000..c049199b
--- /dev/null
+++ b/openapi-contracts/src/test/java/com/sinch/sdk/domains/sms/models/dto/v1/webhooks/IncomingSMSTextDtoTest.java
@@ -0,0 +1,33 @@
+package com.sinch.sdk.domains.sms.models.dto.v1.webhooks;
+
+import com.adelean.inject.resources.junit.jupiter.GivenJsonResource;
+import com.adelean.inject.resources.junit.jupiter.TestWithResources;
+import com.sinch.sdk.BaseTest;
+import com.sinch.sdk.domains.sms.models.webhooks.IncomingSMSText;
+import java.time.OffsetDateTime;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+@TestWithResources
+public class IncomingSMSTextDtoTest extends BaseTest {
+
+ @GivenJsonResource("/domains/sms/v1/webhooks/IncomingSMSText.json")
+ IncomingSMSText client;
+
+ public static IncomingSMSText incomingSMSText =
+ new IncomingSMSText(
+ "This is a test message.",
+ "16051234567",
+ "01XXXXX21XXXXX119Z8P1XXXXX",
+ OffsetDateTime.parse("2022-08-24T14:15:22Z"),
+ "13185551234",
+ null,
+ "string",
+ null);
+
+ @Test
+ void deserialize() {
+
+ Assertions.assertThat(incomingSMSText).usingRecursiveComparison().isEqualTo(client);
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java b/sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java
new file mode 100644
index 00000000..e90fed9a
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/webhooks/DeliveryReport.java
@@ -0,0 +1,46 @@
+package com.sinch.sample.sms.webhooks;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseDeliveryReport;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class DeliveryReport extends BaseApplication {
+ private static final Logger LOGGER = Logger.getLogger(DeliveryReport.class.getName());
+
+ public DeliveryReport() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new DeliveryReport().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String payload =
+ "{\n"
+ + " \"type\": \"delivery_report_sms\",\n"
+ + " \"batch_id\": \"01FC66621XXXXX119Z8PMV1QPQ\",\n"
+ + " \"statuses\": [\n"
+ + " {\n"
+ + " \"code\": 0,\n"
+ + " \"count\": 1,\n"
+ + " \"recipients\": [\n"
+ + " \"44231235674\"\n"
+ + " ],\n"
+ + " \"status\": \"Delivered\"\n"
+ + " }\n"
+ + " ],\n"
+ + " \"total_message_count\": 1\n"
+ + "}";
+ LOGGER.info("Convert payload" + payload);
+
+ BaseDeliveryReport value = client.sms().webHooks().deliveryReport(payload);
+
+ LOGGER.info("Conversion result: " + value);
+ }
+}
diff --git a/sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java b/sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java
new file mode 100644
index 00000000..1889bd59
--- /dev/null
+++ b/sample-app/src/main/java/com/sinch/sample/sms/webhooks/IncomingSMS.java
@@ -0,0 +1,40 @@
+package com.sinch.sample.sms.webhooks;
+
+import com.sinch.sample.BaseApplication;
+import com.sinch.sdk.domains.sms.models.webhooks.BaseIncomingSMS;
+import java.io.IOException;
+import java.util.logging.Logger;
+
+public class IncomingSMS extends BaseApplication {
+ private static final Logger LOGGER = Logger.getLogger(IncomingSMS.class.getName());
+
+ public IncomingSMS() throws IOException {}
+
+ public static void main(String[] args) {
+ try {
+ new IncomingSMS().run();
+ } catch (Exception e) {
+ LOGGER.severe(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ public void run() {
+
+ String payload =
+ "{\n"
+ + " \"body\": \"This is a test message.\",\n"
+ + " \"from\": \"16051234567\",\n"
+ + " \"id\": \"01XXXXX21XXXXX119Z8P1XXXXX\",\n"
+ + " \"operator_id\": \"string\",\n"
+ + " \"received_at\": \"2022-08-24T14:15:22Z\",\n"
+ + " \"to\": \"13185551234\",\n"
+ + " \"type\": \"mo_text\"\n"
+ + "}";
+ LOGGER.info("Convert payload" + payload);
+
+ BaseIncomingSMS> value = client.sms().webHooks().incomingSMS(payload);
+
+ LOGGER.info("Conversion result: " + value);
+ }
+}
diff --git a/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportMMS.json b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportMMS.json
new file mode 100644
index 00000000..a1bf1338
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportMMS.json
@@ -0,0 +1,15 @@
+{
+ "type": "delivery_report_mms",
+ "batch_id": "01FC66621XXXXX119Z8PMV1QPQ",
+ "statuses": [
+ {
+ "code": 0,
+ "count": 1,
+ "recipients": [
+ "44231235674"
+ ],
+ "status": "Delivered"
+ }
+ ],
+ "total_message_count": 1
+}
\ No newline at end of file
diff --git a/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientMMS.json b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientMMS.json
new file mode 100644
index 00000000..3d7c97b7
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientMMS.json
@@ -0,0 +1,15 @@
+{
+
+ "type": "recipient_delivery_report_mms",
+ "batch_id": "01FC66621XXXXX119Z8PMV1QPQ",
+ "recipient": "+44231235674",
+ "code": 401,
+ "status": "Dispatched",
+ "at": "2022-08-30T08:16:08.930Z",
+ "operator": "operator",
+ "applied_originator": "applied originator",
+ "client_reference": "client reference",
+ "encoding": "encoding",
+ "number_of_message_parts": 123,
+ "operator_status_at":"2022-08-30T08:16:08.150Z"
+}
\ No newline at end of file
diff --git a/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientSMS.json b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientSMS.json
new file mode 100644
index 00000000..896f6cad
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportRecipientSMS.json
@@ -0,0 +1,15 @@
+{
+
+ "type": "recipient_delivery_report_sms",
+ "batch_id": "01FC66621XXXXX119Z8PMV1QPQ",
+ "recipient": "+44231235674",
+ "code": 401,
+ "status": "Dispatched",
+ "at": "2022-08-30T08:16:08.930Z",
+ "operator": "operator",
+ "applied_originator": "applied originator",
+ "client_reference": "client reference",
+ "encoding": "encoding",
+ "number_of_message_parts": 123,
+ "operator_status_at":"2022-08-30T08:16:08.150Z"
+}
\ No newline at end of file
diff --git a/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportSMS.json b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportSMS.json
new file mode 100644
index 00000000..f35d84e4
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/webhooks/DeliveryReportSMS.json
@@ -0,0 +1,15 @@
+{
+ "type": "delivery_report_sms",
+ "batch_id": "01FC66621XXXXX119Z8PMV1QPQ",
+ "statuses": [
+ {
+ "code": 0,
+ "count": 1,
+ "recipients": [
+ "44231235674"
+ ],
+ "status": "Delivered"
+ }
+ ],
+ "total_message_count": 1
+}
\ No newline at end of file
diff --git a/test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSBinary.json b/test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSBinary.json
new file mode 100644
index 00000000..2c698b57
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSBinary.json
@@ -0,0 +1,11 @@
+{
+ "body": "VGV4dCBtZXNzYWdl",
+ "from": "16051234567",
+ "id": "01XXXXX21XXXXX119Z8P1XXXXX",
+ "operator_id": "operator",
+ "received_at": "2022-08-24T14:15:22Z",
+ "sent_at": "2022-08-24T14:15:44Z",
+ "to": "13185551234",
+ "type": "mo_binary",
+ "udh": "10010203040506070809000a0b0c0d0e0f"
+}
\ No newline at end of file
diff --git a/test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSText.json b/test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSText.json
new file mode 100644
index 00000000..a97b50f0
--- /dev/null
+++ b/test-resources/src/test/resources/domains/sms/v1/webhooks/IncomingSMSText.json
@@ -0,0 +1,9 @@
+{
+ "body": "This is a test message.",
+ "from": "16051234567",
+ "id": "01XXXXX21XXXXX119Z8P1XXXXX",
+ "operator_id": "string",
+ "received_at": "2022-08-24T14:15:22Z",
+ "to": "13185551234",
+ "type": "mo_text"
+}
\ No newline at end of file