Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4898ded
feat (Conversation): Deprecation of 'SINCH_CHAT'
JPPortier Oct 27, 2025
01a4785
feat (Conversation): [Breaking change] Support 'PaymentLink' and Bole…
JPPortier Oct 27, 2025
d0eb677
feat (Conversation/KakaoTalk): Support 'KakaoTalkButtons'
JPPortier Oct 28, 2025
ccf4434
feat (Conversation): Support 'KakaoTalkCoupons'
JPPortier Oct 29, 2025
038a177
feat (Conversation): Support 'KakaoTalkCommerce'
JPPortier Oct 29, 2025
abdc924
feat (Conversation): Support kakao 'Image'
JPPortier Oct 29, 2025
236afc4
feat (Conversation): Support kakaotalk 'KakaoTalkCommerceChannelSpeci…
JPPortier Oct 29, 2025
eaed47c
feat (Conversation): Support kakaotalk 'KakaoTalkCarouselCommerceChan…
JPPortier Oct 29, 2025
956dd94
feat (Conversation): Support 'COMMERCE' and 'CAROUSEL_COMMERCE' chann…
JPPortier Oct 29, 2025
9ff6773
feat (Conversation): Support new fields for 'ClientCredentials'
JPPortier Oct 29, 2025
46af4e8
feat (Conversation): Support new 'listIdentityConflicts' endpoint
JPPortier Oct 29, 2025
b24ac83
refactor (Conversation): catch-up with generator reordering function
JPPortier Nov 3, 2025
5976ba6
feat (Conversation): Support 'Project Settings'
JPPortier Nov 3, 2025
5a0e240
docs (Conversation): Comment update
JPPortier Dec 12, 2025
16bcb50
feat (Conversation): Support 'CalendarMessage' and 'ShareLocationMess…
JPPortier Dec 15, 2025
79bce95
feat (Conversation/Template): W49 Conversation template synch
JPPortier Dec 16, 2025
f0ad0a7
Merge pull request #289 from sinch/DEVEXP-1136-W49-OAS-catchup-conver…
JPPortier Dec 22, 2025
9520d33
Merge branch 'feat/V2.0-next' into DEVEXP-1112-W42-OAS-catchup-conver…
JPPortier Dec 22, 2025
e9cd1c9
Merge branch 'DEVEXP-1112-W42-OAS-catchup-conversation' into DEVEXP-1…
JPPortier Dec 22, 2025
ec30c5a
Merge pull request #294 from sinch/DEVEXP-1136-W49-OAS-catchup-conver…
JPPortier Dec 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions MIGRATION-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ This guide lists all removed classes and interfaces from V1 and how to migrate t

### [`Conversation`](https://www.javadoc.io/doc/com.sinch.sdk/sinch-sdk-java/2.0.0/com/sinch/sdk/domains/conversation/package-summary.html)

- Removed support of `SINCH_CHAT` channel.
- [channelspecific.whatsapp.payment.OrderDetailsPayment](https://www.javadoc.io/doc/com.sinch.sdk/sinch-sdk-java/latest/com/sinch/sdk/domains/conversation/models/v1/messages/types/channelspecific/whatsapp/payment/OrderDetailsPayment.html) is now processing `OderDetailsSettings` interface for payment settings to support `boleto` and `payment_link` payment methods.

#### Replacement models
| Old class | New class |
|--------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
import com.sinch.sdk.domains.conversation.models.v1.contact.request.ContactGetChannelProfileByChannelIdentityRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.ContactGetChannelProfileByContactIdRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.ContactListRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.IdentityConflictsListRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.ContactListResponse;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.IdentityConflictsListResponse;

/**
* Contact related service
Expand Down Expand Up @@ -149,4 +151,15 @@ public interface ContactService {
*/
String getChannelProfileByChannelIdentity(
ContactGetChannelProfileByChannelIdentityRequest parameters);

/**
* Lists Contact Identity Conflicts Lists contact identity conflicts across supported SIM-based
* channels (SMS, MMS, RCS). Use this to identify contact records sharing the same identity (e.g.,
* phone number), which must be resolved before enabling the Unified Contact ID feature.
*
* @param parameters Filtering parameters
* @return ListIdentityConflictsResponse
* @since 2.0
*/
IdentityConflictsListResponse listIdentityConflicts(IdentityConflictsListRequest parameters);
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,14 @@ public interface ConversationService {
*/
CapabilityService capability();

/**
* ProjectSettings Service instance
*
* @return service instance for project
* @since 2.0
*/
ProjectSettingsService projectSettings();

/**
* WebHooksService Service instance
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.sinch.sdk.domains.conversation.api.v1;

import com.sinch.sdk.domains.conversation.models.v1.projectsettings.request.ProjectSettingsRequest;
import com.sinch.sdk.domains.conversation.models.v1.projectsettings.response.ProjectSettingsResponse;

/**
* Project Settings related service
*
* @see <a
* href="https://developers.sinch.com/docs/conversation/api-reference/conversation/project-settings">https://developers.sinch.com/docs/conversation/api-reference/conversation/project-settings</a>
* @since 2.0
*/
public interface ProjectSettingsService {

/**
* Create Project Settings Creates initial settings for the project. Useful for enabling features
* like Unified Contact ID. For new projects with no existing contacts, you can enable Unified
* Contact ID immediately.
*
* @param projectSettingsRequest The project settings to create. (required)
* @return ProjectSettingsResponse
*/
ProjectSettingsResponse create(ProjectSettingsRequest projectSettingsRequest);

/** Delete Project Settings Deletes all project-level settings for the specified project. */
void delete();

/**
* Get Project Settings Retrieves the current settings for the specified project, including
* contact management options such as Unified Contact ID.
*
* @return ProjectSettingsResponse
*/
ProjectSettingsResponse get();

/**
* Update Project Settings Updates project settings (e.g. enabling/disabling Unified Contact ID).
* For existing projects, you must resolve all identity conflicts before enabling Unified Contact
* ID.
*
* @param projectSettingsRequest The project settings to update. (required)
* @return ProjectSettingsResponse
*/
ProjectSettingsResponse update(ProjectSettingsRequest projectSettingsRequest);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
import com.sinch.sdk.domains.conversation.models.v1.contact.request.ContactGetChannelProfileByContactIdRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.ContactListRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.GetChannelProfileRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.IdentityConflictsListRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.request.MergeContactRequest;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.ContactListResponse;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.IdentityConflicts;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.IdentityConflictsListResponse;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.ListContactsResponse;
import com.sinch.sdk.domains.conversation.models.v1.contact.response.ListIdentityConflictsResponse;
import com.sinch.sdk.models.ConversationContext;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -118,4 +122,26 @@ private void checkGetChannelProfileChannelType(GetChannelProfileRequest client)
client.getChannel(), supportedChannelForGetProfile));
}
}

public IdentityConflictsListResponse listIdentityConflicts(IdentityConflictsListRequest client) {

// guard against null value to start with a default request parameters set
if (null == client) {
client = IdentityConflictsListRequest.builder(null).build();
}

Integer pageSize = client.getPageSize().orElse(null);
String pageToken = client.getPageToken().orElse(null);

ListIdentityConflictsResponse response =
getApi().listIdentityConflicts(uriUUID, pageSize, pageToken);

String nextPageToken = response.getNextPageToken();
List<IdentityConflicts> list = response.getConflicts();
Collection<IdentityConflicts> pageContent = null != list ? list : Collections.emptyList();
Pair<Collection<IdentityConflicts>, TokenPageNavigator> content =
new Pair<>(pageContent, TokenPageNavigator.valueOf(nextPageToken));
return new IdentityConflictsListResponse(
this, new Page<>(client, content.getLeft(), content.getRight()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.OmniMessageOverrideMapper;
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.SendMessageRequestMapper;
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.WhatsAppInteractiveHeaderMapper;
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.kakaotalk.buttons.KakaoTalkButtonMapper;
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.kakaotalk.commerce.KakaoTalkCommerceMapper;
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.kakaotalk.coupons.KakaoTalkCouponMapper;
import com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.whatsapp.payment.OrderDetailsSettingsMapper;
import com.sinch.sdk.domains.conversation.models.v1.messages.ChoiceItemMapper;
import com.sinch.sdk.domains.conversation.models.v1.messages.internal.AppMessageInternalMapper;
import com.sinch.sdk.domains.conversation.models.v1.messages.internal.ChannelSpecificMessageInternalMapper;
Expand Down Expand Up @@ -59,6 +63,7 @@ public class ConversationService
private volatile EventsService events;
private volatile TranscodingService transcoding;
private volatile CapabilityService capability;
private volatile ProjectSettingsService projectSettings;
private volatile WebHooksService webhooks;
private volatile TemplatesService templates;

Expand Down Expand Up @@ -154,6 +159,15 @@ public WebHooksService webhooks() {
return this.webhooks;
}

public ProjectSettingsService projectSettings() {
if (null == this.projectSettings) {
instanceLazyInit();
this.projectSettings =
new ProjectSettingsService(uriUUID, context, httpClientSupplier.get(), authManagers);
}
return this.projectSettings;
}

private void instanceLazyInit() {
if (null != this.authManagers) {
return;
Expand Down Expand Up @@ -214,10 +228,14 @@ private LocalLazyInit() {
ContactMessageMapper.initMapper();
ContactMessageInternalMapper.initMapper();
ConversationMessageMapper.initMapper();
KakaoTalkButtonMapper.initMapper();
KakaoTalkCommerceMapper.initMapper();
KakaoTalkCouponMapper.initMapper();
LineEnterpriseCredentialsMapper.initMapper();
ListMessageInternalMapper.initMapper();
ListSectionMapper.initMapper();
OmniMessageOverrideMapper.initMapper();
OrderDetailsSettingsMapper.initMapper();
RecipientMapper.initMapper();
SendMessageRequestMapper.initMapper();
TemplateMessageMapper.initMapper();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.sinch.sdk.domains.conversation.api.v1.adapters;

import com.sinch.sdk.core.http.AuthManager;
import com.sinch.sdk.core.http.HttpClient;
import com.sinch.sdk.core.http.HttpMapper;
import com.sinch.sdk.domains.conversation.api.v1.internal.ProjectSettingsApi;
import com.sinch.sdk.domains.conversation.models.v1.projectsettings.request.ProjectSettingsRequest;
import com.sinch.sdk.domains.conversation.models.v1.projectsettings.response.ProjectSettingsResponse;
import com.sinch.sdk.models.ConversationContext;
import java.util.Map;

public class ProjectSettingsService
implements com.sinch.sdk.domains.conversation.api.v1.ProjectSettingsService {

private final String uriUUID;
private final ProjectSettingsApi api;

public ProjectSettingsService(
String uriUUID,
ConversationContext context,
HttpClient httpClient,
Map<String, AuthManager> authManagers) {
this.uriUUID = uriUUID;
this.api =
new ProjectSettingsApi(
httpClient, context.getServer(), authManagers, HttpMapper.getInstance());
}

protected ProjectSettingsApi getApi() {
return this.api;
}

@Override
public ProjectSettingsResponse create(ProjectSettingsRequest projectSettingsRequest) {
return getApi().create(uriUUID, projectSettingsRequest);
}

@Override
public void delete() {
getApi().delete(uriUUID);
}

@Override
public ProjectSettingsResponse get() {
return getApi().get(uriUUID);
}

@Override
public ProjectSettingsResponse update(ProjectSettingsRequest projectSettingsRequest) {
return getApi().update(uriUUID, projectSettingsRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.kakaotalk.buttons;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.sinch.sdk.core.utils.databind.Mapper;
import com.sinch.sdk.domains.conversation.models.v1.messages.types.channelspecific.kakaotalk.buttons.KakaoTalkButton;
import com.sinch.sdk.domains.conversation.models.v1.messages.types.channelspecific.kakaotalk.buttons.internal.KakaoTalkButtonInternalImpl;
import java.io.IOException;

public class KakaoTalkButtonMapper {

public static void initMapper() {
Mapper.getInstance()
.registerModule(
new SimpleModule().addDeserializer(KakaoTalkButton.class, new Deserializer()));
}

static class Deserializer extends StdDeserializer<KakaoTalkButton> {

public Deserializer() {
this(null);
}

public Deserializer(Class<KakaoTalkButton> vc) {
super(vc);
}

@Override
public KakaoTalkButton deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {

KakaoTalkButtonInternalImpl deserialized = jp.readValueAs(KakaoTalkButtonInternalImpl.class);

return (KakaoTalkButton) deserialized.getActualInstance();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.kakaotalk.commerce;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.sinch.sdk.core.utils.databind.Mapper;
import com.sinch.sdk.domains.conversation.models.v1.messages.types.channelspecific.kakaotalk.commerce.KakaoTalkCommerce;
import com.sinch.sdk.domains.conversation.models.v1.messages.types.channelspecific.kakaotalk.commerce.internal.KakaoTalkCommerceMessageCommerceImpl;
import java.io.IOException;

public class KakaoTalkCommerceMapper {

public static void initMapper() {
Mapper.getInstance()
.registerModule(
new SimpleModule().addDeserializer(KakaoTalkCommerce.class, new Deserializer()));
}

static class Deserializer extends StdDeserializer<KakaoTalkCommerce> {

public Deserializer() {
this(null);
}

public Deserializer(Class<KakaoTalkCommerce> vc) {
super(vc);
}

@Override
public KakaoTalkCommerce deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {

KakaoTalkCommerceMessageCommerceImpl deserialized =
jp.readValueAs(KakaoTalkCommerceMessageCommerceImpl.class);

return (KakaoTalkCommerce) deserialized.getActualInstance();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.sinch.sdk.domains.conversation.api.v1.adapters.messages.type.channelspecific.kakaotalk.coupons;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.sinch.sdk.core.utils.databind.Mapper;
import com.sinch.sdk.domains.conversation.models.v1.messages.types.channelspecific.kakaotalk.coupons.KakaoTalkCoupon;
import com.sinch.sdk.domains.conversation.models.v1.messages.types.channelspecific.kakaotalk.coupons.internal.KakaoTalkCouponInternalImpl;
import java.io.IOException;

public class KakaoTalkCouponMapper {

public static void initMapper() {
Mapper.getInstance()
.registerModule(
new SimpleModule().addDeserializer(KakaoTalkCoupon.class, new Deserializer()));
}

static class Deserializer extends StdDeserializer<KakaoTalkCoupon> {

public Deserializer() {
this(null);
}

public Deserializer(Class<KakaoTalkCoupon> vc) {
super(vc);
}

@Override
public KakaoTalkCoupon deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {

KakaoTalkCouponInternalImpl deserialized = jp.readValueAs(KakaoTalkCouponInternalImpl.class);

return (KakaoTalkCoupon) deserialized.getActualInstance();
}
}
}
Loading
Loading