diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c032d311..69e5aa20 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.22.0" + ".": "4.23.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index e2794c72..cf69b295 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 134 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-b053468fefe6d757f86f3233ebbc52d80329ed2a6e7a6740fee01e4028a4c3b9.yml -openapi_spec_hash: 416835e693de0fe19945be90a787d3f3 -config_hash: 8d28dbeabe9d4dcc7d5b8c021a4cbbd7 +configured_endpoints: 136 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-47bd7f89519b4aa68b039b9a03888b689fac9d6ee763d26be0b267bbb0b2ddaa.yml +openapi_spec_hash: 67ff63b23cbfb19beac58d6e471836d3 +config_hash: b30c4b3086cd9f3da06a63b256d8c189 diff --git a/CHANGELOG.md b/CHANGELOG.md index 83d3cc41..95ff5e77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## 4.23.0 (2026-07-29) + +Full Changelog: [v4.22.0...v4.23.0](https://github.com/trycourier/courier-java/compare/v4.22.0...v4.23.0) + +### Features + +* Document DELETE/PUT restore for inbox messages (C-19268) ([#175](https://github.com/trycourier/courier-java/issues/175)) ([6a1a54a](https://github.com/trycourier/courier-java/commit/6a1a54a0d6ad45e41c9c99c18e01c315fcae5b58)) +* spec: rename and reorder the API reference sections ([#179](https://github.com/trycourier/courier-java/issues/179)) ([2ce28ee](https://github.com/trycourier/courier-java/commit/2ce28eee967b036c5b725a1146cb8cc2a1a84f02)) + + +### Documentation + +* **openapi:** describe user topic-preference fields explicitly ([#172](https://github.com/trycourier/courier-java/issues/172)) ([1d09244](https://github.com/trycourier/courier-java/commit/1d09244b56cb1ed9c98e28365d7509cd9dbe0018)) +* **openapi:** document Idempotency-Key header on idempotent POST endpoints ([#176](https://github.com/trycourier/courier-java/issues/176)) ([8d254c6](https://github.com/trycourier/courier-java/commit/8d254c610de6563741992db211375fc40d4f33ef)) +* **openapi:** rewrite operation descriptions for agents and SEO ([#174](https://github.com/trycourier/courier-java/issues/174)) ([3453be3](https://github.com/trycourier/courier-java/commit/3453be34b9c9713b88aa72e64c6fdfa3251a2fae)) + ## 4.22.0 (2026-07-23) Full Changelog: [v4.21.0...v4.22.0](https://github.com/trycourier/courier-java/compare/v4.21.0...v4.22.0) diff --git a/build.gradle.kts b/build.gradle.kts index bb83195c..a4f7fe41 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.courier" - version = "4.22.0" // x-release-please-version + version = "4.23.0" // x-release-please-version } subprojects { diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt index 1d5082d7..67b8b24b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt @@ -10,6 +10,7 @@ import com.courier.services.blocking.AutomationService import com.courier.services.blocking.BrandService import com.courier.services.blocking.DigestService import com.courier.services.blocking.InboundService +import com.courier.services.blocking.InboxService import com.courier.services.blocking.JourneyService import com.courier.services.blocking.ListService import com.courier.services.blocking.MessageService @@ -61,42 +62,97 @@ interface CourierClient { */ fun withOptions(modifier: Consumer): CourierClient + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ fun send(): SendService + /** Define filter-based groups whose membership Courier recalculates as user profiles change. */ fun audiences(): AudienceService + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ fun providers(): ProviderService + /** Read the audit trail of configuration and access changes in your workspace. */ fun auditEvents(): AuditEventService + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ fun auth(): AuthService + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun automations(): AutomationService + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ fun journeys(): JourneyService + /** Manage the logos, colors, and layout that give the templates you send a consistent look. */ fun brands(): BrandService fun digests(): DigestService + /** Record an inbound event that triggers the journeys and automations mapped to it. */ fun inbound(): InboundService + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ fun lists(): ListService + fun inbox(): InboxService + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun messages(): MessageService + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun requests(): RequestService + /** Create, update, version, publish, and localize notification templates and their content. */ fun notifications(): NotificationService + /** + * Define reusable channel routing and failover strategies, and see which templates use them. + */ fun routingStrategies(): RoutingStrategyService + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun workspacePreferences(): WorkspacePreferenceService + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ fun profiles(): ProfileService + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun tenants(): TenantService + /** + * Store and retrieve the translation strings Courier uses to render localized template content. + */ fun translations(): TranslationService fun users(): UserService @@ -124,42 +180,105 @@ interface CourierClient { */ fun withOptions(modifier: Consumer): CourierClient.WithRawResponse + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across + * every channel you have configured. + */ fun send(): SendService.WithRawResponse + /** + * Define filter-based groups whose membership Courier recalculates as user profiles change. + */ fun audiences(): AudienceService.WithRawResponse + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ fun providers(): ProviderService.WithRawResponse + /** Read the audit trail of configuration and access changes in your workspace. */ fun auditEvents(): AuditEventService.WithRawResponse + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ fun auth(): AuthService.WithRawResponse + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun automations(): AutomationService.WithRawResponse + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ fun journeys(): JourneyService.WithRawResponse + /** + * Manage the logos, colors, and layout that give the templates you send a consistent look. + */ fun brands(): BrandService.WithRawResponse fun digests(): DigestService.WithRawResponse + /** Record an inbound event that triggers the journeys and automations mapped to it. */ fun inbound(): InboundService.WithRawResponse + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ fun lists(): ListService.WithRawResponse + fun inbox(): InboxService.WithRawResponse + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun messages(): MessageService.WithRawResponse + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun requests(): RequestService.WithRawResponse + /** + * Create, update, version, publish, and localize notification templates and their content. + */ fun notifications(): NotificationService.WithRawResponse + /** + * Define reusable channel routing and failover strategies, and see which templates use + * them. + */ fun routingStrategies(): RoutingStrategyService.WithRawResponse + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun workspacePreferences(): WorkspacePreferenceService.WithRawResponse + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ fun profiles(): ProfileService.WithRawResponse + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun tenants(): TenantService.WithRawResponse + /** + * Store and retrieve the translation strings Courier uses to render localized template + * content. + */ fun translations(): TranslationService.WithRawResponse fun users(): UserService.WithRawResponse diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt index 4ac223e6..059eeeb2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt @@ -10,6 +10,7 @@ import com.courier.services.async.AutomationServiceAsync import com.courier.services.async.BrandServiceAsync import com.courier.services.async.DigestServiceAsync import com.courier.services.async.InboundServiceAsync +import com.courier.services.async.InboxServiceAsync import com.courier.services.async.JourneyServiceAsync import com.courier.services.async.ListServiceAsync import com.courier.services.async.MessageServiceAsync @@ -61,42 +62,97 @@ interface CourierClientAsync { */ fun withOptions(modifier: Consumer): CourierClientAsync + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ fun send(): SendServiceAsync + /** Define filter-based groups whose membership Courier recalculates as user profiles change. */ fun audiences(): AudienceServiceAsync + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ fun providers(): ProviderServiceAsync + /** Read the audit trail of configuration and access changes in your workspace. */ fun auditEvents(): AuditEventServiceAsync + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ fun auth(): AuthServiceAsync + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun automations(): AutomationServiceAsync + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ fun journeys(): JourneyServiceAsync + /** Manage the logos, colors, and layout that give the templates you send a consistent look. */ fun brands(): BrandServiceAsync fun digests(): DigestServiceAsync + /** Record an inbound event that triggers the journeys and automations mapped to it. */ fun inbound(): InboundServiceAsync + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ fun lists(): ListServiceAsync + fun inbox(): InboxServiceAsync + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun messages(): MessageServiceAsync + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun requests(): RequestServiceAsync + /** Create, update, version, publish, and localize notification templates and their content. */ fun notifications(): NotificationServiceAsync + /** + * Define reusable channel routing and failover strategies, and see which templates use them. + */ fun routingStrategies(): RoutingStrategyServiceAsync + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun workspacePreferences(): WorkspacePreferenceServiceAsync + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ fun profiles(): ProfileServiceAsync + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun tenants(): TenantServiceAsync + /** + * Store and retrieve the translation strings Courier uses to render localized template content. + */ fun translations(): TranslationServiceAsync fun users(): UserServiceAsync @@ -128,42 +184,105 @@ interface CourierClientAsync { modifier: Consumer ): CourierClientAsync.WithRawResponse + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across + * every channel you have configured. + */ fun send(): SendServiceAsync.WithRawResponse + /** + * Define filter-based groups whose membership Courier recalculates as user profiles change. + */ fun audiences(): AudienceServiceAsync.WithRawResponse + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ fun providers(): ProviderServiceAsync.WithRawResponse + /** Read the audit trail of configuration and access changes in your workspace. */ fun auditEvents(): AuditEventServiceAsync.WithRawResponse + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ fun auth(): AuthServiceAsync.WithRawResponse + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun automations(): AutomationServiceAsync.WithRawResponse + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ fun journeys(): JourneyServiceAsync.WithRawResponse + /** + * Manage the logos, colors, and layout that give the templates you send a consistent look. + */ fun brands(): BrandServiceAsync.WithRawResponse fun digests(): DigestServiceAsync.WithRawResponse + /** Record an inbound event that triggers the journeys and automations mapped to it. */ fun inbound(): InboundServiceAsync.WithRawResponse + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ fun lists(): ListServiceAsync.WithRawResponse + fun inbox(): InboxServiceAsync.WithRawResponse + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun messages(): MessageServiceAsync.WithRawResponse + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ fun requests(): RequestServiceAsync.WithRawResponse + /** + * Create, update, version, publish, and localize notification templates and their content. + */ fun notifications(): NotificationServiceAsync.WithRawResponse + /** + * Define reusable channel routing and failover strategies, and see which templates use + * them. + */ fun routingStrategies(): RoutingStrategyServiceAsync.WithRawResponse + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun workspacePreferences(): WorkspacePreferenceServiceAsync.WithRawResponse + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ fun profiles(): ProfileServiceAsync.WithRawResponse + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun tenants(): TenantServiceAsync.WithRawResponse + /** + * Store and retrieve the translation strings Courier uses to render localized template + * content. + */ fun translations(): TranslationServiceAsync.WithRawResponse fun users(): UserServiceAsync.WithRawResponse diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt index 9f04092a..5078f394 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt @@ -18,6 +18,8 @@ import com.courier.services.async.DigestServiceAsync import com.courier.services.async.DigestServiceAsyncImpl import com.courier.services.async.InboundServiceAsync import com.courier.services.async.InboundServiceAsyncImpl +import com.courier.services.async.InboxServiceAsync +import com.courier.services.async.InboxServiceAsyncImpl import com.courier.services.async.JourneyServiceAsync import com.courier.services.async.JourneyServiceAsyncImpl import com.courier.services.async.ListServiceAsync @@ -101,6 +103,10 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier private val lists: ListServiceAsync by lazy { ListServiceAsyncImpl(clientOptionsWithUserAgent) } + private val inbox: InboxServiceAsync by lazy { + InboxServiceAsyncImpl(clientOptionsWithUserAgent) + } + private val messages: MessageServiceAsync by lazy { MessageServiceAsyncImpl(clientOptionsWithUserAgent) } @@ -142,42 +148,97 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier override fun withOptions(modifier: Consumer): CourierClientAsync = CourierClientAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ override fun send(): SendServiceAsync = send + /** Define filter-based groups whose membership Courier recalculates as user profiles change. */ override fun audiences(): AudienceServiceAsync = audiences + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ override fun providers(): ProviderServiceAsync = providers + /** Read the audit trail of configuration and access changes in your workspace. */ override fun auditEvents(): AuditEventServiceAsync = auditEvents + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ override fun auth(): AuthServiceAsync = auth + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun automations(): AutomationServiceAsync = automations + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ override fun journeys(): JourneyServiceAsync = journeys + /** Manage the logos, colors, and layout that give the templates you send a consistent look. */ override fun brands(): BrandServiceAsync = brands override fun digests(): DigestServiceAsync = digests + /** Record an inbound event that triggers the journeys and automations mapped to it. */ override fun inbound(): InboundServiceAsync = inbound + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ override fun lists(): ListServiceAsync = lists + override fun inbox(): InboxServiceAsync = inbox + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun messages(): MessageServiceAsync = messages + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun requests(): RequestServiceAsync = requests + /** Create, update, version, publish, and localize notification templates and their content. */ override fun notifications(): NotificationServiceAsync = notifications + /** + * Define reusable channel routing and failover strategies, and see which templates use them. + */ override fun routingStrategies(): RoutingStrategyServiceAsync = routingStrategies + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun workspacePreferences(): WorkspacePreferenceServiceAsync = workspacePreferences + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ override fun profiles(): ProfileServiceAsync = profiles + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun tenants(): TenantServiceAsync = tenants + /** + * Store and retrieve the translation strings Courier uses to render localized template content. + */ override fun translations(): TranslationServiceAsync = translations override fun users(): UserServiceAsync = users @@ -231,6 +292,10 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier ListServiceAsyncImpl.WithRawResponseImpl(clientOptions) } + private val inbox: InboxServiceAsync.WithRawResponse by lazy { + InboxServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + private val messages: MessageServiceAsync.WithRawResponse by lazy { MessageServiceAsyncImpl.WithRawResponseImpl(clientOptions) } @@ -274,44 +339,107 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across + * every channel you have configured. + */ override fun send(): SendServiceAsync.WithRawResponse = send + /** + * Define filter-based groups whose membership Courier recalculates as user profiles change. + */ override fun audiences(): AudienceServiceAsync.WithRawResponse = audiences + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ override fun providers(): ProviderServiceAsync.WithRawResponse = providers + /** Read the audit trail of configuration and access changes in your workspace. */ override fun auditEvents(): AuditEventServiceAsync.WithRawResponse = auditEvents + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ override fun auth(): AuthServiceAsync.WithRawResponse = auth + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun automations(): AutomationServiceAsync.WithRawResponse = automations + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ override fun journeys(): JourneyServiceAsync.WithRawResponse = journeys + /** + * Manage the logos, colors, and layout that give the templates you send a consistent look. + */ override fun brands(): BrandServiceAsync.WithRawResponse = brands override fun digests(): DigestServiceAsync.WithRawResponse = digests + /** Record an inbound event that triggers the journeys and automations mapped to it. */ override fun inbound(): InboundServiceAsync.WithRawResponse = inbound + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ override fun lists(): ListServiceAsync.WithRawResponse = lists + override fun inbox(): InboxServiceAsync.WithRawResponse = inbox + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun messages(): MessageServiceAsync.WithRawResponse = messages + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun requests(): RequestServiceAsync.WithRawResponse = requests + /** + * Create, update, version, publish, and localize notification templates and their content. + */ override fun notifications(): NotificationServiceAsync.WithRawResponse = notifications + /** + * Define reusable channel routing and failover strategies, and see which templates use + * them. + */ override fun routingStrategies(): RoutingStrategyServiceAsync.WithRawResponse = routingStrategies + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun workspacePreferences(): WorkspacePreferenceServiceAsync.WithRawResponse = workspacePreferences + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ override fun profiles(): ProfileServiceAsync.WithRawResponse = profiles + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun tenants(): TenantServiceAsync.WithRawResponse = tenants + /** + * Store and retrieve the translation strings Courier uses to render localized template + * content. + */ override fun translations(): TranslationServiceAsync.WithRawResponse = translations override fun users(): UserServiceAsync.WithRawResponse = users diff --git a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt index d3f901e8..48fcf0b5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt @@ -18,6 +18,8 @@ import com.courier.services.blocking.DigestService import com.courier.services.blocking.DigestServiceImpl import com.courier.services.blocking.InboundService import com.courier.services.blocking.InboundServiceImpl +import com.courier.services.blocking.InboxService +import com.courier.services.blocking.InboxServiceImpl import com.courier.services.blocking.JourneyService import com.courier.services.blocking.JourneyServiceImpl import com.courier.services.blocking.ListService @@ -93,6 +95,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien private val lists: ListService by lazy { ListServiceImpl(clientOptionsWithUserAgent) } + private val inbox: InboxService by lazy { InboxServiceImpl(clientOptionsWithUserAgent) } + private val messages: MessageService by lazy { MessageServiceImpl(clientOptionsWithUserAgent) } private val requests: RequestService by lazy { RequestServiceImpl(clientOptionsWithUserAgent) } @@ -126,42 +130,97 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien override fun withOptions(modifier: Consumer): CourierClient = CourierClientImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ override fun send(): SendService = send + /** Define filter-based groups whose membership Courier recalculates as user profiles change. */ override fun audiences(): AudienceService = audiences + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ override fun providers(): ProviderService = providers + /** Read the audit trail of configuration and access changes in your workspace. */ override fun auditEvents(): AuditEventService = auditEvents + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ override fun auth(): AuthService = auth + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun automations(): AutomationService = automations + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ override fun journeys(): JourneyService = journeys + /** Manage the logos, colors, and layout that give the templates you send a consistent look. */ override fun brands(): BrandService = brands override fun digests(): DigestService = digests + /** Record an inbound event that triggers the journeys and automations mapped to it. */ override fun inbound(): InboundService = inbound + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ override fun lists(): ListService = lists + override fun inbox(): InboxService = inbox + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun messages(): MessageService = messages + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun requests(): RequestService = requests + /** Create, update, version, publish, and localize notification templates and their content. */ override fun notifications(): NotificationService = notifications + /** + * Define reusable channel routing and failover strategies, and see which templates use them. + */ override fun routingStrategies(): RoutingStrategyService = routingStrategies + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun workspacePreferences(): WorkspacePreferenceService = workspacePreferences + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ override fun profiles(): ProfileService = profiles + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun tenants(): TenantService = tenants + /** + * Store and retrieve the translation strings Courier uses to render localized template content. + */ override fun translations(): TranslationService = translations override fun users(): UserService = users @@ -215,6 +274,10 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien ListServiceImpl.WithRawResponseImpl(clientOptions) } + private val inbox: InboxService.WithRawResponse by lazy { + InboxServiceImpl.WithRawResponseImpl(clientOptions) + } + private val messages: MessageService.WithRawResponse by lazy { MessageServiceImpl.WithRawResponseImpl(clientOptions) } @@ -258,43 +321,106 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across + * every channel you have configured. + */ override fun send(): SendService.WithRawResponse = send + /** + * Define filter-based groups whose membership Courier recalculates as user profiles change. + */ override fun audiences(): AudienceService.WithRawResponse = audiences + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ override fun providers(): ProviderService.WithRawResponse = providers + /** Read the audit trail of configuration and access changes in your workspace. */ override fun auditEvents(): AuditEventService.WithRawResponse = auditEvents + /** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ override fun auth(): AuthService.WithRawResponse = auth + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun automations(): AutomationService.WithRawResponse = automations + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ override fun journeys(): JourneyService.WithRawResponse = journeys + /** + * Manage the logos, colors, and layout that give the templates you send a consistent look. + */ override fun brands(): BrandService.WithRawResponse = brands override fun digests(): DigestService.WithRawResponse = digests + /** Record an inbound event that triggers the journeys and automations mapped to it. */ override fun inbound(): InboundService.WithRawResponse = inbound + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ override fun lists(): ListService.WithRawResponse = lists + override fun inbox(): InboxService.WithRawResponse = inbox + + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun messages(): MessageService.WithRawResponse = messages + /** + * Look up the messages Courier has accepted, inspect their delivery history and rendered + * output, and cancel, resend, or archive them. + */ override fun requests(): RequestService.WithRawResponse = requests + /** + * Create, update, version, publish, and localize notification templates and their content. + */ override fun notifications(): NotificationService.WithRawResponse = notifications + /** + * Define reusable channel routing and failover strategies, and see which templates use + * them. + */ override fun routingStrategies(): RoutingStrategyService.WithRawResponse = routingStrategies + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun workspacePreferences(): WorkspacePreferenceService.WithRawResponse = workspacePreferences + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ override fun profiles(): ProfileService.WithRawResponse = profiles + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun tenants(): TenantService.WithRawResponse = tenants + /** + * Store and retrieve the translation strings Courier uses to render localized template + * content. + */ override fun translations(): TranslationService.WithRawResponse = translations override fun users(): UserService.WithRawResponse = users diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceDeleteParams.kt index c5bbd9be..d7ff37d8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceDeleteParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Deletes the specified audience. */ +/** + * Deletes an audience permanently, so update any caller sending to it by audience id first. Those + * sends fail once the audience is gone. + */ class AudienceDeleteParams private constructor( private val audienceId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersParams.kt index a86de265..d2855958 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get list of members of an audience. */ +/** + * Returns the users currently matching an audience filter, with paging. Membership is recalculated, + * so results shift as profiles change. + */ class AudienceListMembersParams private constructor( private val audienceId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListParams.kt index 73165b31..c0703bbd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get the audiences associated with the authorization token. */ +/** + * Returns the audiences in the workspace with paging. Audiences are filter-based groups that + * recalculate as user profiles change. + */ class AudienceListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceRetrieveParams.kt index 5c20adef..7c276ad7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Returns the specified audience by id. */ +/** + * Returns one audience with its name, description, and the filter and AND or OR operator that + * decide which users belong to it. + */ class AudienceRetrieveParams private constructor( private val audienceId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt index 246d1638..76a49fda 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt @@ -21,7 +21,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Creates or updates audience. */ +/** + * Creates or replaces an audience from a filter and an AND or OR operator. Membership recalculates + * automatically as profiles change. + */ class AudienceUpdateParams private constructor( private val audienceId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListParams.kt index ff1f1f54..91aa4bc4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch the list of audit events */ +/** + * Returns the workspace's audit event log with cursor paging. Each event records the actor, target, + * source, type, and timestamp of a change. + */ class AuditEventListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventRetrieveParams.kt index 80eb8427..e6714cd9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch a specific audit event by ID. */ +/** + * Returns one audit event by id, including the actor who performed it, the target they changed, the + * source, the event type, and a timestamp. + */ class AuditEventRetrieveParams private constructor( private val auditEventId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt index b6ae485d..85f00e31 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt @@ -18,7 +18,10 @@ import com.fasterxml.jackson.annotation.JsonProperty import java.util.Collections import java.util.Objects -/** Returns a new access token. */ +/** + * Returns a JWT for authenticating client-side SDKs such as the Inbox. You supply the scope and an + * expires_in duration, both required. + */ class AuthIssueTokenParams private constructor( private val body: Body, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt index a72e9024..8a59e3b4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt @@ -13,7 +13,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get the list of automations. */ +/** + * Lists the workspace's saved automation templates, each with its id and a cursor for paging to the + * next page of results. + */ class AutomationListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt index 22e3716c..ec4b3e33 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt @@ -35,17 +35,21 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Invoke an ad hoc automation run. This endpoint accepts a JSON payload with a series of automation - * steps. For information about what steps are available, checkout the ad hoc automation guide - * [here](https://www.courier.com/docs/automations/steps/). + * Runs a series of automation steps supplied inline, without a saved template, and returns a runId. */ class InvokeInvokeAdHocParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -150,17 +154,38 @@ private constructor( /** A builder for [InvokeInvokeAdHocParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(invokeInvokeAdHocParams: InvokeInvokeAdHocParams) = apply { + idempotencyKey = invokeInvokeAdHocParams.idempotencyKey + xIdempotencyExpiration = invokeInvokeAdHocParams.xIdempotencyExpiration body = invokeInvokeAdHocParams.body.toBuilder() additionalHeaders = invokeInvokeAdHocParams.additionalHeaders.toBuilder() additionalQueryParams = invokeInvokeAdHocParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -383,6 +408,8 @@ private constructor( */ fun build(): InvokeInvokeAdHocParams = InvokeInvokeAdHocParams( + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -391,7 +418,14 @@ private constructor( fun _body(): Body = body - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -5891,13 +5925,22 @@ private constructor( } return other is InvokeInvokeAdHocParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + override fun hashCode(): Int = + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "InvokeInvokeAdHocParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "InvokeInvokeAdHocParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt index 7aa2fcbe..c9102b9f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt @@ -21,10 +21,15 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Invoke an automation run from an automation template. */ +/** + * Starts an automation run from a saved template for one recipient, with optional data and profile, + * and returns a runId. + */ class InvokeInvokeByTemplateParams private constructor( private val templateId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -32,6 +37,10 @@ private constructor( fun templateId(): Optional = Optional.ofNullable(templateId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -124,6 +133,8 @@ private constructor( class Builder internal constructor() { private var templateId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -131,6 +142,8 @@ private constructor( @JvmSynthetic internal fun from(invokeInvokeByTemplateParams: InvokeInvokeByTemplateParams) = apply { templateId = invokeInvokeByTemplateParams.templateId + idempotencyKey = invokeInvokeByTemplateParams.idempotencyKey + xIdempotencyExpiration = invokeInvokeByTemplateParams.xIdempotencyExpiration body = invokeInvokeByTemplateParams.body.toBuilder() additionalHeaders = invokeInvokeByTemplateParams.additionalHeaders.toBuilder() additionalQueryParams = invokeInvokeByTemplateParams.additionalQueryParams.toBuilder() @@ -141,6 +154,23 @@ private constructor( /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -353,6 +383,8 @@ private constructor( fun build(): InvokeInvokeByTemplateParams = InvokeInvokeByTemplateParams( templateId, + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -367,7 +399,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -908,14 +947,23 @@ private constructor( return other is InvokeInvokeByTemplateParams && templateId == other.templateId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(templateId, body, additionalHeaders, additionalQueryParams) + Objects.hash( + templateId, + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "InvokeInvokeByTemplateParams{templateId=$templateId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "InvokeInvokeByTemplateParams{templateId=$templateId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt index f488e2f1..725aef65 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt @@ -21,16 +21,22 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Create a new brand. Requires `name` and `settings` (with at least `colors.primary` and - * `colors.secondary`). + * Creates a brand from a name and settings, including primary and secondary colors. Brands supply + * the logo, colors, and styling that templates render with. */ class BrandCreateParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -110,17 +116,38 @@ private constructor( /** A builder for [BrandCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(brandCreateParams: BrandCreateParams) = apply { + idempotencyKey = brandCreateParams.idempotencyKey + xIdempotencyExpiration = brandCreateParams.xIdempotencyExpiration body = brandCreateParams.body.toBuilder() additionalHeaders = brandCreateParams.additionalHeaders.toBuilder() additionalQueryParams = brandCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -313,6 +340,8 @@ private constructor( */ fun build(): BrandCreateParams = BrandCreateParams( + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -321,7 +350,14 @@ private constructor( fun _body(): Body = body - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -612,13 +648,22 @@ private constructor( } return other is BrandCreateParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + override fun hashCode(): Int = + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "BrandCreateParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "BrandCreateParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandDeleteParams.kt index ef2268cf..b3ceb53f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandDeleteParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Delete a brand by brand ID. */ +/** + * Deletes a brand by id. Reassign any template or tenant that references it before deleting to keep + * their styling intact. + */ class BrandDeleteParams private constructor( private val brandId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListParams.kt index cbf57574..18a518d0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get the list of brands. */ +/** + * Lists the workspace's brands. Every entry carries its name, styling settings, snippets, and + * published version. + */ class BrandListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandRetrieveParams.kt index 71b77c02..7200d97b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch a specific brand by brand ID. */ +/** + * Returns one brand by id, including its colors, logo and styling settings, Handlebars snippets, + * and published version. + */ class BrandRetrieveParams private constructor( private val brandId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt index b4ebfb3d..005fa3d1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt @@ -20,7 +20,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Replace an existing brand with the supplied values. */ +/** + * Replaces a brand with the values you supply, so send the complete settings and snippets rather + * than only the fields you want changed. + */ class BrandUpdateParams private constructor( private val brandId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt index 2cb01798..814431fe 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/digests/schedules/ScheduleListInstancesParams.kt @@ -10,9 +10,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * List the digest instances for a schedule. Each instance represents the events accumulated for a - * single user against the schedule, and can be used to monitor digest accumulation before the - * digest is released. + * Returns the digest instances for a schedule, one per user, with cursor paging. Use it to see what + * has accumulated before a digest releases. */ class ScheduleListInstancesParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt index 52c2c1e4..e32501f8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt @@ -22,7 +22,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Courier Track Event */ +/** + * Records an inbound event that can trigger a journey. Requires an event name, a messageId you + * generate, a type, and a properties object. + */ class InboundTrackEventParams private constructor( private val body: Body, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/inbox/messages/MessageDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/inbox/messages/MessageDeleteParams.kt new file mode 100644 index 00000000..1f4c457a --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/inbox/messages/MessageDeleteParams.kt @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.inbox.messages + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Delete a user's inbox message. The message is removed from every inbox read (it stops appearing + * in the recipient's Inbox); it can be restored. + */ +class MessageDeleteParams +private constructor( + private val messageId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun messageId(): Optional = Optional.ofNullable(messageId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): MessageDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [MessageDeleteParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [MessageDeleteParams]. */ + class Builder internal constructor() { + + private var messageId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(messageDeleteParams: MessageDeleteParams) = apply { + messageId = messageDeleteParams.messageId + additionalHeaders = messageDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = messageDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = messageDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun messageId(messageId: String?) = apply { this.messageId = messageId } + + /** Alias for calling [Builder.messageId] with `messageId.orElse(null)`. */ + fun messageId(messageId: Optional) = messageId(messageId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [MessageDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): MessageDeleteParams = + MessageDeleteParams( + messageId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> messageId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MessageDeleteParams && + messageId == other.messageId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(messageId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "MessageDeleteParams{messageId=$messageId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/inbox/messages/MessageRestoreParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/inbox/messages/MessageRestoreParams.kt new file mode 100644 index 00000000..4b2608d3 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/inbox/messages/MessageRestoreParams.kt @@ -0,0 +1,219 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.inbox.messages + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Restore a previously deleted inbox message. */ +class MessageRestoreParams +private constructor( + private val messageId: String?, + private val body: JsonValue, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun messageId(): Optional = Optional.ofNullable(messageId) + + fun body(): JsonValue = body + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [MessageRestoreParams]. + * + * The following fields are required: + * ```java + * .body() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [MessageRestoreParams]. */ + class Builder internal constructor() { + + private var messageId: String? = null + private var body: JsonValue? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(messageRestoreParams: MessageRestoreParams) = apply { + messageId = messageRestoreParams.messageId + body = messageRestoreParams.body + additionalHeaders = messageRestoreParams.additionalHeaders.toBuilder() + additionalQueryParams = messageRestoreParams.additionalQueryParams.toBuilder() + } + + fun messageId(messageId: String?) = apply { this.messageId = messageId } + + /** Alias for calling [Builder.messageId] with `messageId.orElse(null)`. */ + fun messageId(messageId: Optional) = messageId(messageId.getOrNull()) + + fun body(body: JsonValue) = apply { this.body = body } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [MessageRestoreParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): MessageRestoreParams = + MessageRestoreParams( + messageId, + checkRequired("body", body), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JsonValue = body + + fun _pathParam(index: Int): String = + when (index) { + 0 -> messageId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MessageRestoreParams && + messageId == other.messageId && + body == other.body && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(messageId, body, additionalHeaders, additionalQueryParams) + + override fun toString() = + "MessageRestoreParams{messageId=$messageId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt index ddb3f327..5655bbab 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt @@ -12,8 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Archive a journey. Archived journeys cannot be invoked. Existing journey runs continue to - * completion. + * Archives a journey so it can no longer be invoked. Runs already in flight continue to completion, + * so archiving never strands a user mid-sequence. */ class JourneyArchiveParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCancelParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCancelParams.kt index 558cc4a1..8f9a0eed 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCancelParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCancelParams.kt @@ -7,21 +7,26 @@ import com.courier.core.checkRequired import com.courier.core.http.Headers import com.courier.core.http.QueryParams import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** - * Cancel journey runs. The request body must include EXACTLY ONE of `cancelation_token` (cancels - * every run associated with the token) or `run_id` (cancels a single tenant-scoped run). Supplying - * both or neither returns a `400`. A `run_id` that does not match a run for the tenant returns - * `404`. Cancelation is idempotent: a run that has already finished (`PROCESSED`/`ERROR`) or was - * already `CANCELED` is left unchanged and its current status is returned. + * Cancels in-flight journey runs, either every run sharing a cancelation token or one run by id. + * Use it to stop a sequence when the event resolves. */ class JourneyCancelParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val cancelJourneyRequest: CancelJourneyRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * Request body for `POST /journeys/cancel`. Provide EXACTLY ONE of `cancelation_token` (cancels * every run associated with the token) or `run_id` (cancels a single tenant-scoped run). @@ -52,17 +57,38 @@ private constructor( /** A builder for [JourneyCancelParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var cancelJourneyRequest: CancelJourneyRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(journeyCancelParams: JourneyCancelParams) = apply { + idempotencyKey = journeyCancelParams.idempotencyKey + xIdempotencyExpiration = journeyCancelParams.xIdempotencyExpiration cancelJourneyRequest = journeyCancelParams.cancelJourneyRequest additionalHeaders = journeyCancelParams.additionalHeaders.toBuilder() additionalQueryParams = journeyCancelParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Request body for `POST /journeys/cancel`. Provide EXACTLY ONE of `cancelation_token` * (cancels every run associated with the token) or `run_id` (cancels a single tenant-scoped @@ -197,6 +223,8 @@ private constructor( */ fun build(): JourneyCancelParams = JourneyCancelParams( + idempotencyKey, + xIdempotencyExpiration, checkRequired("cancelJourneyRequest", cancelJourneyRequest), additionalHeaders.build(), additionalQueryParams.build(), @@ -205,7 +233,14 @@ private constructor( fun _body(): CancelJourneyRequest = cancelJourneyRequest - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -215,14 +250,22 @@ private constructor( } return other is JourneyCancelParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && cancelJourneyRequest == other.cancelJourneyRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(cancelJourneyRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + cancelJourneyRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "JourneyCancelParams{cancelJourneyRequest=$cancelJourneyRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "JourneyCancelParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, cancelJourneyRequest=$cancelJourneyRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt index abe3e382..f74e42e2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt @@ -8,21 +8,26 @@ import com.courier.core.checkRequired import com.courier.core.http.Headers import com.courier.core.http.QueryParams import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** - * Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. Send - * nodes are not allowed on `POST`. The standard flow is: create the journey shell here, add - * notification templates with `POST /journeys/{templateId}/templates`, then wire them into the - * journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to publish - * a draft after the fact. + * Creates a journey from a set of nodes, in draft state unless you pass a published state. Send + * nodes cannot be included until their templates exist. */ class JourneyCreateParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val createJourneyRequest: CreateJourneyRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** Request body for creating a journey. */ fun createJourneyRequest(): CreateJourneyRequest = createJourneyRequest @@ -53,17 +58,38 @@ private constructor( /** A builder for [JourneyCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var createJourneyRequest: CreateJourneyRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(journeyCreateParams: JourneyCreateParams) = apply { + idempotencyKey = journeyCreateParams.idempotencyKey + xIdempotencyExpiration = journeyCreateParams.xIdempotencyExpiration createJourneyRequest = journeyCreateParams.createJourneyRequest additionalHeaders = journeyCreateParams.additionalHeaders.toBuilder() additionalQueryParams = journeyCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** Request body for creating a journey. */ fun createJourneyRequest(createJourneyRequest: CreateJourneyRequest) = apply { this.createJourneyRequest = createJourneyRequest @@ -181,6 +207,8 @@ private constructor( */ fun build(): JourneyCreateParams = JourneyCreateParams( + idempotencyKey, + xIdempotencyExpiration, checkRequired("createJourneyRequest", createJourneyRequest), additionalHeaders.build(), additionalQueryParams.build(), @@ -189,7 +217,14 @@ private constructor( fun _body(): CreateJourneyRequest = createJourneyRequest - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -199,14 +234,22 @@ private constructor( } return other is JourneyCreateParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && createJourneyRequest == other.createJourneyRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(createJourneyRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + createJourneyRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "JourneyCreateParams{createJourneyRequest=$createJourneyRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "JourneyCreateParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, createJourneyRequest=$createJourneyRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt index 817b5254..917f7cfc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt @@ -12,12 +12,14 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Invoke a journey by id or alias to start a new run. The response includes a `runId` identifying - * the run. + * Starts a journey run for one user and returns a runId. Runs execute asynchronously, so the + * response arrives before any message is sent. */ class JourneyInvokeParams private constructor( private val templateId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val journeysInvokeRequest: JourneysInvokeRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -25,6 +27,10 @@ private constructor( fun templateId(): Optional = Optional.ofNullable(templateId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * Request body for invoking a journey. Requires either a user identifier or a profile with * contact information. User identifiers can be provided via user_id field, or resolved from @@ -60,6 +66,8 @@ private constructor( class Builder internal constructor() { private var templateId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var journeysInvokeRequest: JourneysInvokeRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -67,6 +75,8 @@ private constructor( @JvmSynthetic internal fun from(journeyInvokeParams: JourneyInvokeParams) = apply { templateId = journeyInvokeParams.templateId + idempotencyKey = journeyInvokeParams.idempotencyKey + xIdempotencyExpiration = journeyInvokeParams.xIdempotencyExpiration journeysInvokeRequest = journeyInvokeParams.journeysInvokeRequest additionalHeaders = journeyInvokeParams.additionalHeaders.toBuilder() additionalQueryParams = journeyInvokeParams.additionalQueryParams.toBuilder() @@ -77,6 +87,23 @@ private constructor( /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Request body for invoking a journey. Requires either a user identifier or a profile with * contact information. User identifiers can be provided via user_id field, or resolved from @@ -199,6 +226,8 @@ private constructor( fun build(): JourneyInvokeParams = JourneyInvokeParams( templateId, + idempotencyKey, + xIdempotencyExpiration, checkRequired("journeysInvokeRequest", journeysInvokeRequest), additionalHeaders.build(), additionalQueryParams.build(), @@ -213,7 +242,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -224,14 +260,23 @@ private constructor( return other is JourneyInvokeParams && templateId == other.templateId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && journeysInvokeRequest == other.journeysInvokeRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(templateId, journeysInvokeRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + templateId, + idempotencyKey, + xIdempotencyExpiration, + journeysInvokeRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "JourneyInvokeParams{templateId=$templateId, journeysInvokeRequest=$journeysInvokeRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "JourneyInvokeParams{templateId=$templateId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, journeysInvokeRequest=$journeysInvokeRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt index 8392863d..7df522f6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt @@ -13,7 +13,9 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get the list of journeys. */ +/** + * Lists the workspace's journeys, each carrying a name, state, and enabled flag. Paged by cursor. + */ class JourneyListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt index 5531ac06..10350f99 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** List published versions of a journey, ordered most recent first. */ +/** + * Lists a journey's published versions, most recent first, so you have a version id to roll back + * to. Paged by cursor. + */ class JourneyListVersionsParams private constructor( private val templateId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt index 8c07fd58..4d08648e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt @@ -12,12 +12,14 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Publish the current draft as a new version. Body is optional; pass `{ "version": "vN" }` to roll - * back to a prior version instead. Returns 404 if the journey has no draft to publish. + * Publishes a journey's current draft as a new version, making it live for new runs. Pass a version + * instead to roll back to an earlier one. */ class JourneyPublishParams private constructor( private val templateId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val journeyPublishRequest: JourneyPublishRequest?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -25,6 +27,10 @@ private constructor( fun templateId(): Optional = Optional.ofNullable(templateId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * Request body for publishing a journey. Pass `version` to roll back to a prior version; omit * to publish the current draft. @@ -55,6 +61,8 @@ private constructor( class Builder internal constructor() { private var templateId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var journeyPublishRequest: JourneyPublishRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -62,6 +70,8 @@ private constructor( @JvmSynthetic internal fun from(journeyPublishParams: JourneyPublishParams) = apply { templateId = journeyPublishParams.templateId + idempotencyKey = journeyPublishParams.idempotencyKey + xIdempotencyExpiration = journeyPublishParams.xIdempotencyExpiration journeyPublishRequest = journeyPublishParams.journeyPublishRequest additionalHeaders = journeyPublishParams.additionalHeaders.toBuilder() additionalQueryParams = journeyPublishParams.additionalQueryParams.toBuilder() @@ -72,6 +82,23 @@ private constructor( /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Request body for publishing a journey. Pass `version` to roll back to a prior version; * omit to publish the current draft. @@ -193,6 +220,8 @@ private constructor( fun build(): JourneyPublishParams = JourneyPublishParams( templateId, + idempotencyKey, + xIdempotencyExpiration, journeyPublishRequest, additionalHeaders.build(), additionalQueryParams.build(), @@ -207,7 +236,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -218,14 +254,23 @@ private constructor( return other is JourneyPublishParams && templateId == other.templateId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && journeyPublishRequest == other.journeyPublishRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(templateId, journeyPublishRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + templateId, + idempotencyKey, + xIdempotencyExpiration, + journeyPublishRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "JourneyPublishParams{templateId=$templateId, journeyPublishRequest=$journeyPublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "JourneyPublishParams{templateId=$templateId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, journeyPublishRequest=$journeyPublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt index 40365c98..15cbc68f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt @@ -12,10 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Replace the journey draft. Updates the working draft only; call `POST - * /journeys/{templateId}/publish` to make it live, or pass `state: "PUBLISHED"` in this request to - * publish immediately. Send-node `template` ids must already exist and be scoped to this journey, - * and node ids must not be claimed by another journey. + * Replaces a journey's working draft, leaving the published version live until you publish. Reach + * for this when editing a journey already running. */ class JourneyReplaceParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt index 0007b837..f10eb8d3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Archive the journey-scoped notification template. Archived templates cannot be sent. */ +/** + * Archives one journey's notification template, preventing further sends. Detach any send node + * referencing it beforehand. + */ class TemplateArchiveParams private constructor( private val templateId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt index ddd6f87d..888cb1cc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt @@ -19,6 +19,8 @@ import kotlin.jvm.optionals.getOrNull class TemplateCreateParams private constructor( private val templateId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val journeyTemplateCreateRequest: JourneyTemplateCreateRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -26,6 +28,10 @@ private constructor( fun templateId(): Optional = Optional.ofNullable(templateId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** Request body for creating a notification template scoped to a journey. */ fun journeyTemplateCreateRequest(): JourneyTemplateCreateRequest = journeyTemplateCreateRequest @@ -57,6 +63,8 @@ private constructor( class Builder internal constructor() { private var templateId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var journeyTemplateCreateRequest: JourneyTemplateCreateRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -64,6 +72,8 @@ private constructor( @JvmSynthetic internal fun from(templateCreateParams: TemplateCreateParams) = apply { templateId = templateCreateParams.templateId + idempotencyKey = templateCreateParams.idempotencyKey + xIdempotencyExpiration = templateCreateParams.xIdempotencyExpiration journeyTemplateCreateRequest = templateCreateParams.journeyTemplateCreateRequest additionalHeaders = templateCreateParams.additionalHeaders.toBuilder() additionalQueryParams = templateCreateParams.additionalQueryParams.toBuilder() @@ -74,6 +84,23 @@ private constructor( /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** Request body for creating a notification template scoped to a journey. */ fun journeyTemplateCreateRequest( journeyTemplateCreateRequest: JourneyTemplateCreateRequest @@ -192,6 +219,8 @@ private constructor( fun build(): TemplateCreateParams = TemplateCreateParams( templateId, + idempotencyKey, + xIdempotencyExpiration, checkRequired("journeyTemplateCreateRequest", journeyTemplateCreateRequest), additionalHeaders.build(), additionalQueryParams.build(), @@ -206,7 +235,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -217,6 +253,8 @@ private constructor( return other is TemplateCreateParams && templateId == other.templateId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && journeyTemplateCreateRequest == other.journeyTemplateCreateRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams @@ -225,11 +263,13 @@ private constructor( override fun hashCode(): Int = Objects.hash( templateId, + idempotencyKey, + xIdempotencyExpiration, journeyTemplateCreateRequest, additionalHeaders, additionalQueryParams, ) override fun toString() = - "TemplateCreateParams{templateId=$templateId, journeyTemplateCreateRequest=$journeyTemplateCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "TemplateCreateParams{templateId=$templateId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, journeyTemplateCreateRequest=$journeyTemplateCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt index ac5fe853..cebe3a52 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt @@ -11,7 +11,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * List published versions of the journey-scoped notification template, ordered most recent first. + * Lists the published versions of a template that belongs to a journey, most recent first. Paged by + * cursor. */ class TemplateListVersionsParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt index 4f47593b..a4bcc7f4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt @@ -14,13 +14,15 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Publish the current draft of the journey-scoped notification template as a new version. - * Optionally roll back to a prior version by passing `{ "version": "vN" }`. + * Publishes a journey-scoped template's draft as a new version. Pass a version instead to roll back + * the template to an earlier publish. */ class TemplatePublishParams private constructor( private val templateId: String, private val notificationId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val journeyTemplatePublishRequest: JourneyTemplatePublishRequest?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -30,6 +32,10 @@ private constructor( fun notificationId(): Optional = Optional.ofNullable(notificationId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * Request body for publishing a journey-scoped notification template. Pass `version` to roll * back to a prior version; omit to publish the current draft. @@ -66,6 +72,8 @@ private constructor( private var templateId: String? = null private var notificationId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var journeyTemplatePublishRequest: JourneyTemplatePublishRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -74,6 +82,8 @@ private constructor( internal fun from(templatePublishParams: TemplatePublishParams) = apply { templateId = templatePublishParams.templateId notificationId = templatePublishParams.notificationId + idempotencyKey = templatePublishParams.idempotencyKey + xIdempotencyExpiration = templatePublishParams.xIdempotencyExpiration journeyTemplatePublishRequest = templatePublishParams.journeyTemplatePublishRequest additionalHeaders = templatePublishParams.additionalHeaders.toBuilder() additionalQueryParams = templatePublishParams.additionalQueryParams.toBuilder() @@ -87,6 +97,23 @@ private constructor( fun notificationId(notificationId: Optional) = notificationId(notificationId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Request body for publishing a journey-scoped notification template. Pass `version` to * roll back to a prior version; omit to publish the current draft. @@ -217,6 +244,8 @@ private constructor( TemplatePublishParams( checkRequired("templateId", templateId), notificationId, + idempotencyKey, + xIdempotencyExpiration, journeyTemplatePublishRequest, additionalHeaders.build(), additionalQueryParams.build(), @@ -233,7 +262,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -245,6 +281,8 @@ private constructor( return other is TemplatePublishParams && templateId == other.templateId && notificationId == other.notificationId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && journeyTemplatePublishRequest == other.journeyTemplatePublishRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams @@ -254,11 +292,13 @@ private constructor( Objects.hash( templateId, notificationId, + idempotencyKey, + xIdempotencyExpiration, journeyTemplatePublishRequest, additionalHeaders, additionalQueryParams, ) override fun toString() = - "TemplatePublishParams{templateId=$templateId, notificationId=$notificationId, journeyTemplatePublishRequest=$journeyTemplatePublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "TemplatePublishParams{templateId=$templateId, notificationId=$notificationId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, journeyTemplatePublishRequest=$journeyTemplatePublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt index 7408ee81..7e180e1b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Replace the journey-scoped notification template draft. */ +/** + * Replaces the draft content of one journey's notification template. Publish it before send nodes + * referencing it render the change. + */ class TemplateReplaceParams private constructor( private val templateId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveContentParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveContentParams.kt index a099436e..ad93b2a9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveContentParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveContentParams.kt @@ -11,10 +11,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Retrieve the elemental content of a journey-scoped notification template. The response contains - * the versioned elements along with their content checksums, which can be used to detect changes - * between versions. Pass `?version=draft` (default `published`) to retrieve the working draft, or - * `?version=vN` for a historical version. + * Returns the Elemental elements and version of a journey-scoped template's content. Compare + * versions to see what changed between publishes. */ class TemplateRetrieveContentParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt index 7292132b..bc1a168e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt @@ -11,8 +11,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Fetch a journey-scoped notification template by id. Pass `?version=draft` (default `published`) - * to retrieve the working draft, or `?version=vN` for a historical version. + * Returns a journey's own notification template with its name, brand, subscription topic, and + * content. Defaults to the published version. */ class TemplateRetrieveParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListDeleteParams.kt index 130926e6..81077730 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListDeleteParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Delete a list by list ID. */ +/** + * Deletes a list, halting sends that target it. A previously deleted list can be brought back with + * the companion restore endpoint. + */ class ListDeleteParams private constructor( private val listId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListParams.kt index 37d0ffe8..280b217c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Returns all of the lists, with the ability to filter based on a pattern. */ +/** + * Returns the workspace's lists, filterable by a pattern to fetch a subset such as every regional + * list. Paged by cursor. + */ class ListListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRestoreParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRestoreParams.kt index 24bc44c5..ed956399 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRestoreParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRestoreParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Restore a previously deleted list. */ +/** + * Restores a previously deleted list along with its subscribers, so a list removed by mistake can + * be brought back rather than rebuilt. + */ class ListRestoreParams private constructor( private val listId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRetrieveParams.kt index 2d4b2185..57ba41b2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Returns a list based on the list ID provided. */ +/** + * Returns one list by id with its name and created and updated timestamps. Fetch its subscribers + * separately with the subscriptions endpoint. + */ class ListRetrieveParams private constructor( private val listId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt index 775c573d..3d67e83b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt @@ -21,7 +21,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Create or replace an existing list with the supplied values. */ +/** + * Creates or replaces a list from a name and preferences. Subscribers are managed through the + * separate subscriptions endpoints. + */ class ListUpdateParams private constructor( private val listId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt index 18b58825..b9e129fa 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt @@ -30,6 +30,8 @@ import kotlin.jvm.optionals.getOrNull class SubscriptionAddParams private constructor( private val listId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -37,6 +39,10 @@ private constructor( fun listId(): Optional = Optional.ofNullable(listId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -77,6 +83,8 @@ private constructor( class Builder internal constructor() { private var listId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -84,6 +92,8 @@ private constructor( @JvmSynthetic internal fun from(subscriptionAddParams: SubscriptionAddParams) = apply { listId = subscriptionAddParams.listId + idempotencyKey = subscriptionAddParams.idempotencyKey + xIdempotencyExpiration = subscriptionAddParams.xIdempotencyExpiration body = subscriptionAddParams.body.toBuilder() additionalHeaders = subscriptionAddParams.additionalHeaders.toBuilder() additionalQueryParams = subscriptionAddParams.additionalQueryParams.toBuilder() @@ -94,6 +104,23 @@ private constructor( /** Alias for calling [Builder.listId] with `listId.orElse(null)`. */ fun listId(listId: Optional) = listId(listId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -259,6 +286,8 @@ private constructor( fun build(): SubscriptionAddParams = SubscriptionAddParams( listId, + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -273,7 +302,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -470,14 +506,23 @@ private constructor( return other is SubscriptionAddParams && listId == other.listId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(listId, body, additionalHeaders, additionalQueryParams) + Objects.hash( + listId, + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "SubscriptionAddParams{listId=$listId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "SubscriptionAddParams{listId=$listId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListParams.kt index ae9de70b..2b1bf571 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get the list's subscriptions. */ +/** + * Returns the users subscribed to a list with paging, each with the preferences recorded for that + * subscription. + */ class SubscriptionListParams private constructor( private val listId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt index 4a3dbd43..d8d35454 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt @@ -22,8 +22,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Subscribe a user to an existing list (note: if the List does not exist, it will be automatically - * created). + * Subscribes one user to a list, creating the list if it does not yet exist. Optional preferences + * apply to this subscription only. */ class SubscriptionSubscribeUserParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionUnsubscribeUserParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionUnsubscribeUserParams.kt index d734eba6..273083f7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionUnsubscribeUserParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionUnsubscribeUserParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Delete a subscription to a list by list ID and user ID. */ +/** + * Removes one user's subscription to a list, addressed by list id and user id. The user's profile + * and other subscriptions are separate resources. + */ class SubscriptionUnsubscribeUserParams private constructor( private val listId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageCancelParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageCancelParams.kt index 0be7d4bf..8ec39cf6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageCancelParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageCancelParams.kt @@ -12,10 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Cancel a message that is currently in the process of being delivered. A well-formatted API call - * to the cancel message API will return either `200` status code for a successful cancellation or - * `409` status code for an unsuccessful cancellation. Both cases will include the actual message - * record in the response body (see details below). + * Cancels a message that is still in the delivery pipeline and returns the message record with its + * resulting canceled or failed status. */ class MessageCancelParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentParams.kt index 7411e191..318bc316 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get message content */ +/** + * Returns the rendered content Courier delivered for a message, broken out per channel, to confirm + * what the recipient received. + */ class MessageContentParams private constructor( private val messageId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryParams.kt index be3b33e0..00f211b0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch the array of events of a message you've previously sent. */ +/** + * Returns the ordered event history for a sent message, one entry per status transition with its + * timestamp. + */ class MessageHistoryParams private constructor( private val messageId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListParams.kt index f256c3d8..11c1c83d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch the statuses of messages you've previously sent. */ +/** + * Returns previously sent messages, most recent first, each carrying its status, recipient, + * channel, and provider. Paged by cursor. + */ class MessageListParams private constructor( private val archived: Boolean?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageResendParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageResendParams.kt index 9b6b037c..61f43ab3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageResendParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageResendParams.kt @@ -12,10 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Resend a previously sent message. The original send request is loaded from storage and a - * brand-new send is enqueued for the same recipient and content, producing a **new** `messageId` — - * the original message is not modified. Throttled by a per-message rate limit; a repeat inside the - * limit window returns `429 Too Many Requests`. + * Resends a previously sent message to the same recipient and content, returning a new messageId. + * The original send request is not modified. */ class MessageResendParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveParams.kt index 302f03f3..0bb8297f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch the status of a message you've previously sent. */ +/** + * Returns a sent message's status, recipient, event, and per-provider delivery detail, with + * timestamps for enqueued, sent, delivered, opened, and clicked. + */ class MessageRetrieveParams private constructor( private val messageId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationArchiveParams.kt index d27b7f60..0e8a1c01 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationArchiveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationArchiveParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Archive a notification template. */ +/** + * Archives a notification template, preventing new sends from referencing it. The template stays + * retrievable for its version history. + */ class NotificationArchiveParams private constructor( private val id: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationCreateParams.kt index 8c1ebbd1..d7a939c6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationCreateParams.kt @@ -8,6 +8,8 @@ import com.courier.core.checkRequired import com.courier.core.http.Headers import com.courier.core.http.QueryParams import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** * Create a notification template. Requires all fields in the notification object. Templates are @@ -15,11 +17,17 @@ import java.util.Objects */ class NotificationCreateParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val notificationTemplateCreateRequest: NotificationTemplateCreateRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** Request body for creating a notification template. */ fun notificationTemplateCreateRequest(): NotificationTemplateCreateRequest = notificationTemplateCreateRequest @@ -51,18 +59,39 @@ private constructor( /** A builder for [NotificationCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var notificationTemplateCreateRequest: NotificationTemplateCreateRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(notificationCreateParams: NotificationCreateParams) = apply { + idempotencyKey = notificationCreateParams.idempotencyKey + xIdempotencyExpiration = notificationCreateParams.xIdempotencyExpiration notificationTemplateCreateRequest = notificationCreateParams.notificationTemplateCreateRequest additionalHeaders = notificationCreateParams.additionalHeaders.toBuilder() additionalQueryParams = notificationCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** Request body for creating a notification template. */ fun notificationTemplateCreateRequest( notificationTemplateCreateRequest: NotificationTemplateCreateRequest @@ -180,6 +209,8 @@ private constructor( */ fun build(): NotificationCreateParams = NotificationCreateParams( + idempotencyKey, + xIdempotencyExpiration, checkRequired( "notificationTemplateCreateRequest", notificationTemplateCreateRequest, @@ -191,7 +222,14 @@ private constructor( fun _body(): NotificationTemplateCreateRequest = notificationTemplateCreateRequest - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -201,14 +239,22 @@ private constructor( } return other is NotificationCreateParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && notificationTemplateCreateRequest == other.notificationTemplateCreateRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(notificationTemplateCreateRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + notificationTemplateCreateRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "NotificationCreateParams{notificationTemplateCreateRequest=$notificationTemplateCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "NotificationCreateParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, notificationTemplateCreateRequest=$notificationTemplateCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationDuplicateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationDuplicateParams.kt index 5352b9d3..d7dc4560 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationDuplicateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationDuplicateParams.kt @@ -12,11 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Duplicate a notification template. Creates a standalone copy within the same workspace and - * environment, with " COPY" appended to the title. The copy clones the source draft's tags, brand, - * subscription topic, routing strategy, channels, and content, and is always created as a - * standalone template (it is not linked to any journey or broadcast, even if the source was). - * Templates that are scoped to a journey or a broadcast cannot be duplicated through this endpoint. + * Copies a notification template within the same workspace and environment, appending " COPY" to + * the title. The copy is standalone and independently editable. */ class NotificationDuplicateParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListParams.kt index 6e86a5b2..c5712925 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** List notification templates in your workspace. */ +/** + * Lists the workspace's notification templates. Each carries a name, tags, brand, routing, and its + * draft or published state. + */ class NotificationListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListVersionsParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListVersionsParams.kt index c0080835..0b59d31d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListVersionsParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListVersionsParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** List versions of a notification template. */ +/** + * Returns a notification template's published versions, most recent first, for comparison or + * rollback. Paged. + */ class NotificationListVersionsParams private constructor( private val id: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPublishParams.kt index 0aa7a978..630f7cab 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPublishParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPublishParams.kt @@ -18,6 +18,8 @@ import kotlin.jvm.optionals.getOrNull class NotificationPublishParams private constructor( private val id: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val notificationTemplatePublishRequest: NotificationTemplatePublishRequest?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -25,6 +27,10 @@ private constructor( fun id(): Optional = Optional.ofNullable(id) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * Optional request body for publishing a notification template. Omit or send an empty object to * publish the current draft. @@ -57,6 +63,8 @@ private constructor( class Builder internal constructor() { private var id: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var notificationTemplatePublishRequest: NotificationTemplatePublishRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -64,6 +72,8 @@ private constructor( @JvmSynthetic internal fun from(notificationPublishParams: NotificationPublishParams) = apply { id = notificationPublishParams.id + idempotencyKey = notificationPublishParams.idempotencyKey + xIdempotencyExpiration = notificationPublishParams.xIdempotencyExpiration notificationTemplatePublishRequest = notificationPublishParams.notificationTemplatePublishRequest additionalHeaders = notificationPublishParams.additionalHeaders.toBuilder() @@ -75,6 +85,23 @@ private constructor( /** Alias for calling [Builder.id] with `id.orElse(null)`. */ fun id(id: Optional) = id(id.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Optional request body for publishing a notification template. Omit or send an empty * object to publish the current draft. @@ -197,6 +224,8 @@ private constructor( fun build(): NotificationPublishParams = NotificationPublishParams( id, + idempotencyKey, + xIdempotencyExpiration, notificationTemplatePublishRequest, additionalHeaders.build(), additionalQueryParams.build(), @@ -212,7 +241,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -223,6 +259,8 @@ private constructor( return other is NotificationPublishParams && id == other.id && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && notificationTemplatePublishRequest == other.notificationTemplatePublishRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams @@ -231,11 +269,13 @@ private constructor( override fun hashCode(): Int = Objects.hash( id, + idempotencyKey, + xIdempotencyExpiration, notificationTemplatePublishRequest, additionalHeaders, additionalQueryParams, ) override fun toString() = - "NotificationPublishParams{id=$id, notificationTemplatePublishRequest=$notificationTemplatePublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "NotificationPublishParams{id=$id, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, notificationTemplatePublishRequest=$notificationTemplatePublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutContentParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutContentParams.kt index 7e5f8702..2521ecf2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutContentParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutContentParams.kt @@ -12,8 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Replace the elemental content of a notification template. Overwrites all elements in the template - * with the provided content. Only supported for V2 (elemental) templates. + * Replaces all Elemental content in a template, overwriting every existing element. Supported for + * V2 templates only, not V1 blocks and channels. */ class NotificationPutContentParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutElementParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutElementParams.kt index 1b247d0d..b6e9e91b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutElementParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutElementParams.kt @@ -12,8 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Update a single element within a notification template. Only supported for V2 (elemental) - * templates. + * Replaces one Elemental element in a template, addressed by its element id. Supported for V2 + * templates only, not V1 blocks and channels. */ class NotificationPutElementParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutLocaleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutLocaleParams.kt index 67978639..c721be33 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutLocaleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationPutLocaleParams.kt @@ -12,8 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Set locale-specific content overrides for a notification template. Each element override must - * reference an existing element by ID. Only supported for V2 (elemental) templates. + * Sets locale-specific content overrides for a template. Each override must reference an element + * that already exists in the default content. */ class NotificationPutLocaleParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationReplaceParams.kt index 3a935803..f0106217 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationReplaceParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Replace a notification template. All fields are required. */ +/** + * Replaces a notification template in full, so send every field rather than only the ones you want + * changed. Publish separately to make it live. + */ class NotificationReplaceParams private constructor( private val id: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentParams.kt index 81d3310c..414a45b0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentParams.kt @@ -10,9 +10,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Retrieve the content of a notification template. The response shape depends on whether the - * template uses V1 (blocks/channels) or V2 (elemental) content. Use the `version` query parameter - * to select draft, published, or a specific historical version. + * Returns a template's content and checksum. V2 templates return Elemental elements, while V1 + * templates return blocks and channels instead. */ class NotificationRetrieveContentParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt index feff5bf4..8a5b2d37 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckDeleteParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Cancel a submission for a notification template. */ +/** + * Cancels a pending template submission, withdrawing it from the approval workflow. The template + * stays in draft and can be resubmitted later. + */ class CheckDeleteParams private constructor( private val id: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt index 4b68d876..d0c2a984 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Retrieve the submission checks for a notification template. */ +/** + * Returns the approval checks recorded for a template submission, each with its pass or fail + * result. + */ class CheckListParams private constructor( private val id: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt index 59bc2067..205c934c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt @@ -23,7 +23,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Replace the submission checks for a notification template. */ +/** + * Replaces the approval checks on a template submission with the complete set supplied in the + * request body. + */ class CheckUpdateParams private constructor( private val id: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt index ef16cfcb..39a0afbf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt @@ -22,12 +22,14 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Merge the supplied values with an existing profile or create a new profile if one doesn't already - * exist. + * Merges the supplied values into a user's profile, creating it if absent and leaving any key you + * omit untouched. Prefer this for everyday writes. */ class ProfileCreateParams private constructor( private val userId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -35,6 +37,10 @@ private constructor( fun userId(): Optional = Optional.ofNullable(userId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -75,6 +81,8 @@ private constructor( class Builder internal constructor() { private var userId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -82,6 +90,8 @@ private constructor( @JvmSynthetic internal fun from(profileCreateParams: ProfileCreateParams) = apply { userId = profileCreateParams.userId + idempotencyKey = profileCreateParams.idempotencyKey + xIdempotencyExpiration = profileCreateParams.xIdempotencyExpiration body = profileCreateParams.body.toBuilder() additionalHeaders = profileCreateParams.additionalHeaders.toBuilder() additionalQueryParams = profileCreateParams.additionalQueryParams.toBuilder() @@ -92,6 +102,23 @@ private constructor( /** Alias for calling [Builder.userId] with `userId.orElse(null)`. */ fun userId(userId: Optional) = userId(userId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -243,6 +270,8 @@ private constructor( fun build(): ProfileCreateParams = ProfileCreateParams( userId, + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -257,7 +286,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -539,14 +575,23 @@ private constructor( return other is ProfileCreateParams && userId == other.userId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(userId, body, additionalHeaders, additionalQueryParams) + Objects.hash( + userId, + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "ProfileCreateParams{userId=$userId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "ProfileCreateParams{userId=$userId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileDeleteParams.kt index 54d1c9bf..12f9c69b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileDeleteParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Deletes the specified user profile. */ +/** + * Deletes a user's profile and stored contact details. List subscriptions and preferences are + * separate resources, so remove those too if required. + */ class ProfileDeleteParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt index 5d6cf5d4..54352e6b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt @@ -22,10 +22,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * When using `PUT`, be sure to include all the key-value pairs required by the recipient's profile. - * Any key-value pairs that exist in the profile but fail to be included in the `PUT` request will - * be removed from the profile. Remember, a `PUT` update is a full replacement of the data. For - * partial updates, use the [Patch](https://www.courier.com/docs/reference/profiles/patch/) request. + * Overwrites a user profile in full, removing any key absent from the request body. Use the patch + * endpoint when changing a single field. */ class ProfileReplaceParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveParams.kt index 7f57bbbc..e73f07ba 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Returns the specified user profile. */ +/** + * Returns a user's stored profile and preferences, including the email address, phone number, and + * push tokens Courier can reach them on. + */ class ProfileRetrieveParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt index 50244a27..3ee742d8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt @@ -22,7 +22,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Update a profile */ +/** + * Applies a JSON Patch to a user profile, adding, removing, or replacing individual fields without + * sending the whole object. + */ class ProfileUpdateParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteParams.kt index af7c820b..7d7890e1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Removes all list subscriptions for given user. */ +/** + * Removes every list subscription for a user at once. Their profile and preferences are untouched, + * so this only affects list-targeted sends. + */ class ListDeleteParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveParams.kt index 3cfcef63..bd246764 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Returns the subscribed lists for a specified user. */ +/** + * Returns the lists a user is subscribed to, with paging. Use it to check what a recipient will + * receive before sending to a list. + */ class ListRetrieveParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt index cc61977f..31da59eb 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt @@ -24,11 +24,14 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Subscribes the given user to one or more lists. If the list does not exist, it will be created. + * Subscribes a user to one or more lists, creating any list that does not yet exist. Optional + * preferences apply to each subscription. */ class ListSubscribeParams private constructor( private val userId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -36,6 +39,10 @@ private constructor( fun userId(): Optional = Optional.ofNullable(userId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -76,6 +83,8 @@ private constructor( class Builder internal constructor() { private var userId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -83,6 +92,8 @@ private constructor( @JvmSynthetic internal fun from(listSubscribeParams: ListSubscribeParams) = apply { userId = listSubscribeParams.userId + idempotencyKey = listSubscribeParams.idempotencyKey + xIdempotencyExpiration = listSubscribeParams.xIdempotencyExpiration body = listSubscribeParams.body.toBuilder() additionalHeaders = listSubscribeParams.additionalHeaders.toBuilder() additionalQueryParams = listSubscribeParams.additionalQueryParams.toBuilder() @@ -93,6 +104,23 @@ private constructor( /** Alias for calling [Builder.userId] with `userId.orElse(null)`. */ fun userId(userId: Optional) = userId(userId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -252,6 +280,8 @@ private constructor( fun build(): ListSubscribeParams = ListSubscribeParams( userId, + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -266,7 +296,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -461,14 +498,23 @@ private constructor( return other is ListSubscribeParams && userId == other.userId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(userId, body, additionalHeaders, additionalQueryParams) + Objects.hash( + userId, + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "ListSubscribeParams{userId=$userId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "ListSubscribeParams{userId=$userId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt index 5ab1a1f3..69b91896 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt @@ -22,16 +22,22 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Create a new provider configuration. The `provider` field must be a known Courier provider key - * (see catalog). + * Configures a provider integration from a Courier provider key and its settings. Check the catalog + * endpoint for the schema each provider expects. */ class ProviderCreateParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * The provider key identifying the type (e.g. "sendgrid", "twilio"). Must be a known Courier * provider — see the catalog endpoint for valid keys. @@ -121,17 +127,38 @@ private constructor( /** A builder for [ProviderCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(providerCreateParams: ProviderCreateParams) = apply { + idempotencyKey = providerCreateParams.idempotencyKey + xIdempotencyExpiration = providerCreateParams.xIdempotencyExpiration body = providerCreateParams.body.toBuilder() additionalHeaders = providerCreateParams.additionalHeaders.toBuilder() additionalQueryParams = providerCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -327,6 +354,8 @@ private constructor( */ fun build(): ProviderCreateParams = ProviderCreateParams( + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -335,7 +364,14 @@ private constructor( fun _body(): Body = body - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -750,13 +786,22 @@ private constructor( } return other is ProviderCreateParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + override fun hashCode(): Int = + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "ProviderCreateParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "ProviderCreateParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderDeleteParams.kt index 3886c0b7..6ba5cbbe 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderDeleteParams.kt @@ -12,8 +12,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Delete a provider configuration. Returns 409 if the provider is still referenced by routing or - * notifications. + * Deletes a provider configuration, which fails while routing strategies or templates still + * reference it. Update those references first. */ class ProviderDeleteParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListParams.kt index 32cbb849..a8f1060d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListParams.kt @@ -10,8 +10,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * List configured provider integrations for the current workspace. Supports cursor-based - * pagination. + * Lists the provider integrations configured in the workspace, one entry per channel and provider + * key with its alias and settings. */ class ProviderListParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderRetrieveParams.kt index ec283b1e..ad806d94 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch a single provider configuration by ID. */ +/** + * Returns one configured provider by id, including its channel, provider key, alias, title, and + * current settings. + */ class ProviderRetrieveParams private constructor( private val id: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt index beb70565..cbb67360 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt @@ -22,10 +22,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Replace an existing provider configuration. The `provider` key is required and determines which - * provider-specific settings schema is applied. All other fields are optional — omitted fields are - * cleared from the stored configuration (this is a full replacement, not a partial merge). Changing - * the provider type for an existing configuration is not supported. + * Replaces a provider's configuration in full, clearing any field you omit rather than merging it. + * Send the complete settings object. */ class ProviderUpdateParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListParams.kt index c0e33e52..bfee2dc2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListParams.kt @@ -10,9 +10,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Returns the catalog of available provider types with their display names, descriptions, and - * configuration schema fields (snake_case, with `type` and `required`). Providers with no - * configurable schema return only `provider`, `name`, and `description`. + * Returns the provider types Courier supports, each with a display name, description, and the + * configuration fields it requires. */ class CatalogListParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/requests/RequestArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/requests/RequestArchiveParams.kt index b02759f8..00143afd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/requests/RequestArchiveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/requests/RequestArchiveParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Archive message */ +/** + * Archives a send request by its request id. Use it to remove test sends or superseded requests + * from the message list without deleting them. + */ class RequestArchiveParams private constructor( private val requestId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParams.kt index 0d9de2c6..14f0c4c9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParams.kt @@ -8,6 +8,8 @@ import com.courier.core.checkRequired import com.courier.core.http.Headers import com.courier.core.http.QueryParams import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** * Create a routing strategy. Requires a name and routing configuration at minimum. Channels and @@ -15,11 +17,17 @@ import java.util.Objects */ class RoutingStrategyCreateParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val routingStrategyCreateRequest: RoutingStrategyCreateRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** Request body for creating a routing strategy. */ fun routingStrategyCreateRequest(): RoutingStrategyCreateRequest = routingStrategyCreateRequest @@ -50,17 +58,38 @@ private constructor( /** A builder for [RoutingStrategyCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var routingStrategyCreateRequest: RoutingStrategyCreateRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(routingStrategyCreateParams: RoutingStrategyCreateParams) = apply { + idempotencyKey = routingStrategyCreateParams.idempotencyKey + xIdempotencyExpiration = routingStrategyCreateParams.xIdempotencyExpiration routingStrategyCreateRequest = routingStrategyCreateParams.routingStrategyCreateRequest additionalHeaders = routingStrategyCreateParams.additionalHeaders.toBuilder() additionalQueryParams = routingStrategyCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** Request body for creating a routing strategy. */ fun routingStrategyCreateRequest( routingStrategyCreateRequest: RoutingStrategyCreateRequest @@ -178,6 +207,8 @@ private constructor( */ fun build(): RoutingStrategyCreateParams = RoutingStrategyCreateParams( + idempotencyKey, + xIdempotencyExpiration, checkRequired("routingStrategyCreateRequest", routingStrategyCreateRequest), additionalHeaders.build(), additionalQueryParams.build(), @@ -186,7 +217,14 @@ private constructor( fun _body(): RoutingStrategyCreateRequest = routingStrategyCreateRequest - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -196,14 +234,22 @@ private constructor( } return other is RoutingStrategyCreateParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && routingStrategyCreateRequest == other.routingStrategyCreateRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(routingStrategyCreateRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + routingStrategyCreateRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "RoutingStrategyCreateParams{routingStrategyCreateRequest=$routingStrategyCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "RoutingStrategyCreateParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, routingStrategyCreateRequest=$routingStrategyCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListNotificationsParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListNotificationsParams.kt index 5832e872..839bb3c5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListNotificationsParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListNotificationsParams.kt @@ -10,8 +10,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * List notification templates associated with a routing strategy. Includes template metadata only, - * not full content. + * Returns the notification templates using a routing strategy, with paging. Check this before + * changing a strategy that templates depend on. */ class RoutingStrategyListNotificationsParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyRetrieveParams.kt index a8ba8e13..62387815 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyRetrieveParams.kt @@ -10,8 +10,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Retrieve a routing strategy by ID. Returns the full entity including routing content and - * metadata. + * Returns one routing strategy by id with its name, tags, channels, and the routing rules that + * decide provider order and fallback. */ class RoutingStrategyRetrieveParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt index 82b300cc..48d788f4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt @@ -50,14 +50,23 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Send a message to one or more recipients. */ +/** + * Sends a message to one or more recipients and returns a requestId. Courier routes it to email, + * SMS, push, chat, or in-app based on your rules. + */ class SendMessageParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * The message property has the following primary top-level properties. They define the * destination and content of the message. @@ -100,17 +109,38 @@ private constructor( /** A builder for [SendMessageParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @JvmSynthetic internal fun from(sendMessageParams: SendMessageParams) = apply { + idempotencyKey = sendMessageParams.idempotencyKey + xIdempotencyExpiration = sendMessageParams.xIdempotencyExpiration body = sendMessageParams.body.toBuilder() additionalHeaders = sendMessageParams.additionalHeaders.toBuilder() additionalQueryParams = sendMessageParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -265,6 +295,8 @@ private constructor( */ fun build(): SendMessageParams = SendMessageParams( + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -273,7 +305,14 @@ private constructor( fun _body(): Body = body - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -4691,13 +4730,22 @@ private constructor( } return other is SendMessageParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } - override fun hashCode(): Int = Objects.hash(body, additionalHeaders, additionalQueryParams) + override fun hashCode(): Int = + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "SendMessageParams{body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "SendMessageParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantDeleteParams.kt index 0ecabed1..ea03b554 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantDeleteParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Delete a Tenant */ +/** + * Deletes a tenant. Its members' workspace-level profiles and preferences live outside the tenant + * and are managed separately. + */ class TenantDeleteParams private constructor( private val tenantId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListParams.kt index 16721c74..c6123a83 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get a List of Tenants */ +/** + * Lists the workspace's tenants, each carrying a name, parent tenant, properties, and default + * preferences. Paged. + */ class TenantListParams private constructor( private val cursor: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersParams.kt index df6831bd..33a818d9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get Users in Tenant */ +/** + * Returns the users belonging to a tenant with cursor paging. Use it to see who a tenant-scoped + * send will reach. + */ class TenantListUsersParams private constructor( private val tenantId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantRetrieveParams.kt index 0c079ff3..2a3af2c2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get a Tenant */ +/** + * Returns one tenant with its name, parent tenant id, default preferences, properties, and the user + * profile applied to its members. + */ class TenantRetrieveParams private constructor( private val tenantId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt index b576d2b1..b926e16d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt @@ -21,7 +21,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Create or Replace a Tenant */ +/** + * Creates or replaces a tenant from a name, parent, brand, properties, and default preferences + * supplied in the request body. + */ class TenantUpdateParams private constructor( private val tenantId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemDeleteParams.kt index 2401f0d6..a07a182f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemDeleteParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Remove Default Preferences For Topic */ +/** + * Removes a tenant's default preference for one subscription topic, addressed by tenant id and + * topic id. + */ class ItemDeleteParams private constructor( private val tenantId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemUpdateParams.kt index c85d7eb2..239a1e8c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/preferences/items/ItemUpdateParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Create or Replace Default Preferences For Topic */ +/** + * Sets a tenant's default opt-in status for one subscription topic, which applies to every member + * unless a user sets their own override. + */ class ItemUpdateParams private constructor( private val tenantId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt index dec1acab..2eaf366a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt @@ -13,12 +13,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Deletes the tenant's notification template with the given `template_id`. - * - * Returns **204 No Content** with an empty body on success. - * - * Returns **404** if there is no template with this ID for the tenant, including a second `DELETE` - * after a successful removal. + * Deletes a tenant's notification template by id. Sends for that tenant then use the workspace + * template registered under the same id. */ class TemplateDeleteParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListParams.kt index 0e14f4b7..1517b6f0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** List Templates in Tenant */ +/** + * Lists a tenant's notification templates, each carrying its version and published timestamp. + * Paged. + */ class TemplateListParams private constructor( private val tenantId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplatePublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplatePublishParams.kt index 2c74d73a..f571d3e0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplatePublishParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplatePublishParams.kt @@ -14,10 +14,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Publishes a specific version of a notification template for a tenant. - * - * The template must already exist in the tenant's notification map. If no version is specified, - * defaults to publishing the "latest" version. + * Publishes a version of a tenant's notification template, making it the content that tenant's + * sends render from until you publish another. */ class TemplatePublishParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateReplaceParams.kt index a787cfc6..29cb9b3a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateReplaceParams.kt @@ -13,12 +13,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Creates or updates a notification template for a tenant. - * - * If the template already exists for the tenant, it will be updated (200). Otherwise, a new - * template is created (201). - * - * Optionally publishes the template immediately if the `published` flag is set to true. + * Creates or updates a notification template scoped to one tenant, letting a tenant override the + * content the workspace template would send. */ class TemplateReplaceParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateRetrieveParams.kt index aef09cc4..c50255dd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateRetrieveParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get a Template in Tenant */ +/** + * Returns a tenant's notification template with its content, version, and created, updated, and + * published timestamps. + */ class TemplateRetrieveParams private constructor( private val tenantId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/versions/VersionRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/versions/VersionRetrieveParams.kt index 194d20d4..5f4d1459 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/versions/VersionRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/versions/VersionRetrieveParams.kt @@ -11,12 +11,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Fetches a specific version of a tenant template. - * - * Supports the following version formats: - * - `latest` - The most recent version of the template - * - `published` - The currently published version - * - `v{version}` - A specific version (e.g., "v1", "v2", "v1.0.0") + * Returns one version of a tenant template, addressed by version number or by latest, with its + * content and publish timestamp. */ class VersionRetrieveParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationRetrieveParams.kt index 3663abce..b72767fa 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationRetrieveParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get translations by locale */ +/** + * Returns the translation strings stored for one domain and locale, for use in localized + * notification content. + */ class TranslationRetrieveParams private constructor( private val domain: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationUpdateParams.kt index 2d302263..4b7f2c60 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/translations/TranslationUpdateParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Update a translation */ +/** + * Uploads the translation strings for one domain and locale. Courier uses them to render localized + * content for recipients in that locale. + */ class TranslationUpdateParams private constructor( private val domain: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkReplaceParams.kt index 6301994f..47d725cd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkReplaceParams.kt @@ -25,21 +25,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Replace a user's complete set of preference overrides in a single request. The topics in the - * request body become the recipient's entire set of overrides: listed topics are created or - * updated, and every existing override that is not included in the body is reset to its topic - * default. Submitting an empty `topics` array is a valid clear-all that resets every existing - * override. - * - * This operation is validation-atomic (all-or-nothing): structural validation fails fast with a - * single `400`, and if any topic is semantically invalid (an unknown topic, a `REQUIRED` topic that - * cannot be opted out, or a custom routing request that is not available on the workspace's plan) - * the request returns a single `400` aggregating every failure in `errors` and writes nothing. On - * success it returns `200` with `items` (the complete resulting override set) and `deleted` (the - * ids of the overrides that were reset to default). - * - * Every `topic_id` in the response — in `items`, `deleted`, and any `errors` — is returned in - * Courier's canonical topic id form, regardless of the form supplied in the request. + * Replaces a user's entire set of preference overrides. Any topic you leave out is reset to its + * default, so send the full set rather than a subset. */ class PreferenceBulkReplaceParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParams.kt index 3f3b17a2..aece4663 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParams.kt @@ -25,24 +25,15 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Additively create or update a user's preferences for one or more subscription topics in a single - * request. Only the topics included in the request body are created or updated; any existing - * overrides for topics not listed are left untouched. - * - * Structural validation of the request body fails fast with a single `400`. Beyond that, each topic - * is processed independently (partial-success, not all-or-nothing): valid topics are written and - * returned in `items`, while topics that cannot be applied are collected in `errors` with a - * per-topic `reason` (for example an unknown topic, a `REQUIRED` topic that cannot be opted out, a - * custom routing request that is not available on the workspace's plan, or a write failure). The - * request therefore returns `200` with both lists whenever the body is structurally valid. - * - * Every `topic_id` in the response — in both `items` and `errors` — is returned in Courier's - * canonical topic id form, regardless of the form supplied in the request. + * Adds or updates a user's preferences for several subscription topics at once. Topics you leave + * out keep whatever they were set to before. */ class PreferenceBulkUpdateParams private constructor( private val userId: String?, private val tenantId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -53,6 +44,10 @@ private constructor( /** Update the preferences of a user for this specific tenant context. */ fun tenantId(): Optional = Optional.ofNullable(tenantId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * The topics to create or update. Between 1 and 50 topics may be provided in a single request. * @@ -96,6 +91,8 @@ private constructor( private var userId: String? = null private var tenantId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var body: Body.Builder = Body.builder() private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -104,6 +101,8 @@ private constructor( internal fun from(preferenceBulkUpdateParams: PreferenceBulkUpdateParams) = apply { userId = preferenceBulkUpdateParams.userId tenantId = preferenceBulkUpdateParams.tenantId + idempotencyKey = preferenceBulkUpdateParams.idempotencyKey + xIdempotencyExpiration = preferenceBulkUpdateParams.xIdempotencyExpiration body = preferenceBulkUpdateParams.body.toBuilder() additionalHeaders = preferenceBulkUpdateParams.additionalHeaders.toBuilder() additionalQueryParams = preferenceBulkUpdateParams.additionalQueryParams.toBuilder() @@ -120,6 +119,23 @@ private constructor( /** Alias for calling [Builder.tenantId] with `tenantId.orElse(null)`. */ fun tenantId(tenantId: Optional) = tenantId(tenantId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Sets the entire request body. * @@ -284,6 +300,8 @@ private constructor( PreferenceBulkUpdateParams( userId, tenantId, + idempotencyKey, + xIdempotencyExpiration, body.build(), additionalHeaders.build(), additionalQueryParams.build(), @@ -298,7 +316,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = QueryParams.builder() @@ -954,14 +979,24 @@ private constructor( return other is PreferenceBulkUpdateParams && userId == other.userId && tenantId == other.tenantId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(userId, tenantId, body, additionalHeaders, additionalQueryParams) + Objects.hash( + userId, + tenantId, + idempotencyKey, + xIdempotencyExpiration, + body, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "PreferenceBulkUpdateParams{userId=$userId, tenantId=$tenantId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "PreferenceBulkUpdateParams{userId=$userId, tenantId=$tenantId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceDeleteTopicParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceDeleteTopicParams.kt index 914d8a82..742317dd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceDeleteTopicParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceDeleteTopicParams.kt @@ -13,9 +13,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Remove a user's preferences for a specific subscription topic, resetting the topic to its - * effective default. This operation is idempotent: deleting a preference that does not exist - * succeeds with no error. + * Removes a user's override for one subscription topic, resetting it to the effective default from + * the tenant or workspace. */ class PreferenceDeleteTopicParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveParams.kt index cbf3e55d..2955ee91 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch all user preferences. */ +/** + * Returns a user's preference overrides with paging, one entry per subscription topic they have set + * a choice for. + */ class PreferenceRetrieveParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicParams.kt index f6151c31..ee4cd95f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Fetch user preferences for a specific subscription topic. */ +/** + * Returns a user's opt-in status and channel choices for one subscription topic, or the effective + * default if they have set no override. + */ class PreferenceRetrieveTopicParams private constructor( private val userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt index 71cdde9e..41607c8c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt @@ -24,7 +24,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Update or Create user preferences for a specific subscription topic. */ +/** + * Sets a user's opt-in status and channel choices for one subscription topic, overriding the tenant + * default for that topic only. + */ class PreferenceUpdateOrCreateTopicParams private constructor( private val userId: String, @@ -479,13 +482,17 @@ private constructor( ) : this(status, customRouting, hasCustomRouting, mutableMapOf()) /** + * The subscription status to set: OPTED_IN or OPTED_OUT. REQUIRED is a topic-level default, + * not a user choice; the API rejects opting a user out of a REQUIRED topic. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ fun status(): PreferenceStatus = status.getRequired("status") /** - * The Channels a user has chosen to receive notifications through for this topic + * The channels to deliver this topic on when has_custom_routing is true. One or more of: + * direct_message, email, push, sms, webhook, inbox. * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -494,6 +501,9 @@ private constructor( customRouting.getOptional("custom_routing") /** + * Set to true to route this topic to the channels in custom_routing instead of the topic's + * default routing. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -568,6 +578,10 @@ private constructor( additionalProperties = topic.additionalProperties.toMutableMap() } + /** + * The subscription status to set: OPTED_IN or OPTED_OUT. REQUIRED is a topic-level + * default, not a user choice; the API rejects opting a user out of a REQUIRED topic. + */ fun status(status: PreferenceStatus) = status(JsonField.of(status)) /** @@ -579,7 +593,10 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } - /** The Channels a user has chosen to receive notifications through for this topic */ + /** + * The channels to deliver this topic on when has_custom_routing is true. One or more + * of: direct_message, email, push, sms, webhook, inbox. + */ fun customRouting(customRouting: List?) = customRouting(JsonField.ofNullable(customRouting)) @@ -610,6 +627,10 @@ private constructor( } } + /** + * Set to true to route this topic to the channels in custom_routing instead of the + * topic's default routing. + */ fun hasCustomRouting(hasCustomRouting: Boolean?) = hasCustomRouting(JsonField.ofNullable(hasCustomRouting)) diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt index e7f6720f..febea8dc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt @@ -60,31 +60,42 @@ private constructor( ) /** + * The topic's default status, returned on reads. It applies whenever the user has no override + * of their own (status equals this value). + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ fun defaultStatus(): PreferenceStatus = defaultStatus.getRequired("default_status") /** + * The user's subscription status for this topic. OPTED_IN or OPTED_OUT reflect the user's own + * choice; REQUIRED is a topic-level default set in the preferences editor, not a user choice. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ fun status(): PreferenceStatus = status.getRequired("status") /** + * The unique identifier of the subscription topic this preference applies to. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ fun topicId(): String = topicId.getRequired("topic_id") /** + * The display name of the subscription topic, returned on reads. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ fun topicName(): String = topicName.getRequired("topic_name") /** - * The Channels a user has chosen to receive notifications through for this topic + * The channels the user has chosen to receive this topic on, present only when + * has_custom_routing is true. One or more of: direct_message, email, push, sms, webhook, inbox. * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -93,6 +104,9 @@ private constructor( customRouting.getOptional("custom_routing") /** + * Whether the user has chosen specific delivery channels for this topic (listed in + * custom_routing) rather than the topic's default routing. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -197,6 +211,10 @@ private constructor( additionalProperties = topicPreference.additionalProperties.toMutableMap() } + /** + * The topic's default status, returned on reads. It applies whenever the user has no + * override of their own (status equals this value). + */ fun defaultStatus(defaultStatus: PreferenceStatus) = defaultStatus(JsonField.of(defaultStatus)) @@ -211,6 +229,11 @@ private constructor( this.defaultStatus = defaultStatus } + /** + * The user's subscription status for this topic. OPTED_IN or OPTED_OUT reflect the user's + * own choice; REQUIRED is a topic-level default set in the preferences editor, not a user + * choice. + */ fun status(status: PreferenceStatus) = status(JsonField.of(status)) /** @@ -222,6 +245,7 @@ private constructor( */ fun status(status: JsonField) = apply { this.status = status } + /** The unique identifier of the subscription topic this preference applies to. */ fun topicId(topicId: String) = topicId(JsonField.of(topicId)) /** @@ -232,6 +256,7 @@ private constructor( */ fun topicId(topicId: JsonField) = apply { this.topicId = topicId } + /** The display name of the subscription topic, returned on reads. */ fun topicName(topicName: String) = topicName(JsonField.of(topicName)) /** @@ -243,7 +268,11 @@ private constructor( */ fun topicName(topicName: JsonField) = apply { this.topicName = topicName } - /** The Channels a user has chosen to receive notifications through for this topic */ + /** + * The channels the user has chosen to receive this topic on, present only when + * has_custom_routing is true. One or more of: direct_message, email, push, sms, webhook, + * inbox. + */ fun customRouting(customRouting: List?) = customRouting(JsonField.ofNullable(customRouting)) @@ -274,6 +303,10 @@ private constructor( } } + /** + * Whether the user has chosen specific delivery channels for this topic (listed in + * custom_routing) rather than the topic's default routing. + */ fun hasCustomRouting(hasCustomRouting: Boolean?) = hasCustomRouting(JsonField.ofNullable(hasCustomRouting)) diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt index d8f89fd3..01ca7b76 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt @@ -24,9 +24,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * This endpoint is used to add a user to multiple tenants in one call. A custom profile can also be - * supplied for each tenant. This profile will be merged with the user's main profile when sending - * to the user with that tenant. + * Adds a user to several tenants in one call, each optionally with a per-tenant profile that + * overrides their workspace profile. */ class TenantAddMultipleParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt index 9b70b75a..e4356b5f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt @@ -22,10 +22,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * This endpoint is used to add a single tenant. - * - * A custom profile can also be supplied with the tenant. This profile will be merged with the - * user's main profile when sending to the user with that tenant. + * Adds a user to one tenant, optionally with a tenant-specific profile that overrides their + * workspace profile for sends in that tenant. */ class TenantAddSingleParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListParams.kt index e802934b..6d545c4d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Returns a paginated list of user tenant associations. */ +/** + * Returns the tenants a user belongs to, with cursor paging. A user can belong to many tenants, + * each with its own profile and preferences. + */ class TenantListParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveAllParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveAllParams.kt index 8d03fca0..87b6bd4e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveAllParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveAllParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Removes a user from any tenants they may have been associated with. */ +/** + * Removes a user from every tenant they belong to in one call. Their workspace-level profile is a + * separate resource. + */ class TenantRemoveAllParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveSingleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveSingleParams.kt index 6dd013cd..e06ef5f5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveSingleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantRemoveSingleParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Removes a user from the supplied tenant. */ +/** + * Removes a user from one tenant. Their other tenant memberships and workspace profile are managed + * through separate endpoints. + */ class TenantRemoveSingleParams private constructor( private val userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddMultipleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddMultipleParams.kt index 246c6d21..9554ca2e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddMultipleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddMultipleParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Adds multiple tokens to a user and overwrites matching existing tokens. */ +/** + * Registers several device tokens for a user in one call, overwriting any stored token with a + * matching value. + */ class TokenAddMultipleParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt index bec9977e..62fb2e2d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt @@ -32,7 +32,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Adds a single token to a user and overwrites a matching existing token. */ +/** + * Registers one device token for a user against a provider key, overwriting the token if it already + * exists. Push sends resolve tokens per user. + */ class TokenAddSingleParams private constructor( private val userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenDeleteParams.kt index 37772af8..439c4fc7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenDeleteParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenDeleteParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Delete User Token */ +/** + * Deletes one device token for a user, addressed by the token value, so push sends no longer target + * that device. + */ class TokenDeleteParams private constructor( private val userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListParams.kt index db7e379e..6898741e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Gets all tokens available for a :user_id */ +/** + * Returns every device token registered for a user, each with its provider key, status, and expiry + * date. + */ class TokenListParams private constructor( private val userId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveParams.kt index 9c36e828..1d7f0687 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveParams.kt @@ -10,7 +10,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Get single token available for a `:token` */ +/** + * Returns one device token with its provider key, status and status reason, expiry date, and any + * properties stored alongside it. + */ class TokenRetrieveParams private constructor( private val userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt index b1425c5c..e8c749cf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt @@ -22,7 +22,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Apply a JSON Patch (RFC 6902) to the specified token. */ +/** + * Applies a JSON Patch to a device token, changing its status, expiry, or properties without + * re-registering it. + */ class TokenUpdateParams private constructor( private val userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParams.kt index 307c5947..4afb3340 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParams.kt @@ -8,18 +8,26 @@ import com.courier.core.checkRequired import com.courier.core.http.Headers import com.courier.core.http.QueryParams import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull /** - * Create a workspace preference. The workspace preference id is generated and returned. Topics are - * created inside a workspace preference via POST /preferences/sections/{section_id}/topics. + * Creates a workspace preference and returns its generated id. Add subscription topics to it + * afterwards with the topics endpoint. */ class WorkspacePreferenceCreateParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val workspacePreferenceCreateRequest: WorkspacePreferenceCreateRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** Request body for creating a workspace preference. */ fun workspacePreferenceCreateRequest(): WorkspacePreferenceCreateRequest = workspacePreferenceCreateRequest @@ -52,6 +60,8 @@ private constructor( /** A builder for [WorkspacePreferenceCreateParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var workspacePreferenceCreateRequest: WorkspacePreferenceCreateRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -59,6 +69,8 @@ private constructor( @JvmSynthetic internal fun from(workspacePreferenceCreateParams: WorkspacePreferenceCreateParams) = apply { + idempotencyKey = workspacePreferenceCreateParams.idempotencyKey + xIdempotencyExpiration = workspacePreferenceCreateParams.xIdempotencyExpiration workspacePreferenceCreateRequest = workspacePreferenceCreateParams.workspacePreferenceCreateRequest additionalHeaders = workspacePreferenceCreateParams.additionalHeaders.toBuilder() @@ -66,6 +78,23 @@ private constructor( workspacePreferenceCreateParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** Request body for creating a workspace preference. */ fun workspacePreferenceCreateRequest( workspacePreferenceCreateRequest: WorkspacePreferenceCreateRequest @@ -183,6 +212,8 @@ private constructor( */ fun build(): WorkspacePreferenceCreateParams = WorkspacePreferenceCreateParams( + idempotencyKey, + xIdempotencyExpiration, checkRequired("workspacePreferenceCreateRequest", workspacePreferenceCreateRequest), additionalHeaders.build(), additionalQueryParams.build(), @@ -191,7 +222,14 @@ private constructor( fun _body(): WorkspacePreferenceCreateRequest = workspacePreferenceCreateRequest - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -201,14 +239,22 @@ private constructor( } return other is WorkspacePreferenceCreateParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && workspacePreferenceCreateRequest == other.workspacePreferenceCreateRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(workspacePreferenceCreateRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + workspacePreferenceCreateRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "WorkspacePreferenceCreateParams{workspacePreferenceCreateRequest=$workspacePreferenceCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "WorkspacePreferenceCreateParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, workspacePreferenceCreateRequest=$workspacePreferenceCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceListParams.kt index df73392c..ba787dfa 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceListParams.kt @@ -8,8 +8,8 @@ import com.courier.core.http.QueryParams import java.util.Objects /** - * List the workspace's preferences. Each workspace preference embeds its topics. Scoped to the - * workspace of the API key. + * Returns the workspace's preferences, each embedding its subscription topics, routing options, and + * whether custom routing is allowed. */ class WorkspacePreferenceListParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParams.kt index 813d4925..0b9ff524 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParams.kt @@ -12,17 +12,22 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Publish the workspace's preferences page. Takes a snapshot of every workspace preference with its - * topics under a new published version, making the current state visible on the hosted preferences - * page (non-draft). + * Publishes the workspace preference page, snapshotting every preference and topic, and returns the + * page id and a preview URL. */ class WorkspacePreferencePublishParams private constructor( + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val publishPreferencesRequest: PublishPreferencesRequest?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** * Optional page metadata to apply when publishing the workspace's preferences page. All fields * are optional; omitted fields fall back to the page defaults (and the workspace default @@ -56,6 +61,8 @@ private constructor( /** A builder for [WorkspacePreferencePublishParams]. */ class Builder internal constructor() { + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var publishPreferencesRequest: PublishPreferencesRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -63,6 +70,8 @@ private constructor( @JvmSynthetic internal fun from(workspacePreferencePublishParams: WorkspacePreferencePublishParams) = apply { + idempotencyKey = workspacePreferencePublishParams.idempotencyKey + xIdempotencyExpiration = workspacePreferencePublishParams.xIdempotencyExpiration publishPreferencesRequest = workspacePreferencePublishParams.publishPreferencesRequest additionalHeaders = workspacePreferencePublishParams.additionalHeaders.toBuilder() @@ -70,6 +79,23 @@ private constructor( workspacePreferencePublishParams.additionalQueryParams.toBuilder() } + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** * Optional page metadata to apply when publishing the workspace's preferences page. All * fields are optional; omitted fields fall back to the page defaults (and the workspace @@ -193,6 +219,8 @@ private constructor( */ fun build(): WorkspacePreferencePublishParams = WorkspacePreferencePublishParams( + idempotencyKey, + xIdempotencyExpiration, publishPreferencesRequest, additionalHeaders.build(), additionalQueryParams.build(), @@ -202,7 +230,14 @@ private constructor( fun _body(): Optional = Optional.ofNullable(publishPreferencesRequest) - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -212,14 +247,22 @@ private constructor( } return other is WorkspacePreferencePublishParams && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && publishPreferencesRequest == other.publishPreferencesRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams } override fun hashCode(): Int = - Objects.hash(publishPreferencesRequest, additionalHeaders, additionalQueryParams) + Objects.hash( + idempotencyKey, + xIdempotencyExpiration, + publishPreferencesRequest, + additionalHeaders, + additionalQueryParams, + ) override fun toString() = - "WorkspacePreferencePublishParams{publishPreferencesRequest=$publishPreferencesRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "WorkspacePreferencePublishParams{idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, publishPreferencesRequest=$publishPreferencesRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceRetrieveParams.kt index bd38e278..a91f62e2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceRetrieveParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Retrieve a workspace preference by id, including its topics. */ +/** + * Returns one workspace preference by id, including its subscription topics, routing options, and + * custom routing flag. + */ class WorkspacePreferenceRetrieveParams private constructor( private val sectionId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicArchiveParams.kt index b63d6d10..7268aa62 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicArchiveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicArchiveParams.kt @@ -12,7 +12,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Archive a topic and remove it from its workspace preference. Same 404 rules as GET. */ +/** + * Archives a subscription topic and removes it from its workspace preference, addressed by section + * id and topic id. + */ class TopicArchiveParams private constructor( private val sectionId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParams.kt index aa4e0616..3dcd60f6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParams.kt @@ -13,12 +13,14 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Create a subscription preference topic inside a workspace preference. Fails with 404 if the - * workspace preference does not exist. The topic id is generated and returned. + * Creates a subscription topic inside a workspace preference. The default status sets whether users + * start opted in, opted out, or required. */ class TopicCreateParams private constructor( private val sectionId: String?, + private val idempotencyKey: String?, + private val xIdempotencyExpiration: String?, private val workspacePreferenceTopicCreateRequest: WorkspacePreferenceTopicCreateRequest, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, @@ -26,6 +28,10 @@ private constructor( fun sectionId(): Optional = Optional.ofNullable(sectionId) + fun idempotencyKey(): Optional = Optional.ofNullable(idempotencyKey) + + fun xIdempotencyExpiration(): Optional = Optional.ofNullable(xIdempotencyExpiration) + /** Request body for creating a preference topic. */ fun workspacePreferenceTopicCreateRequest(): WorkspacePreferenceTopicCreateRequest = workspacePreferenceTopicCreateRequest @@ -58,6 +64,8 @@ private constructor( class Builder internal constructor() { private var sectionId: String? = null + private var idempotencyKey: String? = null + private var xIdempotencyExpiration: String? = null private var workspacePreferenceTopicCreateRequest: WorkspacePreferenceTopicCreateRequest? = null private var additionalHeaders: Headers.Builder = Headers.builder() @@ -66,6 +74,8 @@ private constructor( @JvmSynthetic internal fun from(topicCreateParams: TopicCreateParams) = apply { sectionId = topicCreateParams.sectionId + idempotencyKey = topicCreateParams.idempotencyKey + xIdempotencyExpiration = topicCreateParams.xIdempotencyExpiration workspacePreferenceTopicCreateRequest = topicCreateParams.workspacePreferenceTopicCreateRequest additionalHeaders = topicCreateParams.additionalHeaders.toBuilder() @@ -77,6 +87,23 @@ private constructor( /** Alias for calling [Builder.sectionId] with `sectionId.orElse(null)`. */ fun sectionId(sectionId: Optional) = sectionId(sectionId.getOrNull()) + fun idempotencyKey(idempotencyKey: String?) = apply { this.idempotencyKey = idempotencyKey } + + /** Alias for calling [Builder.idempotencyKey] with `idempotencyKey.orElse(null)`. */ + fun idempotencyKey(idempotencyKey: Optional) = + idempotencyKey(idempotencyKey.getOrNull()) + + fun xIdempotencyExpiration(xIdempotencyExpiration: String?) = apply { + this.xIdempotencyExpiration = xIdempotencyExpiration + } + + /** + * Alias for calling [Builder.xIdempotencyExpiration] with + * `xIdempotencyExpiration.orElse(null)`. + */ + fun xIdempotencyExpiration(xIdempotencyExpiration: Optional) = + xIdempotencyExpiration(xIdempotencyExpiration.getOrNull()) + /** Request body for creating a preference topic. */ fun workspacePreferenceTopicCreateRequest( workspacePreferenceTopicCreateRequest: WorkspacePreferenceTopicCreateRequest @@ -197,6 +224,8 @@ private constructor( fun build(): TopicCreateParams = TopicCreateParams( sectionId, + idempotencyKey, + xIdempotencyExpiration, checkRequired( "workspacePreferenceTopicCreateRequest", workspacePreferenceTopicCreateRequest, @@ -214,7 +243,14 @@ private constructor( else -> "" } - override fun _headers(): Headers = additionalHeaders + override fun _headers(): Headers = + Headers.builder() + .apply { + idempotencyKey?.let { put("Idempotency-Key", it) } + xIdempotencyExpiration?.let { put("x-idempotency-expiration", it) } + putAll(additionalHeaders) + } + .build() override fun _queryParams(): QueryParams = additionalQueryParams @@ -225,6 +261,8 @@ private constructor( return other is TopicCreateParams && sectionId == other.sectionId && + idempotencyKey == other.idempotencyKey && + xIdempotencyExpiration == other.xIdempotencyExpiration && workspacePreferenceTopicCreateRequest == other.workspacePreferenceTopicCreateRequest && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams @@ -233,11 +271,13 @@ private constructor( override fun hashCode(): Int = Objects.hash( sectionId, + idempotencyKey, + xIdempotencyExpiration, workspacePreferenceTopicCreateRequest, additionalHeaders, additionalQueryParams, ) override fun toString() = - "TopicCreateParams{sectionId=$sectionId, workspacePreferenceTopicCreateRequest=$workspacePreferenceTopicCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "TopicCreateParams{sectionId=$sectionId, idempotencyKey=$idempotencyKey, xIdempotencyExpiration=$xIdempotencyExpiration, workspacePreferenceTopicCreateRequest=$workspacePreferenceTopicCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicListParams.kt index 1a22b576..e1916e81 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicListParams.kt @@ -9,7 +9,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** List the topics in a workspace preference. */ +/** + * Returns the subscription topics inside a workspace preference, each with its default status and + * routing options. + */ class TopicListParams private constructor( private val sectionId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicRetrieveParams.kt index a7d341df..2cda0964 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicRetrieveParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/workspacepreferences/topics/TopicRetrieveParams.kt @@ -11,8 +11,8 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Retrieve a topic within a workspace preference. Returns 404 if the workspace preference does not - * exist, the topic does not exist, or the topic belongs to a different workspace preference. + * Returns one subscription topic with its default status, routing options, allowed preferences, and + * unsubscribe header setting. */ class TopicRetrieveParams private constructor( diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsync.kt index 8495e45b..5c55fbd9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsync.kt @@ -18,6 +18,7 @@ import com.courier.models.audiences.AudienceUpdateResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Define filter-based groups whose membership Courier recalculates as user profiles change. */ interface AudienceServiceAsync { /** @@ -32,7 +33,10 @@ interface AudienceServiceAsync { */ fun withOptions(modifier: Consumer): AudienceServiceAsync - /** Returns the specified audience by id. */ + /** + * Returns one audience with its name, description, and the filter and AND or OR operator that + * decide which users belong to it. + */ fun retrieve(audienceId: String): CompletableFuture = retrieve(audienceId, AudienceRetrieveParams.none()) @@ -64,7 +68,10 @@ interface AudienceServiceAsync { fun retrieve(audienceId: String, requestOptions: RequestOptions): CompletableFuture = retrieve(audienceId, AudienceRetrieveParams.none(), requestOptions) - /** Creates or updates audience. */ + /** + * Creates or replaces an audience from a filter and an AND or OR operator. Membership + * recalculates automatically as profiles change. + */ fun update(audienceId: String): CompletableFuture = update(audienceId, AudienceUpdateParams.none()) @@ -99,7 +106,10 @@ interface AudienceServiceAsync { ): CompletableFuture = update(audienceId, AudienceUpdateParams.none(), requestOptions) - /** Get the audiences associated with the authorization token. */ + /** + * Returns the audiences in the workspace with paging. Audiences are filter-based groups that + * recalculate as user profiles change. + */ fun list(): CompletableFuture = list(AudienceListParams.none()) /** @see list */ @@ -117,7 +127,10 @@ interface AudienceServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(AudienceListParams.none(), requestOptions) - /** Deletes the specified audience. */ + /** + * Deletes an audience permanently, so update any caller sending to it by audience id first. + * Those sends fail once the audience is gone. + */ fun delete(audienceId: String): CompletableFuture = delete(audienceId, AudienceDeleteParams.none()) @@ -149,7 +162,10 @@ interface AudienceServiceAsync { fun delete(audienceId: String, requestOptions: RequestOptions): CompletableFuture = delete(audienceId, AudienceDeleteParams.none(), requestOptions) - /** Get list of members of an audience. */ + /** + * Returns the users currently matching an audience filter, with paging. Membership is + * recalculated, so results shift as profiles change. + */ fun listMembers(audienceId: String): CompletableFuture = listMembers(audienceId, AudienceListMembersParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsyncImpl.kt index f4ba083c..03842ef8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AudienceServiceAsyncImpl.kt @@ -30,6 +30,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Define filter-based groups whose membership Courier recalculates as user profiles change. */ class AudienceServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : AudienceServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsync.kt index 6591ccde..58d4cfda 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsync.kt @@ -12,6 +12,7 @@ import com.courier.models.auditevents.AuditEventRetrieveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Read the audit trail of configuration and access changes in your workspace. */ interface AuditEventServiceAsync { /** @@ -26,7 +27,10 @@ interface AuditEventServiceAsync { */ fun withOptions(modifier: Consumer): AuditEventServiceAsync - /** Fetch a specific audit event by ID. */ + /** + * Returns one audit event by id, including the actor who performed it, the target they changed, + * the source, the event type, and a timestamp. + */ fun retrieve(auditEventId: String): CompletableFuture = retrieve(auditEventId, AuditEventRetrieveParams.none()) @@ -61,7 +65,10 @@ interface AuditEventServiceAsync { ): CompletableFuture = retrieve(auditEventId, AuditEventRetrieveParams.none(), requestOptions) - /** Fetch the list of audit events */ + /** + * Returns the workspace's audit event log with cursor paging. Each event records the actor, + * target, source, type, and timestamp of a change. + */ fun list(): CompletableFuture = list(AuditEventListParams.none()) /** @see list */ diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsyncImpl.kt index d2462f2d..970a3995 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AuditEventServiceAsyncImpl.kt @@ -23,6 +23,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Read the audit trail of configuration and access changes in your workspace. */ class AuditEventServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : AuditEventServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsync.kt index 989b0dbd..707b0389 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsync.kt @@ -10,6 +10,11 @@ import com.courier.models.auth.AuthIssueTokenResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ interface AuthServiceAsync { /** @@ -24,7 +29,10 @@ interface AuthServiceAsync { */ fun withOptions(modifier: Consumer): AuthServiceAsync - /** Returns a new access token. */ + /** + * Returns a JWT for authenticating client-side SDKs such as the Inbox. You supply the scope and + * an expires_in duration, both required. + */ fun issueToken(params: AuthIssueTokenParams): CompletableFuture = issueToken(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsyncImpl.kt index dba0b6fc..4cf15b99 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AuthServiceAsyncImpl.kt @@ -20,6 +20,11 @@ import com.courier.models.auth.AuthIssueTokenResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ class AuthServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : AuthServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsync.kt index ba0eef9d..815b235b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsync.kt @@ -11,6 +11,7 @@ import com.courier.services.async.automations.InvokeServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ interface AutomationServiceAsync { /** @@ -25,9 +26,13 @@ interface AutomationServiceAsync { */ fun withOptions(modifier: Consumer): AutomationServiceAsync + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun invoke(): InvokeServiceAsync - /** Get the list of automations. */ + /** + * Lists the workspace's saved automation templates, each with its id and a cursor for paging to + * the next page of results. + */ fun list(): CompletableFuture = list(AutomationListParams.none()) @@ -61,6 +66,7 @@ interface AutomationServiceAsync { modifier: Consumer ): AutomationServiceAsync.WithRawResponse + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun invoke(): InvokeServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsyncImpl.kt index 504929ea..fe176621 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/AutomationServiceAsyncImpl.kt @@ -21,6 +21,7 @@ import com.courier.services.async.automations.InvokeServiceAsyncImpl import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ class AutomationServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : AutomationServiceAsync { @@ -35,6 +36,7 @@ class AutomationServiceAsyncImpl internal constructor(private val clientOptions: override fun withOptions(modifier: Consumer): AutomationServiceAsync = AutomationServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun invoke(): InvokeServiceAsync = invoke override fun list( @@ -61,6 +63,7 @@ class AutomationServiceAsyncImpl internal constructor(private val clientOptions: clientOptions.toBuilder().apply(modifier::accept).build() ) + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun invoke(): InvokeServiceAsync.WithRawResponse = invoke private val listHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsync.kt index 049c1b6b..1bea4ce3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsync.kt @@ -16,6 +16,7 @@ import com.courier.models.brands.BrandUpdateParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Manage the logos, colors, and layout that give the templates you send a consistent look. */ interface BrandServiceAsync { /** @@ -31,8 +32,8 @@ interface BrandServiceAsync { fun withOptions(modifier: Consumer): BrandServiceAsync /** - * Create a new brand. Requires `name` and `settings` (with at least `colors.primary` and - * `colors.secondary`). + * Creates a brand from a name and settings, including primary and secondary colors. Brands + * supply the logo, colors, and styling that templates render with. */ fun create(params: BrandCreateParams): CompletableFuture = create(params, RequestOptions.none()) @@ -43,7 +44,10 @@ interface BrandServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Fetch a specific brand by brand ID. */ + /** + * Returns one brand by id, including its colors, logo and styling settings, Handlebars + * snippets, and published version. + */ fun retrieve(brandId: String): CompletableFuture = retrieve(brandId, BrandRetrieveParams.none()) @@ -75,7 +79,10 @@ interface BrandServiceAsync { fun retrieve(brandId: String, requestOptions: RequestOptions): CompletableFuture = retrieve(brandId, BrandRetrieveParams.none(), requestOptions) - /** Replace an existing brand with the supplied values. */ + /** + * Replaces a brand with the values you supply, so send the complete settings and snippets + * rather than only the fields you want changed. + */ fun update(brandId: String, params: BrandUpdateParams): CompletableFuture = update(brandId, params, RequestOptions.none()) @@ -97,7 +104,10 @@ interface BrandServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Get the list of brands. */ + /** + * Lists the workspace's brands. Every entry carries its name, styling settings, snippets, and + * published version. + */ fun list(): CompletableFuture = list(BrandListParams.none()) /** @see list */ @@ -115,7 +125,10 @@ interface BrandServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(BrandListParams.none(), requestOptions) - /** Delete a brand by brand ID. */ + /** + * Deletes a brand by id. Reassign any template or tenant that references it before deleting to + * keep their styling intact. + */ fun delete(brandId: String): CompletableFuture = delete(brandId, BrandDeleteParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsyncImpl.kt index 514ba1fe..042d2cf9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/BrandServiceAsyncImpl.kt @@ -28,6 +28,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Manage the logos, colors, and layout that give the templates you send a consistent look. */ class BrandServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : BrandServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt index afe0cc5d..1031a8ca 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsync.kt @@ -20,6 +20,10 @@ interface DigestServiceAsync { */ fun withOptions(modifier: Consumer): DigestServiceAsync + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ fun schedules(): ScheduleServiceAsync /** @@ -36,6 +40,10 @@ interface DigestServiceAsync { modifier: Consumer ): DigestServiceAsync.WithRawResponse + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ fun schedules(): ScheduleServiceAsync.WithRawResponse } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt index aa271ff8..120bd857 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/DigestServiceAsyncImpl.kt @@ -21,6 +21,10 @@ class DigestServiceAsyncImpl internal constructor(private val clientOptions: Cli override fun withOptions(modifier: Consumer): DigestServiceAsync = DigestServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ override fun schedules(): ScheduleServiceAsync = schedules class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -37,6 +41,10 @@ class DigestServiceAsyncImpl internal constructor(private val clientOptions: Cli clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ override fun schedules(): ScheduleServiceAsync.WithRawResponse = schedules } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsync.kt index 40ff5e0a..2e1e285d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsync.kt @@ -10,6 +10,7 @@ import com.courier.models.inbound.InboundTrackEventResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Record an inbound event that triggers the journeys and automations mapped to it. */ interface InboundServiceAsync { /** @@ -24,7 +25,10 @@ interface InboundServiceAsync { */ fun withOptions(modifier: Consumer): InboundServiceAsync - /** Courier Track Event */ + /** + * Records an inbound event that can trigger a journey. Requires an event name, a messageId you + * generate, a type, and a properties object. + */ fun trackEvent(params: InboundTrackEventParams): CompletableFuture = trackEvent(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsyncImpl.kt index 9ea3a97a..285bfac6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/InboundServiceAsyncImpl.kt @@ -20,6 +20,7 @@ import com.courier.models.inbound.InboundTrackEventResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Record an inbound event that triggers the journeys and automations mapped to it. */ class InboundServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : InboundServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/InboxServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/InboxServiceAsync.kt new file mode 100644 index 00000000..27305955 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/InboxServiceAsync.kt @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async + +import com.courier.core.ClientOptions +import com.courier.services.async.inbox.MessageServiceAsync +import java.util.function.Consumer + +interface InboxServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): InboxServiceAsync + + /** Manage the messages in a user's in-app inbox. */ + fun messages(): MessageServiceAsync + + /** A view of [InboxServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): InboxServiceAsync.WithRawResponse + + /** Manage the messages in a user's in-app inbox. */ + fun messages(): MessageServiceAsync.WithRawResponse + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/InboxServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/InboxServiceAsyncImpl.kt new file mode 100644 index 00000000..0ad14fab --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/InboxServiceAsyncImpl.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async + +import com.courier.core.ClientOptions +import com.courier.services.async.inbox.MessageServiceAsync +import com.courier.services.async.inbox.MessageServiceAsyncImpl +import java.util.function.Consumer + +class InboxServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + InboxServiceAsync { + + private val withRawResponse: InboxServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val messages: MessageServiceAsync by lazy { MessageServiceAsyncImpl(clientOptions) } + + override fun withRawResponse(): InboxServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): InboxServiceAsync = + InboxServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + /** Manage the messages in a user's in-app inbox. */ + override fun messages(): MessageServiceAsync = messages + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + InboxServiceAsync.WithRawResponse { + + private val messages: MessageServiceAsync.WithRawResponse by lazy { + MessageServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: Consumer + ): InboxServiceAsync.WithRawResponse = + InboxServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + /** Manage the messages in a user's in-app inbox. */ + override fun messages(): MessageServiceAsync.WithRawResponse = messages + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt index ca96cdd8..a4710fac 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt @@ -26,6 +26,10 @@ import com.courier.services.async.journeys.TemplateServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ interface JourneyServiceAsync { /** @@ -40,14 +44,15 @@ interface JourneyServiceAsync { */ fun withOptions(modifier: Consumer): JourneyServiceAsync + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ fun templates(): TemplateServiceAsync /** - * Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. - * Send nodes are not allowed on `POST`. The standard flow is: create the journey shell here, - * add notification templates with `POST /journeys/{templateId}/templates`, then wire them into - * the journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to - * publish a draft after the fact. + * Creates a journey from a set of nodes, in draft state unless you pass a published state. Send + * nodes cannot be included until their templates exist. */ fun create(params: JourneyCreateParams): CompletableFuture = create(params, RequestOptions.none()) @@ -110,7 +115,10 @@ interface JourneyServiceAsync { ): CompletableFuture = retrieve(templateId, JourneyRetrieveParams.none(), requestOptions) - /** Get the list of journeys. */ + /** + * Lists the workspace's journeys, each carrying a name, state, and enabled flag. Paged by + * cursor. + */ fun list(): CompletableFuture = list(JourneyListParams.none()) /** @see list */ @@ -129,8 +137,8 @@ interface JourneyServiceAsync { list(JourneyListParams.none(), requestOptions) /** - * Archive a journey. Archived journeys cannot be invoked. Existing journey runs continue to - * completion. + * Archives a journey so it can no longer be invoked. Runs already in flight continue to + * completion, so archiving never strands a user mid-sequence. */ fun archive(templateId: String): CompletableFuture = archive(templateId, JourneyArchiveParams.none()) @@ -164,12 +172,8 @@ interface JourneyServiceAsync { archive(templateId, JourneyArchiveParams.none(), requestOptions) /** - * Cancel journey runs. The request body must include EXACTLY ONE of `cancelation_token` - * (cancels every run associated with the token) or `run_id` (cancels a single tenant-scoped - * run). Supplying both or neither returns a `400`. A `run_id` that does not match a run for the - * tenant returns `404`. Cancelation is idempotent: a run that has already finished - * (`PROCESSED`/`ERROR`) or was already `CANCELED` is left unchanged and its current status is - * returned. + * Cancels in-flight journey runs, either every run sharing a cancelation token or one run by + * id. Use it to stop a sequence when the event resolves. */ fun cancel(params: JourneyCancelParams): CompletableFuture = cancel(params, RequestOptions.none()) @@ -220,8 +224,8 @@ interface JourneyServiceAsync { cancel(byRunId, RequestOptions.none()) /** - * Invoke a journey by id or alias to start a new run. The response includes a `runId` - * identifying the run. + * Starts a journey run for one user and returns a runId. Runs execute asynchronously, so the + * response arrives before any message is sent. */ fun invoke( templateId: String, @@ -246,7 +250,10 @@ interface JourneyServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** List published versions of a journey, ordered most recent first. */ + /** + * Lists a journey's published versions, most recent first, so you have a version id to roll + * back to. Paged by cursor. + */ fun listVersions(templateId: String): CompletableFuture = listVersions(templateId, JourneyListVersionsParams.none()) @@ -284,8 +291,8 @@ interface JourneyServiceAsync { listVersions(templateId, JourneyListVersionsParams.none(), requestOptions) /** - * Publish the current draft as a new version. Body is optional; pass `{ "version": "vN" }` to - * roll back to a prior version instead. Returns 404 if the journey has no draft to publish. + * Publishes a journey's current draft as a new version, making it live for new runs. Pass a + * version instead to roll back to an earlier one. */ fun publish(templateId: String): CompletableFuture = publish(templateId, JourneyPublishParams.none()) @@ -322,10 +329,8 @@ interface JourneyServiceAsync { publish(templateId, JourneyPublishParams.none(), requestOptions) /** - * Replace the journey draft. Updates the working draft only; call `POST - * /journeys/{templateId}/publish` to make it live, or pass `state: "PUBLISHED"` in this request - * to publish immediately. Send-node `template` ids must already exist and be scoped to this - * journey, and node ids must not be claimed by another journey. + * Replaces a journey's working draft, leaving the published version live until you publish. + * Reach for this when editing a journey already running. */ fun replace( templateId: String, @@ -364,6 +369,10 @@ interface JourneyServiceAsync { modifier: Consumer ): JourneyServiceAsync.WithRawResponse + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ fun templates(): TemplateServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt index 2873bfc5..2df9bdf8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt @@ -37,6 +37,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : JourneyServiceAsync { @@ -51,6 +55,10 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl override fun withOptions(modifier: Consumer): JourneyServiceAsync = JourneyServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ override fun templates(): TemplateServiceAsync = templates override fun create( @@ -133,6 +141,10 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ override fun templates(): TemplateServiceAsync.WithRawResponse = templates private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsync.kt index 816071a3..49e46902 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsync.kt @@ -17,6 +17,10 @@ import com.courier.services.async.lists.SubscriptionServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ interface ListServiceAsync { /** @@ -31,9 +35,16 @@ interface ListServiceAsync { */ fun withOptions(modifier: Consumer): ListServiceAsync + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ fun subscriptions(): SubscriptionServiceAsync - /** Returns a list based on the list ID provided. */ + /** + * Returns one list by id with its name and created and updated timestamps. Fetch its + * subscribers separately with the subscriptions endpoint. + */ fun retrieve(listId: String): CompletableFuture = retrieve(listId, ListRetrieveParams.none()) @@ -68,7 +79,10 @@ interface ListServiceAsync { ): CompletableFuture = retrieve(listId, ListRetrieveParams.none(), requestOptions) - /** Create or replace an existing list with the supplied values. */ + /** + * Creates or replaces a list from a name and preferences. Subscribers are managed through the + * separate subscriptions endpoints. + */ fun update(listId: String, params: ListUpdateParams): CompletableFuture = update(listId, params, RequestOptions.none()) @@ -89,7 +103,10 @@ interface ListServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Returns all of the lists, with the ability to filter based on a pattern. */ + /** + * Returns the workspace's lists, filterable by a pattern to fetch a subset such as every + * regional list. Paged by cursor. + */ fun list(): CompletableFuture = list(ListListParams.none()) /** @see list */ @@ -106,7 +123,10 @@ interface ListServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(ListListParams.none(), requestOptions) - /** Delete a list by list ID. */ + /** + * Deletes a list, halting sends that target it. A previously deleted list can be brought back + * with the companion restore endpoint. + */ fun delete(listId: String): CompletableFuture = delete(listId, ListDeleteParams.none()) /** @see delete */ @@ -136,7 +156,10 @@ interface ListServiceAsync { fun delete(listId: String, requestOptions: RequestOptions): CompletableFuture = delete(listId, ListDeleteParams.none(), requestOptions) - /** Restore a previously deleted list. */ + /** + * Restores a previously deleted list along with its subscribers, so a list removed by mistake + * can be brought back rather than rebuilt. + */ fun restore(listId: String, params: ListRestoreParams): CompletableFuture = restore(listId, params, RequestOptions.none()) @@ -167,6 +190,10 @@ interface ListServiceAsync { */ fun withOptions(modifier: Consumer): ListServiceAsync.WithRawResponse + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ fun subscriptions(): SubscriptionServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsyncImpl.kt index aef50a4a..64ec8797 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/ListServiceAsyncImpl.kt @@ -30,6 +30,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ class ListServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : ListServiceAsync { @@ -46,6 +50,10 @@ class ListServiceAsyncImpl internal constructor(private val clientOptions: Clien override fun withOptions(modifier: Consumer): ListServiceAsync = ListServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ override fun subscriptions(): SubscriptionServiceAsync = subscriptions override fun retrieve( @@ -100,6 +108,10 @@ class ListServiceAsyncImpl internal constructor(private val clientOptions: Clien clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ override fun subscriptions(): SubscriptionServiceAsync.WithRawResponse = subscriptions private val retrieveHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsync.kt index cb502b47..9a160bee 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsync.kt @@ -20,6 +20,10 @@ import com.courier.models.messages.MessageRetrieveResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ interface MessageServiceAsync { /** @@ -34,7 +38,10 @@ interface MessageServiceAsync { */ fun withOptions(modifier: Consumer): MessageServiceAsync - /** Fetch the status of a message you've previously sent. */ + /** + * Returns a sent message's status, recipient, event, and per-provider delivery detail, with + * timestamps for enqueued, sent, delivered, opened, and clicked. + */ fun retrieve(messageId: String): CompletableFuture = retrieve(messageId, MessageRetrieveParams.none()) @@ -70,7 +77,10 @@ interface MessageServiceAsync { ): CompletableFuture = retrieve(messageId, MessageRetrieveParams.none(), requestOptions) - /** Fetch the statuses of messages you've previously sent. */ + /** + * Returns previously sent messages, most recent first, each carrying its status, recipient, + * channel, and provider. Paged by cursor. + */ fun list(): CompletableFuture = list(MessageListParams.none()) /** @see list */ @@ -89,10 +99,8 @@ interface MessageServiceAsync { list(MessageListParams.none(), requestOptions) /** - * Cancel a message that is currently in the process of being delivered. A well-formatted API - * call to the cancel message API will return either `200` status code for a successful - * cancellation or `409` status code for an unsuccessful cancellation. Both cases will include - * the actual message record in the response body (see details below). + * Cancels a message that is still in the delivery pipeline and returns the message record with + * its resulting canceled or failed status. */ fun cancel(messageId: String): CompletableFuture = cancel(messageId, MessageCancelParams.none()) @@ -128,7 +136,10 @@ interface MessageServiceAsync { ): CompletableFuture = cancel(messageId, MessageCancelParams.none(), requestOptions) - /** Get message content */ + /** + * Returns the rendered content Courier delivered for a message, broken out per channel, to + * confirm what the recipient received. + */ fun content(messageId: String): CompletableFuture = content(messageId, MessageContentParams.none()) @@ -163,7 +174,10 @@ interface MessageServiceAsync { ): CompletableFuture = content(messageId, MessageContentParams.none(), requestOptions) - /** Fetch the array of events of a message you've previously sent. */ + /** + * Returns the ordered event history for a sent message, one entry per status transition with + * its timestamp. + */ fun history(messageId: String): CompletableFuture = history(messageId, MessageHistoryParams.none()) @@ -199,10 +213,8 @@ interface MessageServiceAsync { history(messageId, MessageHistoryParams.none(), requestOptions) /** - * Resend a previously sent message. The original send request is loaded from storage and a - * brand-new send is enqueued for the same recipient and content, producing a **new** - * `messageId` — the original message is not modified. Throttled by a per-message rate limit; a - * repeat inside the limit window returns `429 Too Many Requests`. + * Resends a previously sent message to the same recipient and content, returning a new + * messageId. The original send request is not modified. */ fun resend(messageId: String): CompletableFuture = resend(messageId, MessageResendParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsyncImpl.kt index a102fcd2..7bfb630c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/MessageServiceAsyncImpl.kt @@ -32,6 +32,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ class MessageServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : MessageServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt index 795006ee..f8b2d4d1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsync.kt @@ -28,6 +28,7 @@ import com.courier.services.async.notifications.CheckServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Create, update, version, publish, and localize notification templates and their content. */ interface NotificationServiceAsync { /** @@ -42,6 +43,7 @@ interface NotificationServiceAsync { */ fun withOptions(modifier: Consumer): NotificationServiceAsync + /** Create, update, version, publish, and localize notification templates and their content. */ fun checks(): CheckServiceAsync /** @@ -114,7 +116,10 @@ interface NotificationServiceAsync { ): CompletableFuture = retrieve(id, NotificationRetrieveParams.none(), requestOptions) - /** List notification templates in your workspace. */ + /** + * Lists the workspace's notification templates. Each carries a name, tags, brand, routing, and + * its draft or published state. + */ fun list(): CompletableFuture = list(NotificationListParams.none()) /** @see list */ @@ -132,7 +137,10 @@ interface NotificationServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(NotificationListParams.none(), requestOptions) - /** Archive a notification template. */ + /** + * Archives a notification template, preventing new sends from referencing it. The template + * stays retrievable for its version history. + */ fun archive(id: String): CompletableFuture = archive(id, NotificationArchiveParams.none()) @@ -164,12 +172,8 @@ interface NotificationServiceAsync { archive(id, NotificationArchiveParams.none(), requestOptions) /** - * Duplicate a notification template. Creates a standalone copy within the same workspace and - * environment, with " COPY" appended to the title. The copy clones the source draft's tags, - * brand, subscription topic, routing strategy, channels, and content, and is always created as - * a standalone template (it is not linked to any journey or broadcast, even if the source was). - * Templates that are scoped to a journey or a broadcast cannot be duplicated through this - * endpoint. + * Copies a notification template within the same workspace and environment, appending " COPY" + * to the title. The copy is standalone and independently editable. */ fun duplicate(id: String): CompletableFuture = duplicate(id, NotificationDuplicateParams.none()) @@ -207,7 +211,10 @@ interface NotificationServiceAsync { ): CompletableFuture = duplicate(id, NotificationDuplicateParams.none(), requestOptions) - /** List versions of a notification template. */ + /** + * Returns a notification template's published versions, most recent first, for comparison or + * rollback. Paged. + */ fun listVersions(id: String): CompletableFuture = listVersions(id, NotificationListVersionsParams.none()) @@ -280,8 +287,8 @@ interface NotificationServiceAsync { publish(id, NotificationPublishParams.none(), requestOptions) /** - * Replace the elemental content of a notification template. Overwrites all elements in the - * template with the provided content. Only supported for V2 (elemental) templates. + * Replaces all Elemental content in a template, overwriting every existing element. Supported + * for V2 templates only, not V1 blocks and channels. */ fun putContent( id: String, @@ -310,8 +317,8 @@ interface NotificationServiceAsync { ): CompletableFuture /** - * Update a single element within a notification template. Only supported for V2 (elemental) - * templates. + * Replaces one Elemental element in a template, addressed by its element id. Supported for V2 + * templates only, not V1 blocks and channels. */ fun putElement( elementId: String, @@ -340,8 +347,8 @@ interface NotificationServiceAsync { ): CompletableFuture /** - * Set locale-specific content overrides for a notification template. Each element override must - * reference an existing element by ID. Only supported for V2 (elemental) templates. + * Sets locale-specific content overrides for a template. Each override must reference an + * element that already exists in the default content. */ fun putLocale( localeId: String, @@ -369,7 +376,10 @@ interface NotificationServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Replace a notification template. All fields are required. */ + /** + * Replaces a notification template in full, so send every field rather than only the ones you + * want changed. Publish separately to make it live. + */ fun replace( id: String, params: NotificationReplaceParams, @@ -395,9 +405,8 @@ interface NotificationServiceAsync { ): CompletableFuture /** - * Retrieve the content of a notification template. The response shape depends on whether the - * template uses V1 (blocks/channels) or V2 (elemental) content. Use the `version` query - * parameter to select draft, published, or a specific historical version. + * Returns a template's content and checksum. V2 templates return Elemental elements, while V1 + * templates return blocks and channels instead. */ fun retrieveContent(id: String): CompletableFuture = retrieveContent(id, NotificationRetrieveContentParams.none()) @@ -451,6 +460,9 @@ interface NotificationServiceAsync { modifier: Consumer ): NotificationServiceAsync.WithRawResponse + /** + * Create, update, version, publish, and localize notification templates and their content. + */ fun checks(): CheckServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt index b0f46fb9..615e243a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/NotificationServiceAsyncImpl.kt @@ -40,6 +40,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Create, update, version, publish, and localize notification templates and their content. */ class NotificationServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : NotificationServiceAsync { @@ -54,6 +55,7 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption override fun withOptions(modifier: Consumer): NotificationServiceAsync = NotificationServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** Create, update, version, publish, and localize notification templates and their content. */ override fun checks(): CheckServiceAsync = checks override fun create( @@ -157,6 +159,9 @@ class NotificationServiceAsyncImpl internal constructor(private val clientOption clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Create, update, version, publish, and localize notification templates and their content. + */ override fun checks(): CheckServiceAsync.WithRawResponse = checks private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsync.kt index dfc3ed15..87b4dc82 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsync.kt @@ -18,6 +18,10 @@ import com.courier.services.async.profiles.ListServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ interface ProfileServiceAsync { /** @@ -32,11 +36,15 @@ interface ProfileServiceAsync { */ fun withOptions(modifier: Consumer): ProfileServiceAsync + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ fun lists(): ListServiceAsync /** - * Merge the supplied values with an existing profile or create a new profile if one doesn't - * already exist. + * Merges the supplied values into a user's profile, creating it if absent and leaving any key + * you omit untouched. Prefer this for everyday writes. */ fun create( userId: String, @@ -61,7 +69,10 @@ interface ProfileServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Returns the specified user profile. */ + /** + * Returns a user's stored profile and preferences, including the email address, phone number, + * and push tokens Courier can reach them on. + */ fun retrieve(userId: String): CompletableFuture = retrieve(userId, ProfileRetrieveParams.none()) @@ -96,7 +107,10 @@ interface ProfileServiceAsync { ): CompletableFuture = retrieve(userId, ProfileRetrieveParams.none(), requestOptions) - /** Update a profile */ + /** + * Applies a JSON Patch to a user profile, adding, removing, or replacing individual fields + * without sending the whole object. + */ fun update(userId: String, params: ProfileUpdateParams): CompletableFuture = update(userId, params, RequestOptions.none()) @@ -117,7 +131,10 @@ interface ProfileServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Deletes the specified user profile. */ + /** + * Deletes a user's profile and stored contact details. List subscriptions and preferences are + * separate resources, so remove those too if required. + */ fun delete(userId: String): CompletableFuture = delete(userId, ProfileDeleteParams.none()) @@ -149,11 +166,8 @@ interface ProfileServiceAsync { delete(userId, ProfileDeleteParams.none(), requestOptions) /** - * When using `PUT`, be sure to include all the key-value pairs required by the recipient's - * profile. Any key-value pairs that exist in the profile but fail to be included in the `PUT` - * request will be removed from the profile. Remember, a `PUT` update is a full replacement of - * the data. For partial updates, use the - * [Patch](https://www.courier.com/docs/reference/profiles/patch/) request. + * Overwrites a user profile in full, removing any key absent from the request body. Use the + * patch endpoint when changing a single field. */ fun replace( userId: String, @@ -192,6 +206,10 @@ interface ProfileServiceAsync { modifier: Consumer ): ProfileServiceAsync.WithRawResponse + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ fun lists(): ListServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsyncImpl.kt index c8f736ae..12bcb01c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/ProfileServiceAsyncImpl.kt @@ -31,6 +31,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ class ProfileServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : ProfileServiceAsync { @@ -45,6 +49,10 @@ class ProfileServiceAsyncImpl internal constructor(private val clientOptions: Cl override fun withOptions(modifier: Consumer): ProfileServiceAsync = ProfileServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ override fun lists(): ListServiceAsync = lists override fun create( @@ -99,6 +107,10 @@ class ProfileServiceAsyncImpl internal constructor(private val clientOptions: Cl clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ override fun lists(): ListServiceAsync.WithRawResponse = lists private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsync.kt index de000978..d687fe7f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsync.kt @@ -17,6 +17,10 @@ import com.courier.services.async.providers.CatalogServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ interface ProviderServiceAsync { /** @@ -31,11 +35,15 @@ interface ProviderServiceAsync { */ fun withOptions(modifier: Consumer): ProviderServiceAsync + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ fun catalog(): CatalogServiceAsync /** - * Create a new provider configuration. The `provider` field must be a known Courier provider - * key (see catalog). + * Configures a provider integration from a Courier provider key and its settings. Check the + * catalog endpoint for the schema each provider expects. */ fun create(params: ProviderCreateParams): CompletableFuture = create(params, RequestOptions.none()) @@ -46,7 +54,10 @@ interface ProviderServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Fetch a single provider configuration by ID. */ + /** + * Returns one configured provider by id, including its channel, provider key, alias, title, and + * current settings. + */ fun retrieve(id: String): CompletableFuture = retrieve(id, ProviderRetrieveParams.none()) @@ -78,10 +89,8 @@ interface ProviderServiceAsync { retrieve(id, ProviderRetrieveParams.none(), requestOptions) /** - * Replace an existing provider configuration. The `provider` key is required and determines - * which provider-specific settings schema is applied. All other fields are optional — omitted - * fields are cleared from the stored configuration (this is a full replacement, not a partial - * merge). Changing the provider type for an existing configuration is not supported. + * Replaces a provider's configuration in full, clearing any field you omit rather than merging + * it. Send the complete settings object. */ fun update(id: String, params: ProviderUpdateParams): CompletableFuture = update(id, params, RequestOptions.none()) @@ -104,8 +113,8 @@ interface ProviderServiceAsync { ): CompletableFuture /** - * List configured provider integrations for the current workspace. Supports cursor-based - * pagination. + * Lists the provider integrations configured in the workspace, one entry per channel and + * provider key with its alias and settings. */ fun list(): CompletableFuture = list(ProviderListParams.none()) @@ -125,8 +134,8 @@ interface ProviderServiceAsync { list(ProviderListParams.none(), requestOptions) /** - * Delete a provider configuration. Returns 409 if the provider is still referenced by routing - * or notifications. + * Deletes a provider configuration, which fails while routing strategies or templates still + * reference it. Update those references first. */ fun delete(id: String): CompletableFuture = delete(id, ProviderDeleteParams.none()) @@ -171,6 +180,10 @@ interface ProviderServiceAsync { modifier: Consumer ): ProviderServiceAsync.WithRawResponse + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ fun catalog(): CatalogServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsyncImpl.kt index 5e7646ee..74f7b0df 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/ProviderServiceAsyncImpl.kt @@ -30,6 +30,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ class ProviderServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : ProviderServiceAsync { @@ -44,6 +48,10 @@ class ProviderServiceAsyncImpl internal constructor(private val clientOptions: C override fun withOptions(modifier: Consumer): ProviderServiceAsync = ProviderServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ override fun catalog(): CatalogServiceAsync = catalog override fun create( @@ -98,6 +106,10 @@ class ProviderServiceAsyncImpl internal constructor(private val clientOptions: C clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ override fun catalog(): CatalogServiceAsync.WithRawResponse = catalog private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsync.kt index 22cab94b..e00ddb09 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsync.kt @@ -9,6 +9,10 @@ import com.courier.models.requests.RequestArchiveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ interface RequestServiceAsync { /** @@ -23,7 +27,10 @@ interface RequestServiceAsync { */ fun withOptions(modifier: Consumer): RequestServiceAsync - /** Archive message */ + /** + * Archives a send request by its request id. Use it to remove test sends or superseded requests + * from the message list without deleting them. + */ fun archive(requestId: String): CompletableFuture = archive(requestId, RequestArchiveParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsyncImpl.kt index 66fd00e1..a758c5b5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/RequestServiceAsyncImpl.kt @@ -20,6 +20,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ class RequestServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : RequestServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsync.kt index 36c9f9c7..54d5c4c7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsync.kt @@ -19,6 +19,7 @@ import com.courier.models.routingstrategies.RoutingStrategyRetrieveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Define reusable channel routing and failover strategies, and see which templates use them. */ interface RoutingStrategyServiceAsync { /** @@ -65,8 +66,8 @@ interface RoutingStrategyServiceAsync { create(routingStrategyCreateRequest, RequestOptions.none()) /** - * Retrieve a routing strategy by ID. Returns the full entity including routing content and - * metadata. + * Returns one routing strategy by id with its name, tags, channels, and the routing rules that + * decide provider order and fallback. */ fun retrieve(id: String): CompletableFuture = retrieve(id, RoutingStrategyRetrieveParams.none()) @@ -160,8 +161,8 @@ interface RoutingStrategyServiceAsync { archive(id, RoutingStrategyArchiveParams.none(), requestOptions) /** - * List notification templates associated with a routing strategy. Includes template metadata - * only, not full content. + * Returns the notification templates using a routing strategy, with paging. Check this before + * changing a strategy that templates depend on. */ fun listNotifications(id: String): CompletableFuture = listNotifications(id, RoutingStrategyListNotificationsParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncImpl.kt index a805c99e..ceb38953 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncImpl.kt @@ -30,6 +30,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Define reusable channel routing and failover strategies, and see which templates use them. */ class RoutingStrategyServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : RoutingStrategyServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsync.kt index c9589665..6909740b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsync.kt @@ -10,6 +10,10 @@ import com.courier.models.send.SendMessageResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ interface SendServiceAsync { /** @@ -24,7 +28,10 @@ interface SendServiceAsync { */ fun withOptions(modifier: Consumer): SendServiceAsync - /** Send a message to one or more recipients. */ + /** + * Sends a message to one or more recipients and returns a requestId. Courier routes it to + * email, SMS, push, chat, or in-app based on your rules. + */ fun message(params: SendMessageParams): CompletableFuture = message(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsyncImpl.kt index 37a9c03c..5f3a3df5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/SendServiceAsyncImpl.kt @@ -20,6 +20,10 @@ import com.courier.models.send.SendMessageResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ class SendServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : SendServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsync.kt index df63b8f2..a79b3b27 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsync.kt @@ -19,6 +19,10 @@ import com.courier.services.async.tenants.TemplateServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ interface TenantServiceAsync { /** @@ -35,9 +39,16 @@ interface TenantServiceAsync { fun preferences(): PreferenceServiceAsync + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun templates(): TemplateServiceAsync - /** Get a Tenant */ + /** + * Returns one tenant with its name, parent tenant id, default preferences, properties, and the + * user profile applied to its members. + */ fun retrieve(tenantId: String): CompletableFuture = retrieve(tenantId, TenantRetrieveParams.none()) @@ -69,7 +80,10 @@ interface TenantServiceAsync { fun retrieve(tenantId: String, requestOptions: RequestOptions): CompletableFuture = retrieve(tenantId, TenantRetrieveParams.none(), requestOptions) - /** Create or Replace a Tenant */ + /** + * Creates or replaces a tenant from a name, parent, brand, properties, and default preferences + * supplied in the request body. + */ fun update(tenantId: String, params: TenantUpdateParams): CompletableFuture = update(tenantId, params, RequestOptions.none()) @@ -91,7 +105,10 @@ interface TenantServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Get a List of Tenants */ + /** + * Lists the workspace's tenants, each carrying a name, parent tenant, properties, and default + * preferences. Paged. + */ fun list(): CompletableFuture = list(TenantListParams.none()) /** @see list */ @@ -109,7 +126,10 @@ interface TenantServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(TenantListParams.none(), requestOptions) - /** Delete a Tenant */ + /** + * Deletes a tenant. Its members' workspace-level profiles and preferences live outside the + * tenant and are managed separately. + */ fun delete(tenantId: String): CompletableFuture = delete(tenantId, TenantDeleteParams.none()) @@ -141,7 +161,10 @@ interface TenantServiceAsync { fun delete(tenantId: String, requestOptions: RequestOptions): CompletableFuture = delete(tenantId, TenantDeleteParams.none(), requestOptions) - /** Get Users in Tenant */ + /** + * Returns the users belonging to a tenant with cursor paging. Use it to see who a tenant-scoped + * send will reach. + */ fun listUsers(tenantId: String): CompletableFuture = listUsers(tenantId, TenantListUsersParams.none()) @@ -193,6 +216,10 @@ interface TenantServiceAsync { fun preferences(): PreferenceServiceAsync.WithRawResponse + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun templates(): TemplateServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsyncImpl.kt index fa5ff644..68892ef7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/TenantServiceAsyncImpl.kt @@ -33,6 +33,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ class TenantServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TenantServiceAsync { @@ -53,6 +57,10 @@ class TenantServiceAsyncImpl internal constructor(private val clientOptions: Cli override fun preferences(): PreferenceServiceAsync = preferences + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun templates(): TemplateServiceAsync = templates override fun retrieve( @@ -113,6 +121,10 @@ class TenantServiceAsyncImpl internal constructor(private val clientOptions: Cli override fun preferences(): PreferenceServiceAsync.WithRawResponse = preferences + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun templates(): TemplateServiceAsync.WithRawResponse = templates private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsync.kt index ded96302..ad550ed9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsync.kt @@ -11,6 +11,7 @@ import com.courier.models.translations.TranslationUpdateParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Store and retrieve the translation strings Courier uses to render localized template content. */ interface TranslationServiceAsync { /** @@ -25,7 +26,10 @@ interface TranslationServiceAsync { */ fun withOptions(modifier: Consumer): TranslationServiceAsync - /** Get translations by locale */ + /** + * Returns the translation strings stored for one domain and locale, for use in localized + * notification content. + */ fun retrieve(locale: String, params: TranslationRetrieveParams): CompletableFuture = retrieve(locale, params, RequestOptions.none()) @@ -47,7 +51,10 @@ interface TranslationServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Update a translation */ + /** + * Uploads the translation strings for one domain and locale. Courier uses them to render + * localized content for recipients in that locale. + */ fun update(locale: String, params: TranslationUpdateParams): CompletableFuture = update(locale, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsyncImpl.kt index e448a165..90c3d54d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/TranslationServiceAsyncImpl.kt @@ -23,6 +23,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Store and retrieve the translation strings Courier uses to render localized template content. */ class TranslationServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TranslationServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsync.kt index d864c411..db1e8f80 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsync.kt @@ -22,10 +22,15 @@ interface UserServiceAsync { */ fun withOptions(modifier: Consumer): UserServiceAsync + /** Read and write a single user's notification preferences, per topic and per channel. */ fun preferences(): PreferenceServiceAsync + /** Associate a user with one or more tenants, and read or remove those associations. */ fun tenants(): TenantServiceAsync + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications to. + */ fun tokens(): TokenServiceAsync /** A view of [UserServiceAsync] that provides access to raw HTTP responses for each method. */ @@ -38,10 +43,16 @@ interface UserServiceAsync { */ fun withOptions(modifier: Consumer): UserServiceAsync.WithRawResponse + /** Read and write a single user's notification preferences, per topic and per channel. */ fun preferences(): PreferenceServiceAsync.WithRawResponse + /** Associate a user with one or more tenants, and read or remove those associations. */ fun tenants(): TenantServiceAsync.WithRawResponse + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications + * to. + */ fun tokens(): TokenServiceAsync.WithRawResponse } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsyncImpl.kt index 61ff5476..36a93cc7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/UserServiceAsyncImpl.kt @@ -31,10 +31,15 @@ class UserServiceAsyncImpl internal constructor(private val clientOptions: Clien override fun withOptions(modifier: Consumer): UserServiceAsync = UserServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** Read and write a single user's notification preferences, per topic and per channel. */ override fun preferences(): PreferenceServiceAsync = preferences + /** Associate a user with one or more tenants, and read or remove those associations. */ override fun tenants(): TenantServiceAsync = tenants + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications to. + */ override fun tokens(): TokenServiceAsync = tokens class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -59,10 +64,16 @@ class UserServiceAsyncImpl internal constructor(private val clientOptions: Clien clientOptions.toBuilder().apply(modifier::accept).build() ) + /** Read and write a single user's notification preferences, per topic and per channel. */ override fun preferences(): PreferenceServiceAsync.WithRawResponse = preferences + /** Associate a user with one or more tenants, and read or remove those associations. */ override fun tenants(): TenantServiceAsync.WithRawResponse = tenants + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications + * to. + */ override fun tokens(): TokenServiceAsync.WithRawResponse = tokens } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsync.kt index e47246dc..d92ba467 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsync.kt @@ -21,6 +21,10 @@ import com.courier.services.async.workspacepreferences.TopicServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ interface WorkspacePreferenceServiceAsync { /** @@ -35,11 +39,15 @@ interface WorkspacePreferenceServiceAsync { */ fun withOptions(modifier: Consumer): WorkspacePreferenceServiceAsync + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun topics(): TopicServiceAsync /** - * Create a workspace preference. The workspace preference id is generated and returned. Topics - * are created inside a workspace preference via POST /preferences/sections/{section_id}/topics. + * Creates a workspace preference and returns its generated id. Add subscription topics to it + * afterwards with the topics endpoint. */ fun create( params: WorkspacePreferenceCreateParams @@ -69,7 +77,10 @@ interface WorkspacePreferenceServiceAsync { ): CompletableFuture = create(workspacePreferenceCreateRequest, RequestOptions.none()) - /** Retrieve a workspace preference by id, including its topics. */ + /** + * Returns one workspace preference by id, including its subscription topics, routing options, + * and custom routing flag. + */ fun retrieve(sectionId: String): CompletableFuture = retrieve(sectionId, WorkspacePreferenceRetrieveParams.none()) @@ -107,8 +118,8 @@ interface WorkspacePreferenceServiceAsync { retrieve(sectionId, WorkspacePreferenceRetrieveParams.none(), requestOptions) /** - * List the workspace's preferences. Each workspace preference embeds its topics. Scoped to the - * workspace of the API key. + * Returns the workspace's preferences, each embedding its subscription topics, routing options, + * and whether custom routing is allowed. */ fun list(): CompletableFuture = list(WorkspacePreferenceListParams.none()) @@ -164,9 +175,8 @@ interface WorkspacePreferenceServiceAsync { archive(sectionId, WorkspacePreferenceArchiveParams.none(), requestOptions) /** - * Publish the workspace's preferences page. Takes a snapshot of every workspace preference with - * its topics under a new published version, making the current state visible on the hosted - * preferences page (non-draft). + * Publishes the workspace preference page, snapshotting every preference and topic, and returns + * the page id and a preview URL. */ fun publish(): CompletableFuture = publish(WorkspacePreferencePublishParams.none()) @@ -248,6 +258,10 @@ interface WorkspacePreferenceServiceAsync { modifier: Consumer ): WorkspacePreferenceServiceAsync.WithRawResponse + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun topics(): TopicServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncImpl.kt index 6a0676f8..8c24359b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncImpl.kt @@ -32,6 +32,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ class WorkspacePreferenceServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : WorkspacePreferenceServiceAsync { @@ -51,6 +55,10 @@ internal constructor(private val clientOptions: ClientOptions) : WorkspacePrefer clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun topics(): TopicServiceAsync = topics override fun create( @@ -112,6 +120,10 @@ internal constructor(private val clientOptions: ClientOptions) : WorkspacePrefer clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun topics(): TopicServiceAsync.WithRawResponse = topics private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsync.kt index 68d810c6..7ed86d79 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsync.kt @@ -11,6 +11,7 @@ import com.courier.models.automations.invoke.InvokeInvokeByTemplateParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ interface InvokeServiceAsync { /** @@ -26,9 +27,8 @@ interface InvokeServiceAsync { fun withOptions(modifier: Consumer): InvokeServiceAsync /** - * Invoke an ad hoc automation run. This endpoint accepts a JSON payload with a series of - * automation steps. For information about what steps are available, checkout the ad hoc - * automation guide [here](https://www.courier.com/docs/automations/steps/). + * Runs a series of automation steps supplied inline, without a saved template, and returns a + * runId. */ fun invokeAdHoc(params: InvokeInvokeAdHocParams): CompletableFuture = invokeAdHoc(params, RequestOptions.none()) @@ -39,7 +39,10 @@ interface InvokeServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Invoke an automation run from an automation template. */ + /** + * Starts an automation run from a saved template for one recipient, with optional data and + * profile, and returns a runId. + */ fun invokeByTemplate( templateId: String, params: InvokeInvokeByTemplateParams, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsyncImpl.kt index b52b9dd5..95ac3344 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/automations/InvokeServiceAsyncImpl.kt @@ -23,6 +23,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ class InvokeServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : InvokeServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt index 92475a25..043988e8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsync.kt @@ -12,6 +12,10 @@ import com.courier.models.digests.schedules.ScheduleReleaseParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ interface ScheduleServiceAsync { /** @@ -27,9 +31,8 @@ interface ScheduleServiceAsync { fun withOptions(modifier: Consumer): ScheduleServiceAsync /** - * List the digest instances for a schedule. Each instance represents the events accumulated for - * a single user against the schedule, and can be used to monitor digest accumulation before the - * digest is released. + * Returns the digest instances for a schedule, one per user, with cursor paging. Use it to see + * what has accumulated before a digest releases. */ fun listInstances(scheduleId: String): CompletableFuture = listInstances(scheduleId, ScheduleListInstancesParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt index 1af16147..35088a2e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/digests/ScheduleServiceAsyncImpl.kt @@ -24,6 +24,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ class ScheduleServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : ScheduleServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/inbox/MessageServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/inbox/MessageServiceAsync.kt new file mode 100644 index 00000000..821d5950 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/inbox/MessageServiceAsync.kt @@ -0,0 +1,164 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.inbox + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse +import com.courier.models.inbox.messages.MessageDeleteParams +import com.courier.models.inbox.messages.MessageRestoreParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +/** Manage the messages in a user's in-app inbox. */ +interface MessageServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MessageServiceAsync + + /** + * Delete a user's inbox message. The message is removed from every inbox read (it stops + * appearing in the recipient's Inbox); it can be restored. + */ + fun delete(messageId: String): CompletableFuture = + delete(messageId, MessageDeleteParams.none()) + + /** @see delete */ + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + delete(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see delete */ + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + ): CompletableFuture = delete(messageId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: MessageDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see delete */ + fun delete(params: MessageDeleteParams): CompletableFuture = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete(messageId: String, requestOptions: RequestOptions): CompletableFuture = + delete(messageId, MessageDeleteParams.none(), requestOptions) + + /** Restore a previously deleted inbox message. */ + fun restore(messageId: String, params: MessageRestoreParams): CompletableFuture = + restore(messageId, params, RequestOptions.none()) + + /** @see restore */ + fun restore( + messageId: String, + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + restore(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see restore */ + fun restore(params: MessageRestoreParams): CompletableFuture = + restore(params, RequestOptions.none()) + + /** @see restore */ + fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * A view of [MessageServiceAsync] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): MessageServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `delete /inbox/messages/{message_id}`, but is otherwise + * the same as [MessageServiceAsync.delete]. + */ + fun delete(messageId: String): CompletableFuture = + delete(messageId, MessageDeleteParams.none()) + + /** @see delete */ + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + delete(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see delete */ + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + ): CompletableFuture = delete(messageId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: MessageDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see delete */ + fun delete(params: MessageDeleteParams): CompletableFuture = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + messageId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + delete(messageId, MessageDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /inbox/messages/{message_id}/restore`, but is + * otherwise the same as [MessageServiceAsync.restore]. + */ + fun restore( + messageId: String, + params: MessageRestoreParams, + ): CompletableFuture = restore(messageId, params, RequestOptions.none()) + + /** @see restore */ + fun restore( + messageId: String, + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + restore(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see restore */ + fun restore(params: MessageRestoreParams): CompletableFuture = + restore(params, RequestOptions.none()) + + /** @see restore */ + fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/inbox/MessageServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/inbox/MessageServiceAsyncImpl.kt new file mode 100644 index 00000000..e15a01ae --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/inbox/MessageServiceAsyncImpl.kt @@ -0,0 +1,118 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.inbox + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler +import com.courier.core.handlers.errorBodyHandler +import com.courier.core.handlers.errorHandler +import com.courier.core.http.HttpMethod +import com.courier.core.http.HttpRequest +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponse.Handler +import com.courier.core.http.json +import com.courier.core.http.parseable +import com.courier.core.prepareAsync +import com.courier.models.inbox.messages.MessageDeleteParams +import com.courier.models.inbox.messages.MessageRestoreParams +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +/** Manage the messages in a user's in-app inbox. */ +class MessageServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + MessageServiceAsync { + + private val withRawResponse: MessageServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): MessageServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): MessageServiceAsync = + MessageServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun delete( + params: MessageDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // delete /inbox/messages/{message_id} + withRawResponse().delete(params, requestOptions).thenAccept {} + + override fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // put /inbox/messages/{message_id}/restore + withRawResponse().restore(params, requestOptions).thenAccept {} + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + MessageServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): MessageServiceAsync.WithRawResponse = + MessageServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: MessageDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("messageId", params.messageId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("inbox", "messages", params._pathParam(0)) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + } + + private val restoreHandler: Handler = emptyHandler() + + override fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("messageId", params.messageId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("inbox", "messages", params._pathParam(0), "restore") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { restoreHandler.handle(it) } + } + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt index 663afc24..546d7917 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt @@ -24,6 +24,10 @@ import com.courier.models.notifications.NotificationTemplateVersionListResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ interface TemplateServiceAsync { /** @@ -67,8 +71,8 @@ interface TemplateServiceAsync { ): CompletableFuture /** - * Fetch a journey-scoped notification template by id. Pass `?version=draft` (default - * `published`) to retrieve the working draft, or `?version=vN` for a historical version. + * Returns a journey's own notification template with its name, brand, subscription topic, and + * content. Defaults to the published version. */ fun retrieve( notificationId: String, @@ -133,7 +137,10 @@ interface TemplateServiceAsync { ): CompletableFuture = list(templateId, TemplateListParams.none(), requestOptions) - /** Archive the journey-scoped notification template. Archived templates cannot be sent. */ + /** + * Archives one journey's notification template, preventing further sends. Detach any send node + * referencing it beforehand. + */ fun archive(notificationId: String, params: TemplateArchiveParams): CompletableFuture = archive(notificationId, params, RequestOptions.none()) @@ -156,8 +163,8 @@ interface TemplateServiceAsync { ): CompletableFuture /** - * List published versions of the journey-scoped notification template, ordered most recent - * first. + * Lists the published versions of a template that belongs to a journey, most recent first. + * Paged by cursor. */ fun listVersions( notificationId: String, @@ -186,8 +193,8 @@ interface TemplateServiceAsync { ): CompletableFuture /** - * Publish the current draft of the journey-scoped notification template as a new version. - * Optionally roll back to a prior version by passing `{ "version": "vN" }`. + * Publishes a journey-scoped template's draft as a new version. Pass a version instead to roll + * back the template to an earlier publish. */ fun publish(notificationId: String, params: TemplatePublishParams): CompletableFuture = publish(notificationId, params, RequestOptions.none()) @@ -270,7 +277,10 @@ interface TemplateServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Replace the journey-scoped notification template draft. */ + /** + * Replaces the draft content of one journey's notification template. Publish it before send + * nodes referencing it render the change. + */ fun replace( notificationId: String, params: TemplateReplaceParams, @@ -296,10 +306,8 @@ interface TemplateServiceAsync { ): CompletableFuture /** - * Retrieve the elemental content of a journey-scoped notification template. The response - * contains the versioned elements along with their content checksums, which can be used to - * detect changes between versions. Pass `?version=draft` (default `published`) to retrieve the - * working draft, or `?version=vN` for a historical version. + * Returns the Elemental elements and version of a journey-scoped template's content. Compare + * versions to see what changed between publishes. */ fun retrieveContent( notificationId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt index 30be87fb..a087f67d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt @@ -36,6 +36,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ class TemplateServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TemplateServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsync.kt index c18d9413..0256ef99 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsync.kt @@ -15,6 +15,10 @@ import com.courier.models.lists.subscriptions.SubscriptionUnsubscribeUserParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ interface SubscriptionServiceAsync { /** @@ -29,7 +33,10 @@ interface SubscriptionServiceAsync { */ fun withOptions(modifier: Consumer): SubscriptionServiceAsync - /** Get the list's subscriptions. */ + /** + * Returns the users subscribed to a list with paging, each with the preferences recorded for + * that subscription. + */ fun list(listId: String): CompletableFuture = list(listId, SubscriptionListParams.none()) @@ -114,8 +121,8 @@ interface SubscriptionServiceAsync { ): CompletableFuture /** - * Subscribe a user to an existing list (note: if the List does not exist, it will be - * automatically created). + * Subscribes one user to a list, creating the list if it does not yet exist. Optional + * preferences apply to this subscription only. */ fun subscribeUser( userId: String, @@ -140,7 +147,10 @@ interface SubscriptionServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Delete a subscription to a list by list ID and user ID. */ + /** + * Removes one user's subscription to a list, addressed by list id and user id. The user's + * profile and other subscriptions are separate resources. + */ fun unsubscribeUser( userId: String, params: SubscriptionUnsubscribeUserParams, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncImpl.kt index 358fe398..0ac31376 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncImpl.kt @@ -27,6 +27,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ class SubscriptionServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : SubscriptionServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt index 9470d9b3..4ed97b49 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsync.kt @@ -14,6 +14,7 @@ import com.courier.models.notifications.checks.CheckUpdateResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Create, update, version, publish, and localize notification templates and their content. */ interface CheckServiceAsync { /** @@ -28,7 +29,10 @@ interface CheckServiceAsync { */ fun withOptions(modifier: Consumer): CheckServiceAsync - /** Replace the submission checks for a notification template. */ + /** + * Replaces the approval checks on a template submission with the complete set supplied in the + * request body. + */ fun update( submissionId: String, params: CheckUpdateParams, @@ -52,7 +56,10 @@ interface CheckServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Retrieve the submission checks for a notification template. */ + /** + * Returns the approval checks recorded for a template submission, each with its pass or fail + * result. + */ fun list(submissionId: String, params: CheckListParams): CompletableFuture = list(submissionId, params, RequestOptions.none()) @@ -74,7 +81,10 @@ interface CheckServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Cancel a submission for a notification template. */ + /** + * Cancels a pending template submission, withdrawing it from the approval workflow. The + * template stays in draft and can be resubmitted later. + */ fun delete(submissionId: String, params: CheckDeleteParams): CompletableFuture = delete(submissionId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsyncImpl.kt index 48a56b81..08eaacbd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/notifications/CheckServiceAsyncImpl.kt @@ -26,6 +26,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Create, update, version, publish, and localize notification templates and their content. */ class CheckServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : CheckServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsync.kt index b5fc9de1..4b6c19fd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsync.kt @@ -14,6 +14,10 @@ import com.courier.models.profiles.lists.ListSubscribeResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ interface ListServiceAsync { /** @@ -28,7 +32,10 @@ interface ListServiceAsync { */ fun withOptions(modifier: Consumer): ListServiceAsync - /** Returns the subscribed lists for a specified user. */ + /** + * Returns the lists a user is subscribed to, with paging. Use it to check what a recipient will + * receive before sending to a list. + */ fun retrieve(userId: String): CompletableFuture = retrieve(userId, ListRetrieveParams.none()) @@ -63,7 +70,10 @@ interface ListServiceAsync { ): CompletableFuture = retrieve(userId, ListRetrieveParams.none(), requestOptions) - /** Removes all list subscriptions for given user. */ + /** + * Removes every list subscription for a user at once. Their profile and preferences are + * untouched, so this only affects list-targeted sends. + */ fun delete(userId: String): CompletableFuture = delete(userId, ListDeleteParams.none()) @@ -99,8 +109,8 @@ interface ListServiceAsync { delete(userId, ListDeleteParams.none(), requestOptions) /** - * Subscribes the given user to one or more lists. If the list does not exist, it will be - * created. + * Subscribes a user to one or more lists, creating any list that does not yet exist. Optional + * preferences apply to each subscription. */ fun subscribe( userId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsyncImpl.kt index 41fc1de9..f7b7b848 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/profiles/ListServiceAsyncImpl.kt @@ -26,6 +26,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ class ListServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : ListServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsync.kt index 601a3b65..aaf97c92 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsync.kt @@ -10,6 +10,10 @@ import com.courier.models.providers.catalog.CatalogListResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ interface CatalogServiceAsync { /** @@ -25,9 +29,8 @@ interface CatalogServiceAsync { fun withOptions(modifier: Consumer): CatalogServiceAsync /** - * Returns the catalog of available provider types with their display names, descriptions, and - * configuration schema fields (snake_case, with `type` and `required`). Providers with no - * configurable schema return only `provider`, `name`, and `description`. + * Returns the provider types Courier supports, each with a display name, description, and the + * configuration fields it requires. */ fun list(): CompletableFuture = list(CatalogListParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsyncImpl.kt index f12ac37c..3b3dbecd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/providers/CatalogServiceAsyncImpl.kt @@ -19,6 +19,10 @@ import com.courier.models.providers.catalog.CatalogListResponse import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ class CatalogServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : CatalogServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsync.kt index ba6d53d0..66029816 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsync.kt @@ -20,6 +20,10 @@ interface PreferenceServiceAsync { */ fun withOptions(modifier: Consumer): PreferenceServiceAsync + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun items(): ItemServiceAsync /** @@ -37,6 +41,10 @@ interface PreferenceServiceAsync { modifier: Consumer ): PreferenceServiceAsync.WithRawResponse + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun items(): ItemServiceAsync.WithRawResponse } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsyncImpl.kt index 2600f7da..c4b6d7d8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/PreferenceServiceAsyncImpl.kt @@ -21,6 +21,10 @@ class PreferenceServiceAsyncImpl internal constructor(private val clientOptions: override fun withOptions(modifier: Consumer): PreferenceServiceAsync = PreferenceServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun items(): ItemServiceAsync = items class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -37,6 +41,10 @@ class PreferenceServiceAsyncImpl internal constructor(private val clientOptions: clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun items(): ItemServiceAsync.WithRawResponse = items } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt index 57af2f50..4e36c538 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt @@ -19,6 +19,10 @@ import com.courier.services.async.tenants.templates.VersionServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ interface TemplateServiceAsync { /** @@ -33,9 +37,16 @@ interface TemplateServiceAsync { */ fun withOptions(modifier: Consumer): TemplateServiceAsync + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun versions(): VersionServiceAsync - /** Get a Template in Tenant */ + /** + * Returns a tenant's notification template with its content, version, and created, updated, and + * published timestamps. + */ fun retrieve( templateId: String, params: TemplateRetrieveParams, @@ -60,7 +71,10 @@ interface TemplateServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** List Templates in Tenant */ + /** + * Lists a tenant's notification templates, each carrying its version and published timestamp. + * Paged. + */ fun list(tenantId: String): CompletableFuture = list(tenantId, TemplateListParams.none()) @@ -96,12 +110,8 @@ interface TemplateServiceAsync { list(tenantId, TemplateListParams.none(), requestOptions) /** - * Deletes the tenant's notification template with the given `template_id`. - * - * Returns **204 No Content** with an empty body on success. - * - * Returns **404** if there is no template with this ID for the tenant, including a second - * `DELETE` after a successful removal. + * Deletes a tenant's notification template by id. Sends for that tenant then use the workspace + * template registered under the same id. */ fun delete(templateId: String, params: TemplateDeleteParams): CompletableFuture = delete(templateId, params, RequestOptions.none()) @@ -125,10 +135,8 @@ interface TemplateServiceAsync { ): CompletableFuture /** - * Publishes a specific version of a notification template for a tenant. - * - * The template must already exist in the tenant's notification map. If no version is specified, - * defaults to publishing the "latest" version. + * Publishes a version of a tenant's notification template, making it the content that tenant's + * sends render from until you publish another. */ fun publish( templateId: String, @@ -156,12 +164,8 @@ interface TemplateServiceAsync { ): CompletableFuture /** - * Creates or updates a notification template for a tenant. - * - * If the template already exists for the tenant, it will be updated (200). Otherwise, a new - * template is created (201). - * - * Optionally publishes the template immediately if the `published` flag is set to true. + * Creates or updates a notification template scoped to one tenant, letting a tenant override + * the content the workspace template would send. */ fun replace( templateId: String, @@ -201,6 +205,10 @@ interface TemplateServiceAsync { modifier: Consumer ): TemplateServiceAsync.WithRawResponse + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun versions(): VersionServiceAsync.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt index 70affccc..faa27e0c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt @@ -32,6 +32,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ class TemplateServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TemplateServiceAsync { @@ -46,6 +50,10 @@ class TemplateServiceAsyncImpl internal constructor(private val clientOptions: C override fun withOptions(modifier: Consumer): TemplateServiceAsync = TemplateServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun versions(): VersionServiceAsync = versions override fun retrieve( @@ -100,6 +108,10 @@ class TemplateServiceAsyncImpl internal constructor(private val clientOptions: C clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun versions(): VersionServiceAsync.WithRawResponse = versions private val retrieveHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsync.kt index 67da4bad..78975dd5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsync.kt @@ -10,6 +10,10 @@ import com.courier.models.tenants.preferences.items.ItemUpdateParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ interface ItemServiceAsync { /** @@ -24,7 +28,10 @@ interface ItemServiceAsync { */ fun withOptions(modifier: Consumer): ItemServiceAsync - /** Create or Replace Default Preferences For Topic */ + /** + * Sets a tenant's default opt-in status for one subscription topic, which applies to every + * member unless a user sets their own override. + */ fun update(topicId: String, params: ItemUpdateParams): CompletableFuture = update(topicId, params, RequestOptions.none()) @@ -46,7 +53,10 @@ interface ItemServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Remove Default Preferences For Topic */ + /** + * Removes a tenant's default preference for one subscription topic, addressed by tenant id and + * topic id. + */ fun delete(topicId: String, params: ItemDeleteParams): CompletableFuture = delete(topicId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsyncImpl.kt index 5f2b54e8..40d2269d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/preferences/ItemServiceAsyncImpl.kt @@ -21,6 +21,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ class ItemServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : ItemServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsync.kt index e03aed25..e9feb16f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsync.kt @@ -10,6 +10,10 @@ import com.courier.models.tenants.templates.versions.VersionRetrieveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ interface VersionServiceAsync { /** @@ -25,12 +29,8 @@ interface VersionServiceAsync { fun withOptions(modifier: Consumer): VersionServiceAsync /** - * Fetches a specific version of a tenant template. - * - * Supports the following version formats: - * - `latest` - The most recent version of the template - * - `published` - The currently published version - * - `v{version}` - A specific version (e.g., "v1", "v2", "v1.0.0") + * Returns one version of a tenant template, addressed by version number or by latest, with its + * content and publish timestamp. */ fun retrieve( version: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsyncImpl.kt index 34666ba1..64257daf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/templates/VersionServiceAsyncImpl.kt @@ -21,6 +21,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ class VersionServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : VersionServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsync.kt index 5b129471..1ffbf7ba 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsync.kt @@ -20,6 +20,7 @@ import com.courier.models.users.preferences.PreferenceUpdateOrCreateTopicRespons import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Read and write a single user's notification preferences, per topic and per channel. */ interface PreferenceServiceAsync { /** @@ -34,7 +35,10 @@ interface PreferenceServiceAsync { */ fun withOptions(modifier: Consumer): PreferenceServiceAsync - /** Fetch all user preferences. */ + /** + * Returns a user's preference overrides with paging, one entry per subscription topic they have + * set a choice for. + */ fun retrieve(userId: String): CompletableFuture = retrieve(userId, PreferenceRetrieveParams.none()) @@ -71,21 +75,8 @@ interface PreferenceServiceAsync { retrieve(userId, PreferenceRetrieveParams.none(), requestOptions) /** - * Replace a user's complete set of preference overrides in a single request. The topics in the - * request body become the recipient's entire set of overrides: listed topics are created or - * updated, and every existing override that is not included in the body is reset to its topic - * default. Submitting an empty `topics` array is a valid clear-all that resets every existing - * override. - * - * This operation is validation-atomic (all-or-nothing): structural validation fails fast with a - * single `400`, and if any topic is semantically invalid (an unknown topic, a `REQUIRED` topic - * that cannot be opted out, or a custom routing request that is not available on the - * workspace's plan) the request returns a single `400` aggregating every failure in `errors` - * and writes nothing. On success it returns `200` with `items` (the complete resulting override - * set) and `deleted` (the ids of the overrides that were reset to default). - * - * Every `topic_id` in the response — in `items`, `deleted`, and any `errors` — is returned in - * Courier's canonical topic id form, regardless of the form supplied in the request. + * Replaces a user's entire set of preference overrides. Any topic you leave out is reset to its + * default, so send the full set rather than a subset. */ fun bulkReplace( userId: String, @@ -113,20 +104,8 @@ interface PreferenceServiceAsync { ): CompletableFuture /** - * Additively create or update a user's preferences for one or more subscription topics in a - * single request. Only the topics included in the request body are created or updated; any - * existing overrides for topics not listed are left untouched. - * - * Structural validation of the request body fails fast with a single `400`. Beyond that, each - * topic is processed independently (partial-success, not all-or-nothing): valid topics are - * written and returned in `items`, while topics that cannot be applied are collected in - * `errors` with a per-topic `reason` (for example an unknown topic, a `REQUIRED` topic that - * cannot be opted out, a custom routing request that is not available on the workspace's plan, - * or a write failure). The request therefore returns `200` with both lists whenever the body is - * structurally valid. - * - * Every `topic_id` in the response — in both `items` and `errors` — is returned in Courier's - * canonical topic id form, regardless of the form supplied in the request. + * Adds or updates a user's preferences for several subscription topics at once. Topics you + * leave out keep whatever they were set to before. */ fun bulkUpdate( userId: String, @@ -154,9 +133,8 @@ interface PreferenceServiceAsync { ): CompletableFuture /** - * Remove a user's preferences for a specific subscription topic, resetting the topic to its - * effective default. This operation is idempotent: deleting a preference that does not exist - * succeeds with no error. + * Removes a user's override for one subscription topic, resetting it to the effective default + * from the tenant or workspace. */ fun deleteTopic( topicId: String, @@ -181,7 +159,10 @@ interface PreferenceServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Fetch user preferences for a specific subscription topic. */ + /** + * Returns a user's opt-in status and channel choices for one subscription topic, or the + * effective default if they have set no override. + */ fun retrieveTopic( topicId: String, params: PreferenceRetrieveTopicParams, @@ -208,7 +189,10 @@ interface PreferenceServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Update or Create user preferences for a specific subscription topic. */ + /** + * Sets a user's opt-in status and channel choices for one subscription topic, overriding the + * tenant default for that topic only. + */ fun updateOrCreateTopic( topicId: String, params: PreferenceUpdateOrCreateTopicParams, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsyncImpl.kt index 733cacbc..28fe8b05 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/users/PreferenceServiceAsyncImpl.kt @@ -32,6 +32,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Read and write a single user's notification preferences, per topic and per channel. */ class PreferenceServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : PreferenceServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsync.kt index c0c2f924..567a54bd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsync.kt @@ -15,6 +15,7 @@ import com.courier.models.users.tenants.TenantRemoveSingleParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Associate a user with one or more tenants, and read or remove those associations. */ interface TenantServiceAsync { /** @@ -29,7 +30,10 @@ interface TenantServiceAsync { */ fun withOptions(modifier: Consumer): TenantServiceAsync - /** Returns a paginated list of user tenant associations. */ + /** + * Returns the tenants a user belongs to, with cursor paging. A user can belong to many tenants, + * each with its own profile and preferences. + */ fun list(userId: String): CompletableFuture = list(userId, TenantListParams.none()) @@ -64,9 +68,8 @@ interface TenantServiceAsync { ): CompletableFuture = list(userId, TenantListParams.none(), requestOptions) /** - * This endpoint is used to add a user to multiple tenants in one call. A custom profile can - * also be supplied for each tenant. This profile will be merged with the user's main profile - * when sending to the user with that tenant. + * Adds a user to several tenants in one call, each optionally with a per-tenant profile that + * overrides their workspace profile. */ fun addMultiple(userId: String, params: TenantAddMultipleParams): CompletableFuture = addMultiple(userId, params, RequestOptions.none()) @@ -90,10 +93,8 @@ interface TenantServiceAsync { ): CompletableFuture /** - * This endpoint is used to add a single tenant. - * - * A custom profile can also be supplied with the tenant. This profile will be merged with the - * user's main profile when sending to the user with that tenant. + * Adds a user to one tenant, optionally with a tenant-specific profile that overrides their + * workspace profile for sends in that tenant. */ fun addSingle(tenantId: String, params: TenantAddSingleParams): CompletableFuture = addSingle(tenantId, params, RequestOptions.none()) @@ -116,7 +117,10 @@ interface TenantServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Removes a user from any tenants they may have been associated with. */ + /** + * Removes a user from every tenant they belong to in one call. Their workspace-level profile is + * a separate resource. + */ fun removeAll(userId: String): CompletableFuture = removeAll(userId, TenantRemoveAllParams.none()) @@ -148,7 +152,10 @@ interface TenantServiceAsync { fun removeAll(userId: String, requestOptions: RequestOptions): CompletableFuture = removeAll(userId, TenantRemoveAllParams.none(), requestOptions) - /** Removes a user from the supplied tenant. */ + /** + * Removes a user from one tenant. Their other tenant memberships and workspace profile are + * managed through separate endpoints. + */ fun removeSingle(tenantId: String, params: TenantRemoveSingleParams): CompletableFuture = removeSingle(tenantId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsyncImpl.kt index a72c8fb7..89ea264e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TenantServiceAsyncImpl.kt @@ -27,6 +27,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Associate a user with one or more tenants, and read or remove those associations. */ class TenantServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TenantServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsync.kt index 9be42244..6b331580 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsync.kt @@ -17,6 +17,7 @@ import com.courier.models.users.tokens.TokenUpdateParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** Register and manage the APNS and FCM device tokens Courier delivers push notifications to. */ interface TokenServiceAsync { /** @@ -31,7 +32,10 @@ interface TokenServiceAsync { */ fun withOptions(modifier: Consumer): TokenServiceAsync - /** Get single token available for a `:token` */ + /** + * Returns one device token with its provider key, status and status reason, expiry date, and + * any properties stored alongside it. + */ fun retrieve( token: String, params: TokenRetrieveParams, @@ -55,7 +59,10 @@ interface TokenServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Apply a JSON Patch (RFC 6902) to the specified token. */ + /** + * Applies a JSON Patch to a device token, changing its status, expiry, or properties without + * re-registering it. + */ fun update(token: String, params: TokenUpdateParams): CompletableFuture = update(token, params, RequestOptions.none()) @@ -76,7 +83,10 @@ interface TokenServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Gets all tokens available for a :user_id */ + /** + * Returns every device token registered for a user, each with its provider key, status, and + * expiry date. + */ fun list(userId: String): CompletableFuture = list(userId, TokenListParams.none()) @@ -108,7 +118,10 @@ interface TokenServiceAsync { fun list(userId: String, requestOptions: RequestOptions): CompletableFuture = list(userId, TokenListParams.none(), requestOptions) - /** Delete User Token */ + /** + * Deletes one device token for a user, addressed by the token value, so push sends no longer + * target that device. + */ fun delete(token: String, params: TokenDeleteParams): CompletableFuture = delete(token, params, RequestOptions.none()) @@ -129,7 +142,10 @@ interface TokenServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Adds multiple tokens to a user and overwrites matching existing tokens. */ + /** + * Registers several device tokens for a user in one call, overwriting any stored token with a + * matching value. + */ fun addMultiple(userId: String): CompletableFuture = addMultiple(userId, TokenAddMultipleParams.none()) @@ -161,7 +177,10 @@ interface TokenServiceAsync { fun addMultiple(userId: String, requestOptions: RequestOptions): CompletableFuture = addMultiple(userId, TokenAddMultipleParams.none(), requestOptions) - /** Adds a single token to a user and overwrites a matching existing token. */ + /** + * Registers one device token for a user against a provider key, overwriting the token if it + * already exists. Push sends resolve tokens per user. + */ fun addSingle(token: String, params: TokenAddSingleParams): CompletableFuture = addSingle(token, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsyncImpl.kt index 493e458a..5f8b89ec 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/users/TokenServiceAsyncImpl.kt @@ -29,6 +29,7 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Register and manage the APNS and FCM device tokens Courier delivers push notifications to. */ class TokenServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TokenServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsync.kt index 42214e08..e91c95ac 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsync.kt @@ -16,6 +16,10 @@ import com.courier.models.workspacepreferences.topics.TopicRetrieveParams import java.util.concurrent.CompletableFuture import java.util.function.Consumer +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ interface TopicServiceAsync { /** @@ -31,8 +35,8 @@ interface TopicServiceAsync { fun withOptions(modifier: Consumer): TopicServiceAsync /** - * Create a subscription preference topic inside a workspace preference. Fails with 404 if the - * workspace preference does not exist. The topic id is generated and returned. + * Creates a subscription topic inside a workspace preference. The default status sets whether + * users start opted in, opted out, or required. */ fun create( sectionId: String, @@ -59,9 +63,8 @@ interface TopicServiceAsync { ): CompletableFuture /** - * Retrieve a topic within a workspace preference. Returns 404 if the workspace preference does - * not exist, the topic does not exist, or the topic belongs to a different workspace - * preference. + * Returns one subscription topic with its default status, routing options, allowed preferences, + * and unsubscribe header setting. */ fun retrieve( topicId: String, @@ -89,7 +92,10 @@ interface TopicServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** List the topics in a workspace preference. */ + /** + * Returns the subscription topics inside a workspace preference, each with its default status + * and routing options. + */ fun list(sectionId: String): CompletableFuture = list(sectionId, TopicListParams.none()) @@ -125,7 +131,10 @@ interface TopicServiceAsync { ): CompletableFuture = list(sectionId, TopicListParams.none(), requestOptions) - /** Archive a topic and remove it from its workspace preference. Same 404 rules as GET. */ + /** + * Archives a subscription topic and removes it from its workspace preference, addressed by + * section id and topic id. + */ fun archive(topicId: String, params: TopicArchiveParams): CompletableFuture = archive(topicId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncImpl.kt index 1601d378..6794a04b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncImpl.kt @@ -28,6 +28,10 @@ import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ class TopicServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TopicServiceAsync { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceService.kt index 4b73b462..f63644f0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceService.kt @@ -18,6 +18,7 @@ import com.courier.models.audiences.AudienceUpdateResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Define filter-based groups whose membership Courier recalculates as user profiles change. */ interface AudienceService { /** @@ -32,7 +33,10 @@ interface AudienceService { */ fun withOptions(modifier: Consumer): AudienceService - /** Returns the specified audience by id. */ + /** + * Returns one audience with its name, description, and the filter and AND or OR operator that + * decide which users belong to it. + */ fun retrieve(audienceId: String): Audience = retrieve(audienceId, AudienceRetrieveParams.none()) /** @see retrieve */ @@ -61,7 +65,10 @@ interface AudienceService { fun retrieve(audienceId: String, requestOptions: RequestOptions): Audience = retrieve(audienceId, AudienceRetrieveParams.none(), requestOptions) - /** Creates or updates audience. */ + /** + * Creates or replaces an audience from a filter and an AND or OR operator. Membership + * recalculates automatically as profiles change. + */ fun update(audienceId: String): AudienceUpdateResponse = update(audienceId, AudienceUpdateParams.none()) @@ -93,7 +100,10 @@ interface AudienceService { fun update(audienceId: String, requestOptions: RequestOptions): AudienceUpdateResponse = update(audienceId, AudienceUpdateParams.none(), requestOptions) - /** Get the audiences associated with the authorization token. */ + /** + * Returns the audiences in the workspace with paging. Audiences are filter-based groups that + * recalculate as user profiles change. + */ fun list(): AudienceListResponse = list(AudienceListParams.none()) /** @see list */ @@ -110,7 +120,10 @@ interface AudienceService { fun list(requestOptions: RequestOptions): AudienceListResponse = list(AudienceListParams.none(), requestOptions) - /** Deletes the specified audience. */ + /** + * Deletes an audience permanently, so update any caller sending to it by audience id first. + * Those sends fail once the audience is gone. + */ fun delete(audienceId: String) = delete(audienceId, AudienceDeleteParams.none()) /** @see delete */ @@ -134,7 +147,10 @@ interface AudienceService { fun delete(audienceId: String, requestOptions: RequestOptions) = delete(audienceId, AudienceDeleteParams.none(), requestOptions) - /** Get list of members of an audience. */ + /** + * Returns the users currently matching an audience filter, with paging. Membership is + * recalculated, so results shift as profiles change. + */ fun listMembers(audienceId: String): AudienceListMembersResponse = listMembers(audienceId, AudienceListMembersParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceServiceImpl.kt index 60ef4f0e..5988aa8c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AudienceServiceImpl.kt @@ -29,6 +29,7 @@ import com.courier.models.audiences.AudienceUpdateResponse import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Define filter-based groups whose membership Courier recalculates as user profiles change. */ class AudienceServiceImpl internal constructor(private val clientOptions: ClientOptions) : AudienceService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventService.kt index da38d7a5..e14eece4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventService.kt @@ -12,6 +12,7 @@ import com.courier.models.auditevents.AuditEventRetrieveParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Read the audit trail of configuration and access changes in your workspace. */ interface AuditEventService { /** @@ -26,7 +27,10 @@ interface AuditEventService { */ fun withOptions(modifier: Consumer): AuditEventService - /** Fetch a specific audit event by ID. */ + /** + * Returns one audit event by id, including the actor who performed it, the target they changed, + * the source, the event type, and a timestamp. + */ fun retrieve(auditEventId: String): AuditEvent = retrieve(auditEventId, AuditEventRetrieveParams.none()) @@ -57,7 +61,10 @@ interface AuditEventService { fun retrieve(auditEventId: String, requestOptions: RequestOptions): AuditEvent = retrieve(auditEventId, AuditEventRetrieveParams.none(), requestOptions) - /** Fetch the list of audit events */ + /** + * Returns the workspace's audit event log with cursor paging. Each event records the actor, + * target, source, type, and timestamp of a change. + */ fun list(): AuditEventListResponse = list(AuditEventListParams.none()) /** @see list */ diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventServiceImpl.kt index 25ffe78b..f4e14402 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuditEventServiceImpl.kt @@ -22,6 +22,7 @@ import com.courier.models.auditevents.AuditEventRetrieveParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Read the audit trail of configuration and access changes in your workspace. */ class AuditEventServiceImpl internal constructor(private val clientOptions: ClientOptions) : AuditEventService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthService.kt index 6f732da0..c62d3122 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthService.kt @@ -10,6 +10,11 @@ import com.courier.models.auth.AuthIssueTokenResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ interface AuthService { /** @@ -24,7 +29,10 @@ interface AuthService { */ fun withOptions(modifier: Consumer): AuthService - /** Returns a new access token. */ + /** + * Returns a JWT for authenticating client-side SDKs such as the Inbox. You supply the scope and + * an expires_in duration, both required. + */ fun issueToken(params: AuthIssueTokenParams): AuthIssueTokenResponse = issueToken(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthServiceImpl.kt index 5273cd94..76325ea7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AuthServiceImpl.kt @@ -19,6 +19,11 @@ import com.courier.models.auth.AuthIssueTokenParams import com.courier.models.auth.AuthIssueTokenResponse import java.util.function.Consumer +/** + * Issue scoped, short-lived JWTs so client-side SDKs — Inbox, Preferences, and the embedded + * designer — can call Courier as a single user. Server-side requests authenticate with your + * workspace API key instead. + */ class AuthServiceImpl internal constructor(private val clientOptions: ClientOptions) : AuthService { private val withRawResponse: AuthService.WithRawResponse by lazy { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationService.kt index 8c6bf97d..926c96ea 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationService.kt @@ -11,6 +11,7 @@ import com.courier.services.blocking.automations.InvokeService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ interface AutomationService { /** @@ -25,9 +26,13 @@ interface AutomationService { */ fun withOptions(modifier: Consumer): AutomationService + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun invoke(): InvokeService - /** Get the list of automations. */ + /** + * Lists the workspace's saved automation templates, each with its id and a cursor for paging to + * the next page of results. + */ fun list(): AutomationTemplateListResponse = list(AutomationListParams.none()) /** @see list */ @@ -57,6 +62,7 @@ interface AutomationService { modifier: Consumer ): AutomationService.WithRawResponse + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ fun invoke(): InvokeService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationServiceImpl.kt index bb8209a2..700ccec7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/AutomationServiceImpl.kt @@ -20,6 +20,7 @@ import com.courier.services.blocking.automations.InvokeService import com.courier.services.blocking.automations.InvokeServiceImpl import java.util.function.Consumer +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ class AutomationServiceImpl internal constructor(private val clientOptions: ClientOptions) : AutomationService { @@ -34,6 +35,7 @@ class AutomationServiceImpl internal constructor(private val clientOptions: Clie override fun withOptions(modifier: Consumer): AutomationService = AutomationServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun invoke(): InvokeService = invoke override fun list( @@ -60,6 +62,7 @@ class AutomationServiceImpl internal constructor(private val clientOptions: Clie clientOptions.toBuilder().apply(modifier::accept).build() ) + /** Invoke a stored automation template or an ad hoc automation defined in the request. */ override fun invoke(): InvokeService.WithRawResponse = invoke private val listHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandService.kt index 1200f4c1..60216e06 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandService.kt @@ -16,6 +16,7 @@ import com.courier.models.brands.BrandUpdateParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Manage the logos, colors, and layout that give the templates you send a consistent look. */ interface BrandService { /** @@ -31,8 +32,8 @@ interface BrandService { fun withOptions(modifier: Consumer): BrandService /** - * Create a new brand. Requires `name` and `settings` (with at least `colors.primary` and - * `colors.secondary`). + * Creates a brand from a name and settings, including primary and secondary colors. Brands + * supply the logo, colors, and styling that templates render with. */ fun create(params: BrandCreateParams): Brand = create(params, RequestOptions.none()) @@ -42,7 +43,10 @@ interface BrandService { requestOptions: RequestOptions = RequestOptions.none(), ): Brand - /** Fetch a specific brand by brand ID. */ + /** + * Returns one brand by id, including its colors, logo and styling settings, Handlebars + * snippets, and published version. + */ fun retrieve(brandId: String): Brand = retrieve(brandId, BrandRetrieveParams.none()) /** @see retrieve */ @@ -69,7 +73,10 @@ interface BrandService { fun retrieve(brandId: String, requestOptions: RequestOptions): Brand = retrieve(brandId, BrandRetrieveParams.none(), requestOptions) - /** Replace an existing brand with the supplied values. */ + /** + * Replaces a brand with the values you supply, so send the complete settings and snippets + * rather than only the fields you want changed. + */ fun update(brandId: String, params: BrandUpdateParams): Brand = update(brandId, params, RequestOptions.none()) @@ -89,7 +96,10 @@ interface BrandService { requestOptions: RequestOptions = RequestOptions.none(), ): Brand - /** Get the list of brands. */ + /** + * Lists the workspace's brands. Every entry carries its name, styling settings, snippets, and + * published version. + */ fun list(): BrandListResponse = list(BrandListParams.none()) /** @see list */ @@ -106,7 +116,10 @@ interface BrandService { fun list(requestOptions: RequestOptions): BrandListResponse = list(BrandListParams.none(), requestOptions) - /** Delete a brand by brand ID. */ + /** + * Deletes a brand by id. Reassign any template or tenant that references it before deleting to + * keep their styling intact. + */ fun delete(brandId: String) = delete(brandId, BrandDeleteParams.none()) /** @see delete */ diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandServiceImpl.kt index 1e6c8aa3..9881b7d3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/BrandServiceImpl.kt @@ -27,6 +27,7 @@ import com.courier.models.brands.BrandUpdateParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Manage the logos, colors, and layout that give the templates you send a consistent look. */ class BrandServiceImpl internal constructor(private val clientOptions: ClientOptions) : BrandService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt index c7ccda3f..868efaf3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestService.kt @@ -20,6 +20,10 @@ interface DigestService { */ fun withOptions(modifier: Consumer): DigestService + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ fun schedules(): ScheduleService /** A view of [DigestService] that provides access to raw HTTP responses for each method. */ @@ -32,6 +36,10 @@ interface DigestService { */ fun withOptions(modifier: Consumer): DigestService.WithRawResponse + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ fun schedules(): ScheduleService.WithRawResponse } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt index 9bc624d3..4cf6ea74 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/DigestServiceImpl.kt @@ -21,6 +21,10 @@ class DigestServiceImpl internal constructor(private val clientOptions: ClientOp override fun withOptions(modifier: Consumer): DigestService = DigestServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ override fun schedules(): ScheduleService = schedules class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -37,6 +41,10 @@ class DigestServiceImpl internal constructor(private val clientOptions: ClientOp clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ override fun schedules(): ScheduleService.WithRawResponse = schedules } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundService.kt index 664deb45..65482c61 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundService.kt @@ -10,6 +10,7 @@ import com.courier.models.inbound.InboundTrackEventResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Record an inbound event that triggers the journeys and automations mapped to it. */ interface InboundService { /** @@ -24,7 +25,10 @@ interface InboundService { */ fun withOptions(modifier: Consumer): InboundService - /** Courier Track Event */ + /** + * Records an inbound event that can trigger a journey. Requires an event name, a messageId you + * generate, a type, and a properties object. + */ fun trackEvent(params: InboundTrackEventParams): InboundTrackEventResponse = trackEvent(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundServiceImpl.kt index ef3cef26..b9baf52d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboundServiceImpl.kt @@ -19,6 +19,7 @@ import com.courier.models.inbound.InboundTrackEventParams import com.courier.models.inbound.InboundTrackEventResponse import java.util.function.Consumer +/** Record an inbound event that triggers the journeys and automations mapped to it. */ class InboundServiceImpl internal constructor(private val clientOptions: ClientOptions) : InboundService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboxService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboxService.kt new file mode 100644 index 00000000..c83883bb --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboxService.kt @@ -0,0 +1,39 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking + +import com.courier.core.ClientOptions +import com.courier.services.blocking.inbox.MessageService +import java.util.function.Consumer + +interface InboxService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): InboxService + + /** Manage the messages in a user's in-app inbox. */ + fun messages(): MessageService + + /** A view of [InboxService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): InboxService.WithRawResponse + + /** Manage the messages in a user's in-app inbox. */ + fun messages(): MessageService.WithRawResponse + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboxServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboxServiceImpl.kt new file mode 100644 index 00000000..670ae134 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/InboxServiceImpl.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking + +import com.courier.core.ClientOptions +import com.courier.services.blocking.inbox.MessageService +import com.courier.services.blocking.inbox.MessageServiceImpl +import java.util.function.Consumer + +class InboxServiceImpl internal constructor(private val clientOptions: ClientOptions) : + InboxService { + + private val withRawResponse: InboxService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val messages: MessageService by lazy { MessageServiceImpl(clientOptions) } + + override fun withRawResponse(): InboxService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): InboxService = + InboxServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + /** Manage the messages in a user's in-app inbox. */ + override fun messages(): MessageService = messages + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + InboxService.WithRawResponse { + + private val messages: MessageService.WithRawResponse by lazy { + MessageServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: Consumer + ): InboxService.WithRawResponse = + InboxServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + /** Manage the messages in a user's in-app inbox. */ + override fun messages(): MessageService.WithRawResponse = messages + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt index d70d5f95..42527ac7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt @@ -26,6 +26,10 @@ import com.courier.services.blocking.journeys.TemplateService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ interface JourneyService { /** @@ -40,14 +44,15 @@ interface JourneyService { */ fun withOptions(modifier: Consumer): JourneyService + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ fun templates(): TemplateService /** - * Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. - * Send nodes are not allowed on `POST`. The standard flow is: create the journey shell here, - * add notification templates with `POST /journeys/{templateId}/templates`, then wire them into - * the journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to - * publish a draft after the fact. + * Creates a journey from a set of nodes, in draft state unless you pass a published state. Send + * nodes cannot be included until their templates exist. */ fun create(params: JourneyCreateParams): JourneyResponse = create(params, RequestOptions.none()) @@ -105,7 +110,10 @@ interface JourneyService { fun retrieve(templateId: String, requestOptions: RequestOptions): JourneyResponse = retrieve(templateId, JourneyRetrieveParams.none(), requestOptions) - /** Get the list of journeys. */ + /** + * Lists the workspace's journeys, each carrying a name, state, and enabled flag. Paged by + * cursor. + */ fun list(): JourneysListResponse = list(JourneyListParams.none()) /** @see list */ @@ -123,8 +131,8 @@ interface JourneyService { list(JourneyListParams.none(), requestOptions) /** - * Archive a journey. Archived journeys cannot be invoked. Existing journey runs continue to - * completion. + * Archives a journey so it can no longer be invoked. Runs already in flight continue to + * completion, so archiving never strands a user mid-sequence. */ fun archive(templateId: String) = archive(templateId, JourneyArchiveParams.none()) @@ -153,12 +161,8 @@ interface JourneyService { archive(templateId, JourneyArchiveParams.none(), requestOptions) /** - * Cancel journey runs. The request body must include EXACTLY ONE of `cancelation_token` - * (cancels every run associated with the token) or `run_id` (cancels a single tenant-scoped - * run). Supplying both or neither returns a `400`. A `run_id` that does not match a run for the - * tenant returns `404`. Cancelation is idempotent: a run that has already finished - * (`PROCESSED`/`ERROR`) or was already `CANCELED` is left unchanged and its current status is - * returned. + * Cancels in-flight journey runs, either every run sharing a cancelation token or one run by + * id. Use it to stop a sequence when the event resolves. */ fun cancel(params: JourneyCancelParams): CancelJourneyResponse = cancel(params, RequestOptions.none()) @@ -205,8 +209,8 @@ interface JourneyService { cancel(byRunId, RequestOptions.none()) /** - * Invoke a journey by id or alias to start a new run. The response includes a `runId` - * identifying the run. + * Starts a journey run for one user and returns a runId. Runs execute asynchronously, so the + * response arrives before any message is sent. */ fun invoke(templateId: String, params: JourneyInvokeParams): JourneysInvokeResponse = invoke(templateId, params, RequestOptions.none()) @@ -229,7 +233,10 @@ interface JourneyService { requestOptions: RequestOptions = RequestOptions.none(), ): JourneysInvokeResponse - /** List published versions of a journey, ordered most recent first. */ + /** + * Lists a journey's published versions, most recent first, so you have a version id to roll + * back to. Paged by cursor. + */ fun listVersions(templateId: String): JourneyVersionsListResponse = listVersions(templateId, JourneyListVersionsParams.none()) @@ -265,8 +272,8 @@ interface JourneyService { listVersions(templateId, JourneyListVersionsParams.none(), requestOptions) /** - * Publish the current draft as a new version. Body is optional; pass `{ "version": "vN" }` to - * roll back to a prior version instead. Returns 404 if the journey has no draft to publish. + * Publishes a journey's current draft as a new version, making it live for new runs. Pass a + * version instead to roll back to an earlier one. */ fun publish(templateId: String): JourneyResponse = publish(templateId, JourneyPublishParams.none()) @@ -299,10 +306,8 @@ interface JourneyService { publish(templateId, JourneyPublishParams.none(), requestOptions) /** - * Replace the journey draft. Updates the working draft only; call `POST - * /journeys/{templateId}/publish` to make it live, or pass `state: "PUBLISHED"` in this request - * to publish immediately. Send-node `template` ids must already exist and be scoped to this - * journey, and node ids must not be claimed by another journey. + * Replaces a journey's working draft, leaving the published version live until you publish. + * Reach for this when editing a journey already running. */ fun replace(templateId: String, params: JourneyReplaceParams): JourneyResponse = replace(templateId, params, RequestOptions.none()) @@ -334,6 +339,10 @@ interface JourneyService { */ fun withOptions(modifier: Consumer): JourneyService.WithRawResponse + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ fun templates(): TemplateService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt index 52471954..45fd53c0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt @@ -36,6 +36,10 @@ import com.courier.services.blocking.journeys.TemplateServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ class JourneyServiceImpl internal constructor(private val clientOptions: ClientOptions) : JourneyService { @@ -50,6 +54,10 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO override fun withOptions(modifier: Consumer): JourneyService = JourneyServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ override fun templates(): TemplateService = templates override fun create( @@ -130,6 +138,10 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with + * the templates scoped to them. + */ override fun templates(): TemplateService.WithRawResponse = templates private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListService.kt index b5fd0e55..b59dbdcc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListService.kt @@ -17,6 +17,10 @@ import com.courier.services.blocking.lists.SubscriptionService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ interface ListService { /** @@ -31,9 +35,16 @@ interface ListService { */ fun withOptions(modifier: Consumer): ListService + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ fun subscriptions(): SubscriptionService - /** Returns a list based on the list ID provided. */ + /** + * Returns one list by id with its name and created and updated timestamps. Fetch its + * subscribers separately with the subscriptions endpoint. + */ fun retrieve(listId: String): SubscriptionList = retrieve(listId, ListRetrieveParams.none()) /** @see retrieve */ @@ -63,7 +74,10 @@ interface ListService { fun retrieve(listId: String, requestOptions: RequestOptions): SubscriptionList = retrieve(listId, ListRetrieveParams.none(), requestOptions) - /** Create or replace an existing list with the supplied values. */ + /** + * Creates or replaces a list from a name and preferences. Subscribers are managed through the + * separate subscriptions endpoints. + */ fun update(listId: String, params: ListUpdateParams) = update(listId, params, RequestOptions.none()) @@ -80,7 +94,10 @@ interface ListService { /** @see update */ fun update(params: ListUpdateParams, requestOptions: RequestOptions = RequestOptions.none()) - /** Returns all of the lists, with the ability to filter based on a pattern. */ + /** + * Returns the workspace's lists, filterable by a pattern to fetch a subset such as every + * regional list. Paged by cursor. + */ fun list(): ListListResponse = list(ListListParams.none()) /** @see list */ @@ -97,7 +114,10 @@ interface ListService { fun list(requestOptions: RequestOptions): ListListResponse = list(ListListParams.none(), requestOptions) - /** Delete a list by list ID. */ + /** + * Deletes a list, halting sends that target it. A previously deleted list can be brought back + * with the companion restore endpoint. + */ fun delete(listId: String) = delete(listId, ListDeleteParams.none()) /** @see delete */ @@ -121,7 +141,10 @@ interface ListService { fun delete(listId: String, requestOptions: RequestOptions) = delete(listId, ListDeleteParams.none(), requestOptions) - /** Restore a previously deleted list. */ + /** + * Restores a previously deleted list along with its subscribers, so a list removed by mistake + * can be brought back rather than rebuilt. + */ fun restore(listId: String, params: ListRestoreParams) = restore(listId, params, RequestOptions.none()) @@ -148,6 +171,10 @@ interface ListService { */ fun withOptions(modifier: Consumer): ListService.WithRawResponse + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ fun subscriptions(): SubscriptionService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListServiceImpl.kt index 1c3a0acb..6cafa827 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ListServiceImpl.kt @@ -29,6 +29,10 @@ import com.courier.services.blocking.lists.SubscriptionServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ class ListServiceImpl internal constructor(private val clientOptions: ClientOptions) : ListService { private val withRawResponse: ListService.WithRawResponse by lazy { @@ -44,6 +48,10 @@ class ListServiceImpl internal constructor(private val clientOptions: ClientOpti override fun withOptions(modifier: Consumer): ListService = ListServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or + * list pattern. + */ override fun subscriptions(): SubscriptionService = subscriptions override fun retrieve( @@ -89,6 +97,10 @@ class ListServiceImpl internal constructor(private val clientOptions: ClientOpti clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage static groups of users that you subscribe explicitly, and send to them by list id + * or list pattern. + */ override fun subscriptions(): SubscriptionService.WithRawResponse = subscriptions private val retrieveHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageService.kt index cefd97f3..dc52358c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageService.kt @@ -20,6 +20,10 @@ import com.courier.models.messages.MessageRetrieveResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ interface MessageService { /** @@ -34,7 +38,10 @@ interface MessageService { */ fun withOptions(modifier: Consumer): MessageService - /** Fetch the status of a message you've previously sent. */ + /** + * Returns a sent message's status, recipient, event, and per-provider delivery detail, with + * timestamps for enqueued, sent, delivered, opened, and clicked. + */ fun retrieve(messageId: String): MessageRetrieveResponse = retrieve(messageId, MessageRetrieveParams.none()) @@ -66,7 +73,10 @@ interface MessageService { fun retrieve(messageId: String, requestOptions: RequestOptions): MessageRetrieveResponse = retrieve(messageId, MessageRetrieveParams.none(), requestOptions) - /** Fetch the statuses of messages you've previously sent. */ + /** + * Returns previously sent messages, most recent first, each carrying its status, recipient, + * channel, and provider. Paged by cursor. + */ fun list(): MessageListResponse = list(MessageListParams.none()) /** @see list */ @@ -84,10 +94,8 @@ interface MessageService { list(MessageListParams.none(), requestOptions) /** - * Cancel a message that is currently in the process of being delivered. A well-formatted API - * call to the cancel message API will return either `200` status code for a successful - * cancellation or `409` status code for an unsuccessful cancellation. Both cases will include - * the actual message record in the response body (see details below). + * Cancels a message that is still in the delivery pipeline and returns the message record with + * its resulting canceled or failed status. */ fun cancel(messageId: String): MessageDetails = cancel(messageId, MessageCancelParams.none()) @@ -117,7 +125,10 @@ interface MessageService { fun cancel(messageId: String, requestOptions: RequestOptions): MessageDetails = cancel(messageId, MessageCancelParams.none(), requestOptions) - /** Get message content */ + /** + * Returns the rendered content Courier delivered for a message, broken out per channel, to + * confirm what the recipient received. + */ fun content(messageId: String): MessageContentResponse = content(messageId, MessageContentParams.none()) @@ -149,7 +160,10 @@ interface MessageService { fun content(messageId: String, requestOptions: RequestOptions): MessageContentResponse = content(messageId, MessageContentParams.none(), requestOptions) - /** Fetch the array of events of a message you've previously sent. */ + /** + * Returns the ordered event history for a sent message, one entry per status transition with + * its timestamp. + */ fun history(messageId: String): MessageHistoryResponse = history(messageId, MessageHistoryParams.none()) @@ -182,10 +196,8 @@ interface MessageService { history(messageId, MessageHistoryParams.none(), requestOptions) /** - * Resend a previously sent message. The original send request is loaded from storage and a - * brand-new send is enqueued for the same recipient and content, producing a **new** - * `messageId` — the original message is not modified. Throttled by a per-message rate limit; a - * repeat inside the limit window returns `429 Too Many Requests`. + * Resends a previously sent message to the same recipient and content, returning a new + * messageId. The original send request is not modified. */ fun resend(messageId: String): MessageResendResponse = resend(messageId, MessageResendParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageServiceImpl.kt index e57937f4..da4288be 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/MessageServiceImpl.kt @@ -31,6 +31,10 @@ import com.courier.models.messages.MessageRetrieveResponse import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ class MessageServiceImpl internal constructor(private val clientOptions: ClientOptions) : MessageService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt index 85f2a049..c4c3c1c4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationService.kt @@ -28,6 +28,7 @@ import com.courier.services.blocking.notifications.CheckService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Create, update, version, publish, and localize notification templates and their content. */ interface NotificationService { /** @@ -42,6 +43,7 @@ interface NotificationService { */ fun withOptions(modifier: Consumer): NotificationService + /** Create, update, version, publish, and localize notification templates and their content. */ fun checks(): CheckService /** @@ -109,7 +111,10 @@ interface NotificationService { fun retrieve(id: String, requestOptions: RequestOptions): NotificationTemplateResponse = retrieve(id, NotificationRetrieveParams.none(), requestOptions) - /** List notification templates in your workspace. */ + /** + * Lists the workspace's notification templates. Each carries a name, tags, brand, routing, and + * its draft or published state. + */ fun list(): NotificationListResponse = list(NotificationListParams.none()) /** @see list */ @@ -127,7 +132,10 @@ interface NotificationService { fun list(requestOptions: RequestOptions): NotificationListResponse = list(NotificationListParams.none(), requestOptions) - /** Archive a notification template. */ + /** + * Archives a notification template, preventing new sends from referencing it. The template + * stays retrievable for its version history. + */ fun archive(id: String) = archive(id, NotificationArchiveParams.none()) /** @see archive */ @@ -155,12 +163,8 @@ interface NotificationService { archive(id, NotificationArchiveParams.none(), requestOptions) /** - * Duplicate a notification template. Creates a standalone copy within the same workspace and - * environment, with " COPY" appended to the title. The copy clones the source draft's tags, - * brand, subscription topic, routing strategy, channels, and content, and is always created as - * a standalone template (it is not linked to any journey or broadcast, even if the source was). - * Templates that are scoped to a journey or a broadcast cannot be duplicated through this - * endpoint. + * Copies a notification template within the same workspace and environment, appending " COPY" + * to the title. The copy is standalone and independently editable. */ fun duplicate(id: String): NotificationTemplateResponse = duplicate(id, NotificationDuplicateParams.none()) @@ -192,7 +196,10 @@ interface NotificationService { fun duplicate(id: String, requestOptions: RequestOptions): NotificationTemplateResponse = duplicate(id, NotificationDuplicateParams.none(), requestOptions) - /** List versions of a notification template. */ + /** + * Returns a notification template's published versions, most recent first, for comparison or + * rollback. Paged. + */ fun listVersions(id: String): NotificationTemplateVersionListResponse = listVersions(id, NotificationListVersionsParams.none()) @@ -259,8 +266,8 @@ interface NotificationService { publish(id, NotificationPublishParams.none(), requestOptions) /** - * Replace the elemental content of a notification template. Overwrites all elements in the - * template with the provided content. Only supported for V2 (elemental) templates. + * Replaces all Elemental content in a template, overwriting every existing element. Supported + * for V2 templates only, not V1 blocks and channels. */ fun putContent( id: String, @@ -286,8 +293,8 @@ interface NotificationService { ): NotificationContentMutationResponse /** - * Update a single element within a notification template. Only supported for V2 (elemental) - * templates. + * Replaces one Elemental element in a template, addressed by its element id. Supported for V2 + * templates only, not V1 blocks and channels. */ fun putElement( elementId: String, @@ -313,8 +320,8 @@ interface NotificationService { ): NotificationContentMutationResponse /** - * Set locale-specific content overrides for a notification template. Each element override must - * reference an existing element by ID. Only supported for V2 (elemental) templates. + * Sets locale-specific content overrides for a template. Each override must reference an + * element that already exists in the default content. */ fun putLocale( localeId: String, @@ -339,7 +346,10 @@ interface NotificationService { requestOptions: RequestOptions = RequestOptions.none(), ): NotificationContentMutationResponse - /** Replace a notification template. All fields are required. */ + /** + * Replaces a notification template in full, so send every field rather than only the ones you + * want changed. Publish separately to make it live. + */ fun replace(id: String, params: NotificationReplaceParams): NotificationTemplateResponse = replace(id, params, RequestOptions.none()) @@ -361,9 +371,8 @@ interface NotificationService { ): NotificationTemplateResponse /** - * Retrieve the content of a notification template. The response shape depends on whether the - * template uses V1 (blocks/channels) or V2 (elemental) content. Use the `version` query - * parameter to select draft, published, or a specific historical version. + * Returns a template's content and checksum. V2 templates return Elemental elements, while V1 + * templates return blocks and channels instead. */ fun retrieveContent(id: String): NotificationRetrieveContentResponse = retrieveContent(id, NotificationRetrieveContentParams.none()) @@ -414,6 +423,9 @@ interface NotificationService { modifier: Consumer ): NotificationService.WithRawResponse + /** + * Create, update, version, publish, and localize notification templates and their content. + */ fun checks(): CheckService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt index 9b6d39da..29841e06 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/NotificationServiceImpl.kt @@ -39,6 +39,7 @@ import com.courier.services.blocking.notifications.CheckServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Create, update, version, publish, and localize notification templates and their content. */ class NotificationServiceImpl internal constructor(private val clientOptions: ClientOptions) : NotificationService { @@ -53,6 +54,7 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl override fun withOptions(modifier: Consumer): NotificationService = NotificationServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** Create, update, version, publish, and localize notification templates and their content. */ override fun checks(): CheckService = checks override fun create( @@ -152,6 +154,9 @@ class NotificationServiceImpl internal constructor(private val clientOptions: Cl clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Create, update, version, publish, and localize notification templates and their content. + */ override fun checks(): CheckService.WithRawResponse = checks private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileService.kt index 5b31ed8f..ebcd0900 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileService.kt @@ -18,6 +18,10 @@ import com.courier.services.blocking.profiles.ListService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ interface ProfileService { /** @@ -32,11 +36,15 @@ interface ProfileService { */ fun withOptions(modifier: Consumer): ProfileService + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ fun lists(): ListService /** - * Merge the supplied values with an existing profile or create a new profile if one doesn't - * already exist. + * Merges the supplied values into a user's profile, creating it if absent and leaving any key + * you omit untouched. Prefer this for everyday writes. */ fun create(userId: String, params: ProfileCreateParams): ProfileCreateResponse = create(userId, params, RequestOptions.none()) @@ -58,7 +66,10 @@ interface ProfileService { requestOptions: RequestOptions = RequestOptions.none(), ): ProfileCreateResponse - /** Returns the specified user profile. */ + /** + * Returns a user's stored profile and preferences, including the email address, phone number, + * and push tokens Courier can reach them on. + */ fun retrieve(userId: String): ProfileRetrieveResponse = retrieve(userId, ProfileRetrieveParams.none()) @@ -89,7 +100,10 @@ interface ProfileService { fun retrieve(userId: String, requestOptions: RequestOptions): ProfileRetrieveResponse = retrieve(userId, ProfileRetrieveParams.none(), requestOptions) - /** Update a profile */ + /** + * Applies a JSON Patch to a user profile, adding, removing, or replacing individual fields + * without sending the whole object. + */ fun update(userId: String, params: ProfileUpdateParams) = update(userId, params, RequestOptions.none()) @@ -106,7 +120,10 @@ interface ProfileService { /** @see update */ fun update(params: ProfileUpdateParams, requestOptions: RequestOptions = RequestOptions.none()) - /** Deletes the specified user profile. */ + /** + * Deletes a user's profile and stored contact details. List subscriptions and preferences are + * separate resources, so remove those too if required. + */ fun delete(userId: String) = delete(userId, ProfileDeleteParams.none()) /** @see delete */ @@ -131,11 +148,8 @@ interface ProfileService { delete(userId, ProfileDeleteParams.none(), requestOptions) /** - * When using `PUT`, be sure to include all the key-value pairs required by the recipient's - * profile. Any key-value pairs that exist in the profile but fail to be included in the `PUT` - * request will be removed from the profile. Remember, a `PUT` update is a full replacement of - * the data. For partial updates, use the - * [Patch](https://www.courier.com/docs/reference/profiles/patch/) request. + * Overwrites a user profile in full, removing any key absent from the request body. Use the + * patch endpoint when changing a single field. */ fun replace(userId: String, params: ProfileReplaceParams): ProfileReplaceResponse = replace(userId, params, RequestOptions.none()) @@ -167,6 +181,10 @@ interface ProfileService { */ fun withOptions(modifier: Consumer): ProfileService.WithRawResponse + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ fun lists(): ListService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileServiceImpl.kt index cdf52218..90312200 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProfileServiceImpl.kt @@ -30,6 +30,10 @@ import com.courier.services.blocking.profiles.ListServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ class ProfileServiceImpl internal constructor(private val clientOptions: ClientOptions) : ProfileService { @@ -44,6 +48,10 @@ class ProfileServiceImpl internal constructor(private val clientOptions: ClientO override fun withOptions(modifier: Consumer): ProfileService = ProfileServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ override fun lists(): ListService = lists override fun create( @@ -94,6 +102,10 @@ class ProfileServiceImpl internal constructor(private val clientOptions: ClientO clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Store the contact information Courier delivers to for each user — email, phone number, + * push tokens, and any custom data you send to. + */ override fun lists(): ListService.WithRawResponse = lists private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderService.kt index 77bd49e4..e622ecfa 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderService.kt @@ -17,6 +17,10 @@ import com.courier.services.blocking.providers.CatalogService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ interface ProviderService { /** @@ -31,11 +35,15 @@ interface ProviderService { */ fun withOptions(modifier: Consumer): ProviderService + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ fun catalog(): CatalogService /** - * Create a new provider configuration. The `provider` field must be a known Courier provider - * key (see catalog). + * Configures a provider integration from a Courier provider key and its settings. Check the + * catalog endpoint for the schema each provider expects. */ fun create(params: ProviderCreateParams): Provider = create(params, RequestOptions.none()) @@ -45,7 +53,10 @@ interface ProviderService { requestOptions: RequestOptions = RequestOptions.none(), ): Provider - /** Fetch a single provider configuration by ID. */ + /** + * Returns one configured provider by id, including its channel, provider key, alias, title, and + * current settings. + */ fun retrieve(id: String): Provider = retrieve(id, ProviderRetrieveParams.none()) /** @see retrieve */ @@ -75,10 +86,8 @@ interface ProviderService { retrieve(id, ProviderRetrieveParams.none(), requestOptions) /** - * Replace an existing provider configuration. The `provider` key is required and determines - * which provider-specific settings schema is applied. All other fields are optional — omitted - * fields are cleared from the stored configuration (this is a full replacement, not a partial - * merge). Changing the provider type for an existing configuration is not supported. + * Replaces a provider's configuration in full, clearing any field you omit rather than merging + * it. Send the complete settings object. */ fun update(id: String, params: ProviderUpdateParams): Provider = update(id, params, RequestOptions.none()) @@ -100,8 +109,8 @@ interface ProviderService { ): Provider /** - * List configured provider integrations for the current workspace. Supports cursor-based - * pagination. + * Lists the provider integrations configured in the workspace, one entry per channel and + * provider key with its alias and settings. */ fun list(): ProviderListResponse = list(ProviderListParams.none()) @@ -120,8 +129,8 @@ interface ProviderService { list(ProviderListParams.none(), requestOptions) /** - * Delete a provider configuration. Returns 409 if the provider is still referenced by routing - * or notifications. + * Deletes a provider configuration, which fails while routing strategies or templates still + * reference it. Update those references first. */ fun delete(id: String) = delete(id, ProviderDeleteParams.none()) @@ -156,6 +165,10 @@ interface ProviderService { */ fun withOptions(modifier: Consumer): ProviderService.WithRawResponse + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ fun catalog(): CatalogService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderServiceImpl.kt index 2022f3e4..07d5776b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/ProviderServiceImpl.kt @@ -29,6 +29,10 @@ import com.courier.services.blocking.providers.CatalogServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ class ProviderServiceImpl internal constructor(private val clientOptions: ClientOptions) : ProviderService { @@ -43,6 +47,10 @@ class ProviderServiceImpl internal constructor(private val clientOptions: Client override fun withOptions(modifier: Consumer): ProviderService = ProviderServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ override fun catalog(): CatalogService = catalog override fun create(params: ProviderCreateParams, requestOptions: RequestOptions): Provider = @@ -89,6 +97,10 @@ class ProviderServiceImpl internal constructor(private val clientOptions: Client clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Configure the channel providers Courier delivers through, and browse the provider types + * it supports. + */ override fun catalog(): CatalogService.WithRawResponse = catalog private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestService.kt index 080feee9..e797b4a6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestService.kt @@ -9,6 +9,10 @@ import com.courier.models.requests.RequestArchiveParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ interface RequestService { /** @@ -23,7 +27,10 @@ interface RequestService { */ fun withOptions(modifier: Consumer): RequestService - /** Archive message */ + /** + * Archives a send request by its request id. Use it to remove test sends or superseded requests + * from the message list without deleting them. + */ fun archive(requestId: String) = archive(requestId, RequestArchiveParams.none()) /** @see archive */ diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestServiceImpl.kt index c13cbb41..9cfad988 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RequestServiceImpl.kt @@ -19,6 +19,10 @@ import com.courier.models.requests.RequestArchiveParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Look up the messages Courier has accepted, inspect their delivery history and rendered output, + * and cancel, resend, or archive them. + */ class RequestServiceImpl internal constructor(private val clientOptions: ClientOptions) : RequestService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyService.kt index 3890fbb6..5a71d833 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyService.kt @@ -19,6 +19,7 @@ import com.courier.models.routingstrategies.RoutingStrategyRetrieveParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Define reusable channel routing and failover strategies, and see which templates use them. */ interface RoutingStrategyService { /** @@ -64,8 +65,8 @@ interface RoutingStrategyService { ): RoutingStrategyGetResponse = create(routingStrategyCreateRequest, RequestOptions.none()) /** - * Retrieve a routing strategy by ID. Returns the full entity including routing content and - * metadata. + * Returns one routing strategy by id with its name, tags, channels, and the routing rules that + * decide provider order and fallback. */ fun retrieve(id: String): RoutingStrategyGetResponse = retrieve(id, RoutingStrategyRetrieveParams.none()) @@ -151,8 +152,8 @@ interface RoutingStrategyService { archive(id, RoutingStrategyArchiveParams.none(), requestOptions) /** - * List notification templates associated with a routing strategy. Includes template metadata - * only, not full content. + * Returns the notification templates using a routing strategy, with paging. Check this before + * changing a strategy that templates depend on. */ fun listNotifications(id: String): AssociatedNotificationListResponse = listNotifications(id, RoutingStrategyListNotificationsParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyServiceImpl.kt index f8dc5a3d..af47b1d3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/RoutingStrategyServiceImpl.kt @@ -29,6 +29,7 @@ import com.courier.models.routingstrategies.RoutingStrategyRetrieveParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Define reusable channel routing and failover strategies, and see which templates use them. */ class RoutingStrategyServiceImpl internal constructor(private val clientOptions: ClientOptions) : RoutingStrategyService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendService.kt index 92f9b3ec..bb456577 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendService.kt @@ -10,6 +10,10 @@ import com.courier.models.send.SendMessageResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ interface SendService { /** @@ -24,7 +28,10 @@ interface SendService { */ fun withOptions(modifier: Consumer): SendService - /** Send a message to one or more recipients. */ + /** + * Sends a message to one or more recipients and returns a requestId. Courier routes it to + * email, SMS, push, chat, or in-app based on your rules. + */ fun message(params: SendMessageParams): SendMessageResponse = message(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendServiceImpl.kt index 577116b8..2044d961 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/SendServiceImpl.kt @@ -19,6 +19,10 @@ import com.courier.models.send.SendMessageParams import com.courier.models.send.SendMessageResponse import java.util.function.Consumer +/** + * Send a message to one or more recipients — users, lists, audiences, or tenants — across every + * channel you have configured. + */ class SendServiceImpl internal constructor(private val clientOptions: ClientOptions) : SendService { private val withRawResponse: SendService.WithRawResponse by lazy { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantService.kt index 2e5beb42..9d00608e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantService.kt @@ -19,6 +19,10 @@ import com.courier.services.blocking.tenants.TemplateService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ interface TenantService { /** @@ -35,9 +39,16 @@ interface TenantService { fun preferences(): PreferenceService + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun templates(): TemplateService - /** Get a Tenant */ + /** + * Returns one tenant with its name, parent tenant id, default preferences, properties, and the + * user profile applied to its members. + */ fun retrieve(tenantId: String): Tenant = retrieve(tenantId, TenantRetrieveParams.none()) /** @see retrieve */ @@ -66,7 +77,10 @@ interface TenantService { fun retrieve(tenantId: String, requestOptions: RequestOptions): Tenant = retrieve(tenantId, TenantRetrieveParams.none(), requestOptions) - /** Create or Replace a Tenant */ + /** + * Creates or replaces a tenant from a name, parent, brand, properties, and default preferences + * supplied in the request body. + */ fun update(tenantId: String, params: TenantUpdateParams): Tenant = update(tenantId, params, RequestOptions.none()) @@ -86,7 +100,10 @@ interface TenantService { requestOptions: RequestOptions = RequestOptions.none(), ): Tenant - /** Get a List of Tenants */ + /** + * Lists the workspace's tenants, each carrying a name, parent tenant, properties, and default + * preferences. Paged. + */ fun list(): TenantListResponse = list(TenantListParams.none()) /** @see list */ @@ -103,7 +120,10 @@ interface TenantService { fun list(requestOptions: RequestOptions): TenantListResponse = list(TenantListParams.none(), requestOptions) - /** Delete a Tenant */ + /** + * Deletes a tenant. Its members' workspace-level profiles and preferences live outside the + * tenant and are managed separately. + */ fun delete(tenantId: String) = delete(tenantId, TenantDeleteParams.none()) /** @see delete */ @@ -127,7 +147,10 @@ interface TenantService { fun delete(tenantId: String, requestOptions: RequestOptions) = delete(tenantId, TenantDeleteParams.none(), requestOptions) - /** Get Users in Tenant */ + /** + * Returns the users belonging to a tenant with cursor paging. Use it to see who a tenant-scoped + * send will reach. + */ fun listUsers(tenantId: String): TenantListUsersResponse = listUsers(tenantId, TenantListUsersParams.none()) @@ -171,6 +194,10 @@ interface TenantService { fun preferences(): PreferenceService.WithRawResponse + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun templates(): TemplateService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantServiceImpl.kt index f2f39451..e9b22455 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TenantServiceImpl.kt @@ -32,6 +32,10 @@ import com.courier.services.blocking.tenants.TemplateServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ class TenantServiceImpl internal constructor(private val clientOptions: ClientOptions) : TenantService { @@ -50,6 +54,10 @@ class TenantServiceImpl internal constructor(private val clientOptions: ClientOp override fun preferences(): PreferenceService = preferences + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun templates(): TemplateService = templates override fun retrieve(params: TenantRetrieveParams, requestOptions: RequestOptions): Tenant = @@ -102,6 +110,10 @@ class TenantServiceImpl internal constructor(private val clientOptions: ClientOp override fun preferences(): PreferenceService.WithRawResponse = preferences + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun templates(): TemplateService.WithRawResponse = templates private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationService.kt index 84676828..d6e9149a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationService.kt @@ -11,6 +11,7 @@ import com.courier.models.translations.TranslationUpdateParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Store and retrieve the translation strings Courier uses to render localized template content. */ interface TranslationService { /** @@ -25,7 +26,10 @@ interface TranslationService { */ fun withOptions(modifier: Consumer): TranslationService - /** Get translations by locale */ + /** + * Returns the translation strings stored for one domain and locale, for use in localized + * notification content. + */ fun retrieve(locale: String, params: TranslationRetrieveParams): String = retrieve(locale, params, RequestOptions.none()) @@ -46,7 +50,10 @@ interface TranslationService { requestOptions: RequestOptions = RequestOptions.none(), ): String - /** Update a translation */ + /** + * Uploads the translation strings for one domain and locale. Courier uses them to render + * localized content for recipients in that locale. + */ fun update(locale: String, params: TranslationUpdateParams) = update(locale, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationServiceImpl.kt index 3e824f41..265b063b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/TranslationServiceImpl.kt @@ -22,6 +22,7 @@ import com.courier.models.translations.TranslationUpdateParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Store and retrieve the translation strings Courier uses to render localized template content. */ class TranslationServiceImpl internal constructor(private val clientOptions: ClientOptions) : TranslationService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserService.kt index 2e262d7c..74a71261 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserService.kt @@ -22,10 +22,15 @@ interface UserService { */ fun withOptions(modifier: Consumer): UserService + /** Read and write a single user's notification preferences, per topic and per channel. */ fun preferences(): PreferenceService + /** Associate a user with one or more tenants, and read or remove those associations. */ fun tenants(): TenantService + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications to. + */ fun tokens(): TokenService /** A view of [UserService] that provides access to raw HTTP responses for each method. */ @@ -38,10 +43,16 @@ interface UserService { */ fun withOptions(modifier: Consumer): UserService.WithRawResponse + /** Read and write a single user's notification preferences, per topic and per channel. */ fun preferences(): PreferenceService.WithRawResponse + /** Associate a user with one or more tenants, and read or remove those associations. */ fun tenants(): TenantService.WithRawResponse + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications + * to. + */ fun tokens(): TokenService.WithRawResponse } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserServiceImpl.kt index 4dcbac0f..c7eb5c33 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/UserServiceImpl.kt @@ -28,10 +28,15 @@ class UserServiceImpl internal constructor(private val clientOptions: ClientOpti override fun withOptions(modifier: Consumer): UserService = UserServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** Read and write a single user's notification preferences, per topic and per channel. */ override fun preferences(): PreferenceService = preferences + /** Associate a user with one or more tenants, and read or remove those associations. */ override fun tenants(): TenantService = tenants + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications to. + */ override fun tokens(): TokenService = tokens class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -56,10 +61,16 @@ class UserServiceImpl internal constructor(private val clientOptions: ClientOpti clientOptions.toBuilder().apply(modifier::accept).build() ) + /** Read and write a single user's notification preferences, per topic and per channel. */ override fun preferences(): PreferenceService.WithRawResponse = preferences + /** Associate a user with one or more tenants, and read or remove those associations. */ override fun tenants(): TenantService.WithRawResponse = tenants + /** + * Register and manage the APNS and FCM device tokens Courier delivers push notifications + * to. + */ override fun tokens(): TokenService.WithRawResponse = tokens } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceService.kt index 49915266..dcbd7872 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceService.kt @@ -21,6 +21,10 @@ import com.courier.services.blocking.workspacepreferences.TopicService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ interface WorkspacePreferenceService { /** @@ -35,11 +39,15 @@ interface WorkspacePreferenceService { */ fun withOptions(modifier: Consumer): WorkspacePreferenceService + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun topics(): TopicService /** - * Create a workspace preference. The workspace preference id is generated and returned. Topics - * are created inside a workspace preference via POST /preferences/sections/{section_id}/topics. + * Creates a workspace preference and returns its generated id. Add subscription topics to it + * afterwards with the topics endpoint. */ fun create(params: WorkspacePreferenceCreateParams): WorkspacePreferenceGetResponse = create(params, RequestOptions.none()) @@ -68,7 +76,10 @@ interface WorkspacePreferenceService { ): WorkspacePreferenceGetResponse = create(workspacePreferenceCreateRequest, RequestOptions.none()) - /** Retrieve a workspace preference by id, including its topics. */ + /** + * Returns one workspace preference by id, including its subscription topics, routing options, + * and custom routing flag. + */ fun retrieve(sectionId: String): WorkspacePreferenceGetResponse = retrieve(sectionId, WorkspacePreferenceRetrieveParams.none()) @@ -104,8 +115,8 @@ interface WorkspacePreferenceService { retrieve(sectionId, WorkspacePreferenceRetrieveParams.none(), requestOptions) /** - * List the workspace's preferences. Each workspace preference embeds its topics. Scoped to the - * workspace of the API key. + * Returns the workspace's preferences, each embedding its subscription topics, routing options, + * and whether custom routing is allowed. */ fun list(): WorkspacePreferenceListResponse = list(WorkspacePreferenceListParams.none()) @@ -157,9 +168,8 @@ interface WorkspacePreferenceService { archive(sectionId, WorkspacePreferenceArchiveParams.none(), requestOptions) /** - * Publish the workspace's preferences page. Takes a snapshot of every workspace preference with - * its topics under a new published version, making the current state visible on the hosted - * preferences page (non-draft). + * Publishes the workspace preference page, snapshotting every preference and topic, and returns + * the page id and a preview URL. */ fun publish(): PublishPreferencesResponse = publish(WorkspacePreferencePublishParams.none()) @@ -236,6 +246,10 @@ interface WorkspacePreferenceService { modifier: Consumer ): WorkspacePreferenceService.WithRawResponse + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ fun topics(): TopicService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceImpl.kt index d08ce1c1..952deedf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceImpl.kt @@ -31,6 +31,10 @@ import com.courier.services.blocking.workspacepreferences.TopicServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ class WorkspacePreferenceServiceImpl internal constructor(private val clientOptions: ClientOptions) : WorkspacePreferenceService { @@ -47,6 +51,10 @@ internal constructor(private val clientOptions: ClientOptions) : WorkspacePrefer ): WorkspacePreferenceService = WorkspacePreferenceServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun topics(): TopicService = topics override fun create( @@ -106,6 +114,10 @@ internal constructor(private val clientOptions: ClientOptions) : WorkspacePrefer clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage the workspace catalog of subscription topics, the sections that group them, and + * publishing the preference page. + */ override fun topics(): TopicService.WithRawResponse = topics private val createHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeService.kt index 88196cae..161e0549 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeService.kt @@ -11,6 +11,7 @@ import com.courier.models.automations.invoke.InvokeInvokeByTemplateParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ interface InvokeService { /** @@ -26,9 +27,8 @@ interface InvokeService { fun withOptions(modifier: Consumer): InvokeService /** - * Invoke an ad hoc automation run. This endpoint accepts a JSON payload with a series of - * automation steps. For information about what steps are available, checkout the ad hoc - * automation guide [here](https://www.courier.com/docs/automations/steps/). + * Runs a series of automation steps supplied inline, without a saved template, and returns a + * runId. */ fun invokeAdHoc(params: InvokeInvokeAdHocParams): AutomationInvokeResponse = invokeAdHoc(params, RequestOptions.none()) @@ -39,7 +39,10 @@ interface InvokeService { requestOptions: RequestOptions = RequestOptions.none(), ): AutomationInvokeResponse - /** Invoke an automation run from an automation template. */ + /** + * Starts an automation run from a saved template for one recipient, with optional data and + * profile, and returns a runId. + */ fun invokeByTemplate( templateId: String, params: InvokeInvokeByTemplateParams, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeServiceImpl.kt index 00dc2d0b..5ce6ac84 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/automations/InvokeServiceImpl.kt @@ -22,6 +22,7 @@ import com.courier.models.automations.invoke.InvokeInvokeByTemplateParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Invoke a stored automation template or an ad hoc automation defined in the request. */ class InvokeServiceImpl internal constructor(private val clientOptions: ClientOptions) : InvokeService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt index 5774cb32..d6523015 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleService.kt @@ -12,6 +12,10 @@ import com.courier.models.digests.schedules.ScheduleReleaseParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ interface ScheduleService { /** @@ -27,9 +31,8 @@ interface ScheduleService { fun withOptions(modifier: Consumer): ScheduleService /** - * List the digest instances for a schedule. Each instance represents the events accumulated for - * a single user against the schedule, and can be used to monitor digest accumulation before the - * digest is released. + * Returns the digest instances for a schedule, one per user, with cursor paging. Use it to see + * what has accumulated before a digest releases. */ fun listInstances(scheduleId: String): DigestInstanceListResponse = listInstances(scheduleId, ScheduleListInstancesParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt index 346dde55..261b07ad 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/digests/ScheduleServiceImpl.kt @@ -23,6 +23,10 @@ import com.courier.models.digests.schedules.ScheduleReleaseParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Inspect what has accumulated in a digest schedule and release a digest ahead of its next + * scheduled delivery. + */ class ScheduleServiceImpl internal constructor(private val clientOptions: ClientOptions) : ScheduleService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/inbox/MessageService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/inbox/MessageService.kt new file mode 100644 index 00000000..607fd59d --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/inbox/MessageService.kt @@ -0,0 +1,152 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.inbox + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse +import com.courier.models.inbox.messages.MessageDeleteParams +import com.courier.models.inbox.messages.MessageRestoreParams +import com.google.errorprone.annotations.MustBeClosed +import java.util.function.Consumer + +/** Manage the messages in a user's in-app inbox. */ +interface MessageService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MessageService + + /** + * Delete a user's inbox message. The message is removed from every inbox read (it stops + * appearing in the recipient's Inbox); it can be restored. + */ + fun delete(messageId: String) = delete(messageId, MessageDeleteParams.none()) + + /** @see delete */ + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see delete */ + fun delete(messageId: String, params: MessageDeleteParams = MessageDeleteParams.none()) = + delete(messageId, params, RequestOptions.none()) + + /** @see delete */ + fun delete(params: MessageDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(params: MessageDeleteParams) = delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete(messageId: String, requestOptions: RequestOptions) = + delete(messageId, MessageDeleteParams.none(), requestOptions) + + /** Restore a previously deleted inbox message. */ + fun restore(messageId: String, params: MessageRestoreParams) = + restore(messageId, params, RequestOptions.none()) + + /** @see restore */ + fun restore( + messageId: String, + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) = restore(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see restore */ + fun restore(params: MessageRestoreParams) = restore(params, RequestOptions.none()) + + /** @see restore */ + fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** A view of [MessageService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): MessageService.WithRawResponse + + /** + * Returns a raw HTTP response for `delete /inbox/messages/{message_id}`, but is otherwise + * the same as [MessageService.delete]. + */ + @MustBeClosed + fun delete(messageId: String): HttpResponse = delete(messageId, MessageDeleteParams.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + messageId: String, + params: MessageDeleteParams = MessageDeleteParams.none(), + ): HttpResponse = delete(messageId, params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + params: MessageDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(params: MessageDeleteParams): HttpResponse = + delete(params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete(messageId: String, requestOptions: RequestOptions): HttpResponse = + delete(messageId, MessageDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /inbox/messages/{message_id}/restore`, but is + * otherwise the same as [MessageService.restore]. + */ + @MustBeClosed + fun restore(messageId: String, params: MessageRestoreParams): HttpResponse = + restore(messageId, params, RequestOptions.none()) + + /** @see restore */ + @MustBeClosed + fun restore( + messageId: String, + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = restore(params.toBuilder().messageId(messageId).build(), requestOptions) + + /** @see restore */ + @MustBeClosed + fun restore(params: MessageRestoreParams): HttpResponse = + restore(params, RequestOptions.none()) + + /** @see restore */ + @MustBeClosed + fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/inbox/MessageServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/inbox/MessageServiceImpl.kt new file mode 100644 index 00000000..422d8229 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/inbox/MessageServiceImpl.kt @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.inbox + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler +import com.courier.core.handlers.errorBodyHandler +import com.courier.core.handlers.errorHandler +import com.courier.core.http.HttpMethod +import com.courier.core.http.HttpRequest +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponse.Handler +import com.courier.core.http.json +import com.courier.core.http.parseable +import com.courier.core.prepare +import com.courier.models.inbox.messages.MessageDeleteParams +import com.courier.models.inbox.messages.MessageRestoreParams +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +/** Manage the messages in a user's in-app inbox. */ +class MessageServiceImpl internal constructor(private val clientOptions: ClientOptions) : + MessageService { + + private val withRawResponse: MessageService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): MessageService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): MessageService = + MessageServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun delete(params: MessageDeleteParams, requestOptions: RequestOptions) { + // delete /inbox/messages/{message_id} + withRawResponse().delete(params, requestOptions) + } + + override fun restore(params: MessageRestoreParams, requestOptions: RequestOptions) { + // put /inbox/messages/{message_id}/restore + withRawResponse().restore(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + MessageService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): MessageService.WithRawResponse = + MessageServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: MessageDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("messageId", params.messageId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("inbox", "messages", params._pathParam(0)) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val restoreHandler: Handler = emptyHandler() + + override fun restore( + params: MessageRestoreParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("messageId", params.messageId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("inbox", "messages", params._pathParam(0), "restore") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { restoreHandler.handle(it) } + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt index e943ff65..c7357522 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt @@ -24,6 +24,10 @@ import com.courier.models.notifications.NotificationTemplateVersionListResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ interface TemplateService { /** @@ -64,8 +68,8 @@ interface TemplateService { ): JourneyTemplateGetResponse /** - * Fetch a journey-scoped notification template by id. Pass `?version=draft` (default - * `published`) to retrieve the working draft, or `?version=vN` for a historical version. + * Returns a journey's own notification template with its name, brand, subscription topic, and + * content. Defaults to the published version. */ fun retrieve( notificationId: String, @@ -125,7 +129,10 @@ interface TemplateService { fun list(templateId: String, requestOptions: RequestOptions): JourneyTemplateListResponse = list(templateId, TemplateListParams.none(), requestOptions) - /** Archive the journey-scoped notification template. Archived templates cannot be sent. */ + /** + * Archives one journey's notification template, preventing further sends. Detach any send node + * referencing it beforehand. + */ fun archive(notificationId: String, params: TemplateArchiveParams) = archive(notificationId, params, RequestOptions.none()) @@ -146,8 +153,8 @@ interface TemplateService { ) /** - * List published versions of the journey-scoped notification template, ordered most recent - * first. + * Lists the published versions of a template that belongs to a journey, most recent first. + * Paged by cursor. */ fun listVersions( notificationId: String, @@ -174,8 +181,8 @@ interface TemplateService { ): NotificationTemplateVersionListResponse /** - * Publish the current draft of the journey-scoped notification template as a new version. - * Optionally roll back to a prior version by passing `{ "version": "vN" }`. + * Publishes a journey-scoped template's draft as a new version. Pass a version instead to roll + * back the template to an earlier publish. */ fun publish(notificationId: String, params: TemplatePublishParams) = publish(notificationId, params, RequestOptions.none()) @@ -251,7 +258,10 @@ interface TemplateService { requestOptions: RequestOptions = RequestOptions.none(), ): NotificationContentMutationResponse - /** Replace the journey-scoped notification template draft. */ + /** + * Replaces the draft content of one journey's notification template. Publish it before send + * nodes referencing it render the change. + */ fun replace(notificationId: String, params: TemplateReplaceParams): JourneyTemplateGetResponse = replace(notificationId, params, RequestOptions.none()) @@ -274,10 +284,8 @@ interface TemplateService { ): JourneyTemplateGetResponse /** - * Retrieve the elemental content of a journey-scoped notification template. The response - * contains the versioned elements along with their content checksums, which can be used to - * detect changes between versions. Pass `?version=draft` (default `published`) to retrieve the - * working draft, or `?version=vN` for a historical version. + * Returns the Elemental elements and version of a journey-scoped template's content. Compare + * versions to see what changed between publishes. */ fun retrieveContent( notificationId: String, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt index 0d1be5ff..f4a47b79 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt @@ -35,6 +35,10 @@ import com.courier.models.notifications.NotificationTemplateVersionListResponse import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Build, version, publish, invoke, and cancel multi-step notification workflows, along with the + * templates scoped to them. + */ class TemplateServiceImpl internal constructor(private val clientOptions: ClientOptions) : TemplateService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionService.kt index 0cbaec9f..dd9da2ac 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionService.kt @@ -15,6 +15,10 @@ import com.courier.models.lists.subscriptions.SubscriptionUnsubscribeUserParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ interface SubscriptionService { /** @@ -29,7 +33,10 @@ interface SubscriptionService { */ fun withOptions(modifier: Consumer): SubscriptionService - /** Get the list's subscriptions. */ + /** + * Returns the users subscribed to a list with paging, each with the preferences recorded for + * that subscription. + */ fun list(listId: String): SubscriptionListResponse = list(listId, SubscriptionListParams.none()) /** @see list */ @@ -103,8 +110,8 @@ interface SubscriptionService { ) /** - * Subscribe a user to an existing list (note: if the List does not exist, it will be - * automatically created). + * Subscribes one user to a list, creating the list if it does not yet exist. Optional + * preferences apply to this subscription only. */ fun subscribeUser(userId: String, params: SubscriptionSubscribeUserParams) = subscribeUser(userId, params, RequestOptions.none()) @@ -126,7 +133,10 @@ interface SubscriptionService { requestOptions: RequestOptions = RequestOptions.none(), ) - /** Delete a subscription to a list by list ID and user ID. */ + /** + * Removes one user's subscription to a list, addressed by list id and user id. The user's + * profile and other subscriptions are separate resources. + */ fun unsubscribeUser(userId: String, params: SubscriptionUnsubscribeUserParams) = unsubscribeUser(userId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionServiceImpl.kt index 8f766b7a..ab4e5f5c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/lists/SubscriptionServiceImpl.kt @@ -26,6 +26,10 @@ import com.courier.models.lists.subscriptions.SubscriptionUnsubscribeUserParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage static groups of users that you subscribe explicitly, and send to them by list id or list + * pattern. + */ class SubscriptionServiceImpl internal constructor(private val clientOptions: ClientOptions) : SubscriptionService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt index 279716be..ff7721b8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckService.kt @@ -14,6 +14,7 @@ import com.courier.models.notifications.checks.CheckUpdateResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Create, update, version, publish, and localize notification templates and their content. */ interface CheckService { /** @@ -28,7 +29,10 @@ interface CheckService { */ fun withOptions(modifier: Consumer): CheckService - /** Replace the submission checks for a notification template. */ + /** + * Replaces the approval checks on a template submission with the complete set supplied in the + * request body. + */ fun update(submissionId: String, params: CheckUpdateParams): CheckUpdateResponse = update(submissionId, params, RequestOptions.none()) @@ -50,7 +54,10 @@ interface CheckService { requestOptions: RequestOptions = RequestOptions.none(), ): CheckUpdateResponse - /** Retrieve the submission checks for a notification template. */ + /** + * Returns the approval checks recorded for a template submission, each with its pass or fail + * result. + */ fun list(submissionId: String, params: CheckListParams): CheckListResponse = list(submissionId, params, RequestOptions.none()) @@ -71,7 +78,10 @@ interface CheckService { requestOptions: RequestOptions = RequestOptions.none(), ): CheckListResponse - /** Cancel a submission for a notification template. */ + /** + * Cancels a pending template submission, withdrawing it from the approval workflow. The + * template stays in draft and can be resubmitted later. + */ fun delete(submissionId: String, params: CheckDeleteParams) = delete(submissionId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckServiceImpl.kt index 1f5f182d..e0b847c2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/notifications/CheckServiceImpl.kt @@ -25,6 +25,7 @@ import com.courier.models.notifications.checks.CheckUpdateResponse import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Create, update, version, publish, and localize notification templates and their content. */ class CheckServiceImpl internal constructor(private val clientOptions: ClientOptions) : CheckService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListService.kt index 895f377a..5d206c0e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListService.kt @@ -14,6 +14,10 @@ import com.courier.models.profiles.lists.ListSubscribeResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ interface ListService { /** @@ -28,7 +32,10 @@ interface ListService { */ fun withOptions(modifier: Consumer): ListService - /** Returns the subscribed lists for a specified user. */ + /** + * Returns the lists a user is subscribed to, with paging. Use it to check what a recipient will + * receive before sending to a list. + */ fun retrieve(userId: String): ListRetrieveResponse = retrieve(userId, ListRetrieveParams.none()) /** @see retrieve */ @@ -58,7 +65,10 @@ interface ListService { fun retrieve(userId: String, requestOptions: RequestOptions): ListRetrieveResponse = retrieve(userId, ListRetrieveParams.none(), requestOptions) - /** Removes all list subscriptions for given user. */ + /** + * Removes every list subscription for a user at once. Their profile and preferences are + * untouched, so this only affects list-targeted sends. + */ fun delete(userId: String): ListDeleteResponse = delete(userId, ListDeleteParams.none()) /** @see delete */ @@ -88,8 +98,8 @@ interface ListService { delete(userId, ListDeleteParams.none(), requestOptions) /** - * Subscribes the given user to one or more lists. If the list does not exist, it will be - * created. + * Subscribes a user to one or more lists, creating any list that does not yet exist. Optional + * preferences apply to each subscription. */ fun subscribe(userId: String, params: ListSubscribeParams): ListSubscribeResponse = subscribe(userId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListServiceImpl.kt index ef235a6c..9476a644 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/profiles/ListServiceImpl.kt @@ -25,6 +25,10 @@ import com.courier.models.profiles.lists.ListSubscribeResponse import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Store the contact information Courier delivers to for each user — email, phone number, push + * tokens, and any custom data you send to. + */ class ListServiceImpl internal constructor(private val clientOptions: ClientOptions) : ListService { private val withRawResponse: ListService.WithRawResponse by lazy { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogService.kt index 79a3deef..cac74233 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogService.kt @@ -10,6 +10,10 @@ import com.courier.models.providers.catalog.CatalogListResponse import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ interface CatalogService { /** @@ -25,9 +29,8 @@ interface CatalogService { fun withOptions(modifier: Consumer): CatalogService /** - * Returns the catalog of available provider types with their display names, descriptions, and - * configuration schema fields (snake_case, with `type` and `required`). Providers with no - * configurable schema return only `provider`, `name`, and `description`. + * Returns the provider types Courier supports, each with a display name, description, and the + * configuration fields it requires. */ fun list(): CatalogListResponse = list(CatalogListParams.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogServiceImpl.kt index b6379458..38300a35 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/providers/CatalogServiceImpl.kt @@ -18,6 +18,10 @@ import com.courier.models.providers.catalog.CatalogListParams import com.courier.models.providers.catalog.CatalogListResponse import java.util.function.Consumer +/** + * Configure the channel providers Courier delivers through, and browse the provider types it + * supports. + */ class CatalogServiceImpl internal constructor(private val clientOptions: ClientOptions) : CatalogService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceService.kt index 185a456a..dea81295 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceService.kt @@ -20,6 +20,10 @@ interface PreferenceService { */ fun withOptions(modifier: Consumer): PreferenceService + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun items(): ItemService /** A view of [PreferenceService] that provides access to raw HTTP responses for each method. */ @@ -34,6 +38,10 @@ interface PreferenceService { modifier: Consumer ): PreferenceService.WithRawResponse + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ fun items(): ItemService.WithRawResponse } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceServiceImpl.kt index 0aa99273..10aa3a1e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/PreferenceServiceImpl.kt @@ -21,6 +21,10 @@ class PreferenceServiceImpl internal constructor(private val clientOptions: Clie override fun withOptions(modifier: Consumer): PreferenceService = PreferenceServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun items(): ItemService = items class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : @@ -37,6 +41,10 @@ class PreferenceServiceImpl internal constructor(private val clientOptions: Clie clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with + * their users and default preferences. + */ override fun items(): ItemService.WithRawResponse = items } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt index e5174142..c4474f16 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt @@ -19,6 +19,10 @@ import com.courier.services.blocking.tenants.templates.VersionService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ interface TemplateService { /** @@ -33,9 +37,16 @@ interface TemplateService { */ fun withOptions(modifier: Consumer): TemplateService + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun versions(): VersionService - /** Get a Template in Tenant */ + /** + * Returns a tenant's notification template with its content, version, and created, updated, and + * published timestamps. + */ fun retrieve( templateId: String, params: TemplateRetrieveParams, @@ -59,7 +70,10 @@ interface TemplateService { requestOptions: RequestOptions = RequestOptions.none(), ): BaseTemplateTenantAssociation - /** List Templates in Tenant */ + /** + * Lists a tenant's notification templates, each carrying its version and published timestamp. + * Paged. + */ fun list(tenantId: String): TemplateListResponse = list(tenantId, TemplateListParams.none()) /** @see list */ @@ -89,12 +103,8 @@ interface TemplateService { list(tenantId, TemplateListParams.none(), requestOptions) /** - * Deletes the tenant's notification template with the given `template_id`. - * - * Returns **204 No Content** with an empty body on success. - * - * Returns **404** if there is no template with this ID for the tenant, including a second - * `DELETE` after a successful removal. + * Deletes a tenant's notification template by id. Sends for that tenant then use the workspace + * template registered under the same id. */ fun delete(templateId: String, params: TemplateDeleteParams) = delete(templateId, params, RequestOptions.none()) @@ -113,10 +123,8 @@ interface TemplateService { fun delete(params: TemplateDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) /** - * Publishes a specific version of a notification template for a tenant. - * - * The template must already exist in the tenant's notification map. If no version is specified, - * defaults to publishing the "latest" version. + * Publishes a version of a tenant's notification template, making it the content that tenant's + * sends render from until you publish another. */ fun publish( templateId: String, @@ -142,12 +150,8 @@ interface TemplateService { ): PostTenantTemplatePublishResponse /** - * Creates or updates a notification template for a tenant. - * - * If the template already exists for the tenant, it will be updated (200). Otherwise, a new - * template is created (201). - * - * Optionally publishes the template immediately if the `published` flag is set to true. + * Creates or updates a notification template scoped to one tenant, letting a tenant override + * the content the workspace template would send. */ fun replace(templateId: String, params: TemplateReplaceParams): PutTenantTemplateResponse = replace(templateId, params, RequestOptions.none()) @@ -180,6 +184,10 @@ interface TemplateService { */ fun withOptions(modifier: Consumer): TemplateService.WithRawResponse + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ fun versions(): VersionService.WithRawResponse /** diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt index 261e3622..c3ae73d2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt @@ -31,6 +31,10 @@ import com.courier.services.blocking.tenants.templates.VersionServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ class TemplateServiceImpl internal constructor(private val clientOptions: ClientOptions) : TemplateService { @@ -45,6 +49,10 @@ class TemplateServiceImpl internal constructor(private val clientOptions: Client override fun withOptions(modifier: Consumer): TemplateService = TemplateServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun versions(): VersionService = versions override fun retrieve( @@ -97,6 +105,10 @@ class TemplateServiceImpl internal constructor(private val clientOptions: Client clientOptions.toBuilder().apply(modifier::accept).build() ) + /** + * Manage the templates and template versions scoped to a single tenant, including the ones + * authored in the embedded designer. + */ override fun versions(): VersionService.WithRawResponse = versions private val retrieveHandler: Handler = diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemService.kt index 4691b482..46f3c8f1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemService.kt @@ -10,6 +10,10 @@ import com.courier.models.tenants.preferences.items.ItemUpdateParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ interface ItemService { /** @@ -24,7 +28,10 @@ interface ItemService { */ fun withOptions(modifier: Consumer): ItemService - /** Create or Replace Default Preferences For Topic */ + /** + * Sets a tenant's default opt-in status for one subscription topic, which applies to every + * member unless a user sets their own override. + */ fun update(topicId: String, params: ItemUpdateParams) = update(topicId, params, RequestOptions.none()) @@ -41,7 +48,10 @@ interface ItemService { /** @see update */ fun update(params: ItemUpdateParams, requestOptions: RequestOptions = RequestOptions.none()) - /** Remove Default Preferences For Topic */ + /** + * Removes a tenant's default preference for one subscription topic, addressed by tenant id and + * topic id. + */ fun delete(topicId: String, params: ItemDeleteParams) = delete(topicId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemServiceImpl.kt index e2de2d66..8f11a388 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/preferences/ItemServiceImpl.kt @@ -20,6 +20,10 @@ import com.courier.models.tenants.preferences.items.ItemUpdateParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage tenants — the organizations, teams, or accounts your users belong to — along with their + * users and default preferences. + */ class ItemServiceImpl internal constructor(private val clientOptions: ClientOptions) : ItemService { private val withRawResponse: ItemService.WithRawResponse by lazy { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionService.kt index bd8e9493..6f1b02fe 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionService.kt @@ -10,6 +10,10 @@ import com.courier.models.tenants.templates.versions.VersionRetrieveParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ interface VersionService { /** @@ -25,12 +29,8 @@ interface VersionService { fun withOptions(modifier: Consumer): VersionService /** - * Fetches a specific version of a tenant template. - * - * Supports the following version formats: - * - `latest` - The most recent version of the template - * - `published` - The currently published version - * - `v{version}` - A specific version (e.g., "v1", "v2", "v1.0.0") + * Returns one version of a tenant template, addressed by version number or by latest, with its + * content and publish timestamp. */ fun retrieve(version: String, params: VersionRetrieveParams): BaseTemplateTenantAssociation = retrieve(version, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionServiceImpl.kt index e972beab..683ebd19 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/templates/VersionServiceImpl.kt @@ -20,6 +20,10 @@ import com.courier.models.tenants.templates.versions.VersionRetrieveParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the templates and template versions scoped to a single tenant, including the ones authored + * in the embedded designer. + */ class VersionServiceImpl internal constructor(private val clientOptions: ClientOptions) : VersionService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceService.kt index 79034d92..8b611715 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceService.kt @@ -20,6 +20,7 @@ import com.courier.models.users.preferences.PreferenceUpdateOrCreateTopicRespons import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Read and write a single user's notification preferences, per topic and per channel. */ interface PreferenceService { /** @@ -34,7 +35,10 @@ interface PreferenceService { */ fun withOptions(modifier: Consumer): PreferenceService - /** Fetch all user preferences. */ + /** + * Returns a user's preference overrides with paging, one entry per subscription topic they have + * set a choice for. + */ fun retrieve(userId: String): PreferenceRetrieveResponse = retrieve(userId, PreferenceRetrieveParams.none()) @@ -67,21 +71,8 @@ interface PreferenceService { retrieve(userId, PreferenceRetrieveParams.none(), requestOptions) /** - * Replace a user's complete set of preference overrides in a single request. The topics in the - * request body become the recipient's entire set of overrides: listed topics are created or - * updated, and every existing override that is not included in the body is reset to its topic - * default. Submitting an empty `topics` array is a valid clear-all that resets every existing - * override. - * - * This operation is validation-atomic (all-or-nothing): structural validation fails fast with a - * single `400`, and if any topic is semantically invalid (an unknown topic, a `REQUIRED` topic - * that cannot be opted out, or a custom routing request that is not available on the - * workspace's plan) the request returns a single `400` aggregating every failure in `errors` - * and writes nothing. On success it returns `200` with `items` (the complete resulting override - * set) and `deleted` (the ids of the overrides that were reset to default). - * - * Every `topic_id` in the response — in `items`, `deleted`, and any `errors` — is returned in - * Courier's canonical topic id form, regardless of the form supplied in the request. + * Replaces a user's entire set of preference overrides. Any topic you leave out is reset to its + * default, so send the full set rather than a subset. */ fun bulkReplace( userId: String, @@ -107,20 +98,8 @@ interface PreferenceService { ): PreferenceBulkReplaceResponse /** - * Additively create or update a user's preferences for one or more subscription topics in a - * single request. Only the topics included in the request body are created or updated; any - * existing overrides for topics not listed are left untouched. - * - * Structural validation of the request body fails fast with a single `400`. Beyond that, each - * topic is processed independently (partial-success, not all-or-nothing): valid topics are - * written and returned in `items`, while topics that cannot be applied are collected in - * `errors` with a per-topic `reason` (for example an unknown topic, a `REQUIRED` topic that - * cannot be opted out, a custom routing request that is not available on the workspace's plan, - * or a write failure). The request therefore returns `200` with both lists whenever the body is - * structurally valid. - * - * Every `topic_id` in the response — in both `items` and `errors` — is returned in Courier's - * canonical topic id form, regardless of the form supplied in the request. + * Adds or updates a user's preferences for several subscription topics at once. Topics you + * leave out keep whatever they were set to before. */ fun bulkUpdate( userId: String, @@ -146,9 +125,8 @@ interface PreferenceService { ): PreferenceBulkUpdateResponse /** - * Remove a user's preferences for a specific subscription topic, resetting the topic to its - * effective default. This operation is idempotent: deleting a preference that does not exist - * succeeds with no error. + * Removes a user's override for one subscription topic, resetting it to the effective default + * from the tenant or workspace. */ fun deleteTopic(topicId: String, params: PreferenceDeleteTopicParams) = deleteTopic(topicId, params, RequestOptions.none()) @@ -170,7 +148,10 @@ interface PreferenceService { requestOptions: RequestOptions = RequestOptions.none(), ) - /** Fetch user preferences for a specific subscription topic. */ + /** + * Returns a user's opt-in status and channel choices for one subscription topic, or the + * effective default if they have set no override. + */ fun retrieveTopic( topicId: String, params: PreferenceRetrieveTopicParams, @@ -194,7 +175,10 @@ interface PreferenceService { requestOptions: RequestOptions = RequestOptions.none(), ): PreferenceRetrieveTopicResponse - /** Update or Create user preferences for a specific subscription topic. */ + /** + * Sets a user's opt-in status and channel choices for one subscription topic, overriding the + * tenant default for that topic only. + */ fun updateOrCreateTopic( topicId: String, params: PreferenceUpdateOrCreateTopicParams, diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceServiceImpl.kt index 862cd0ff..ed229210 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/PreferenceServiceImpl.kt @@ -31,6 +31,7 @@ import com.courier.models.users.preferences.PreferenceUpdateOrCreateTopicRespons import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Read and write a single user's notification preferences, per topic and per channel. */ class PreferenceServiceImpl internal constructor(private val clientOptions: ClientOptions) : PreferenceService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantService.kt index 36782f1e..23646c39 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantService.kt @@ -15,6 +15,7 @@ import com.courier.models.users.tenants.TenantRemoveSingleParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Associate a user with one or more tenants, and read or remove those associations. */ interface TenantService { /** @@ -29,7 +30,10 @@ interface TenantService { */ fun withOptions(modifier: Consumer): TenantService - /** Returns a paginated list of user tenant associations. */ + /** + * Returns the tenants a user belongs to, with cursor paging. A user can belong to many tenants, + * each with its own profile and preferences. + */ fun list(userId: String): TenantListResponse = list(userId, TenantListParams.none()) /** @see list */ @@ -59,9 +63,8 @@ interface TenantService { list(userId, TenantListParams.none(), requestOptions) /** - * This endpoint is used to add a user to multiple tenants in one call. A custom profile can - * also be supplied for each tenant. This profile will be merged with the user's main profile - * when sending to the user with that tenant. + * Adds a user to several tenants in one call, each optionally with a per-tenant profile that + * overrides their workspace profile. */ fun addMultiple(userId: String, params: TenantAddMultipleParams) = addMultiple(userId, params, RequestOptions.none()) @@ -83,10 +86,8 @@ interface TenantService { ) /** - * This endpoint is used to add a single tenant. - * - * A custom profile can also be supplied with the tenant. This profile will be merged with the - * user's main profile when sending to the user with that tenant. + * Adds a user to one tenant, optionally with a tenant-specific profile that overrides their + * workspace profile for sends in that tenant. */ fun addSingle(tenantId: String, params: TenantAddSingleParams) = addSingle(tenantId, params, RequestOptions.none()) @@ -107,7 +108,10 @@ interface TenantService { requestOptions: RequestOptions = RequestOptions.none(), ) - /** Removes a user from any tenants they may have been associated with. */ + /** + * Removes a user from every tenant they belong to in one call. Their workspace-level profile is + * a separate resource. + */ fun removeAll(userId: String) = removeAll(userId, TenantRemoveAllParams.none()) /** @see removeAll */ @@ -134,7 +138,10 @@ interface TenantService { fun removeAll(userId: String, requestOptions: RequestOptions) = removeAll(userId, TenantRemoveAllParams.none(), requestOptions) - /** Removes a user from the supplied tenant. */ + /** + * Removes a user from one tenant. Their other tenant memberships and workspace profile are + * managed through separate endpoints. + */ fun removeSingle(tenantId: String, params: TenantRemoveSingleParams) = removeSingle(tenantId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantServiceImpl.kt index 1b119f22..781e8809 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TenantServiceImpl.kt @@ -26,6 +26,7 @@ import com.courier.models.users.tenants.TenantRemoveSingleParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Associate a user with one or more tenants, and read or remove those associations. */ class TenantServiceImpl internal constructor(private val clientOptions: ClientOptions) : TenantService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenService.kt index 22130973..068f0009 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenService.kt @@ -17,6 +17,7 @@ import com.courier.models.users.tokens.TokenUpdateParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** Register and manage the APNS and FCM device tokens Courier delivers push notifications to. */ interface TokenService { /** @@ -31,7 +32,10 @@ interface TokenService { */ fun withOptions(modifier: Consumer): TokenService - /** Get single token available for a `:token` */ + /** + * Returns one device token with its provider key, status and status reason, expiry date, and + * any properties stored alongside it. + */ fun retrieve(token: String, params: TokenRetrieveParams): TokenRetrieveResponse = retrieve(token, params, RequestOptions.none()) @@ -52,7 +56,10 @@ interface TokenService { requestOptions: RequestOptions = RequestOptions.none(), ): TokenRetrieveResponse - /** Apply a JSON Patch (RFC 6902) to the specified token. */ + /** + * Applies a JSON Patch to a device token, changing its status, expiry, or properties without + * re-registering it. + */ fun update(token: String, params: TokenUpdateParams) = update(token, params, RequestOptions.none()) @@ -69,7 +76,10 @@ interface TokenService { /** @see update */ fun update(params: TokenUpdateParams, requestOptions: RequestOptions = RequestOptions.none()) - /** Gets all tokens available for a :user_id */ + /** + * Returns every device token registered for a user, each with its provider key, status, and + * expiry date. + */ fun list(userId: String): TokenListResponse = list(userId, TokenListParams.none()) /** @see list */ @@ -96,7 +106,10 @@ interface TokenService { fun list(userId: String, requestOptions: RequestOptions): TokenListResponse = list(userId, TokenListParams.none(), requestOptions) - /** Delete User Token */ + /** + * Deletes one device token for a user, addressed by the token value, so push sends no longer + * target that device. + */ fun delete(token: String, params: TokenDeleteParams) = delete(token, params, RequestOptions.none()) @@ -113,7 +126,10 @@ interface TokenService { /** @see delete */ fun delete(params: TokenDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) - /** Adds multiple tokens to a user and overwrites matching existing tokens. */ + /** + * Registers several device tokens for a user in one call, overwriting any stored token with a + * matching value. + */ fun addMultiple(userId: String) = addMultiple(userId, TokenAddMultipleParams.none()) /** @see addMultiple */ @@ -142,7 +158,10 @@ interface TokenService { fun addMultiple(userId: String, requestOptions: RequestOptions) = addMultiple(userId, TokenAddMultipleParams.none(), requestOptions) - /** Adds a single token to a user and overwrites a matching existing token. */ + /** + * Registers one device token for a user against a provider key, overwriting the token if it + * already exists. Push sends resolve tokens per user. + */ fun addSingle(token: String, params: TokenAddSingleParams) = addSingle(token, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenServiceImpl.kt index 3ba3d017..bfaa441d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/users/TokenServiceImpl.kt @@ -28,6 +28,7 @@ import com.courier.models.users.tokens.TokenUpdateParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** Register and manage the APNS and FCM device tokens Courier delivers push notifications to. */ class TokenServiceImpl internal constructor(private val clientOptions: ClientOptions) : TokenService { diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicService.kt index b90d7c55..9246b3b6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicService.kt @@ -16,6 +16,10 @@ import com.courier.models.workspacepreferences.topics.TopicRetrieveParams import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ interface TopicService { /** @@ -31,8 +35,8 @@ interface TopicService { fun withOptions(modifier: Consumer): TopicService /** - * Create a subscription preference topic inside a workspace preference. Fails with 404 if the - * workspace preference does not exist. The topic id is generated and returned. + * Creates a subscription topic inside a workspace preference. The default status sets whether + * users start opted in, opted out, or required. */ fun create(sectionId: String, params: TopicCreateParams): WorkspacePreferenceTopicGetResponse = create(sectionId, params, RequestOptions.none()) @@ -56,9 +60,8 @@ interface TopicService { ): WorkspacePreferenceTopicGetResponse /** - * Retrieve a topic within a workspace preference. Returns 404 if the workspace preference does - * not exist, the topic does not exist, or the topic belongs to a different workspace - * preference. + * Returns one subscription topic with its default status, routing options, allowed preferences, + * and unsubscribe header setting. */ fun retrieve( topicId: String, @@ -83,7 +86,10 @@ interface TopicService { requestOptions: RequestOptions = RequestOptions.none(), ): WorkspacePreferenceTopicGetResponse - /** List the topics in a workspace preference. */ + /** + * Returns the subscription topics inside a workspace preference, each with its default status + * and routing options. + */ fun list(sectionId: String): WorkspacePreferenceTopicListResponse = list(sectionId, TopicListParams.none()) @@ -118,7 +124,10 @@ interface TopicService { ): WorkspacePreferenceTopicListResponse = list(sectionId, TopicListParams.none(), requestOptions) - /** Archive a topic and remove it from its workspace preference. Same 404 rules as GET. */ + /** + * Archives a subscription topic and removes it from its workspace preference, addressed by + * section id and topic id. + */ fun archive(topicId: String, params: TopicArchiveParams) = archive(topicId, params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceImpl.kt index 5acd30eb..6eda6242 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceImpl.kt @@ -27,6 +27,10 @@ import com.courier.models.workspacepreferences.topics.TopicRetrieveParams import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull +/** + * Manage the workspace catalog of subscription topics, the sections that group them, and publishing + * the preference page. + */ class TopicServiceImpl internal constructor(private val clientOptions: ClientOptions) : TopicService { diff --git a/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParamsTest.kt index 0cf862d9..01f07d8f 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.automations.invoke import com.courier.core.JsonValue +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -11,6 +12,8 @@ internal class InvokeInvokeAdHocParamsTest { @Test fun create() { InvokeInvokeAdHocParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .automation( InvokeInvokeAdHocParams.Automation.builder() .addStep( @@ -65,10 +68,118 @@ internal class InvokeInvokeAdHocParamsTest { .build() } + @Test + fun headers() { + val params = + InvokeInvokeAdHocParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .automation( + InvokeInvokeAdHocParams.Automation.builder() + .addStep( + InvokeInvokeAdHocParams.Automation.Step.AutomationDelayStep.builder() + .action( + InvokeInvokeAdHocParams.Automation.Step.AutomationDelayStep + .Action + .DELAY + ) + .duration("duration") + .until("20240408T080910.123") + .build() + ) + .addStep( + InvokeInvokeAdHocParams.Automation.Step.AutomationSendStep.builder() + .action( + InvokeInvokeAdHocParams.Automation.Step.AutomationSendStep + .Action + .SEND + ) + .brand("brand") + .data( + InvokeInvokeAdHocParams.Automation.Step.AutomationSendStep.Data + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .profile( + InvokeInvokeAdHocParams.Automation.Step.AutomationSendStep + .Profile + .builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .recipient("recipient") + .template("64TP5HKPFTM8VTK1Y75SJDQX9JK0") + .build() + ) + .cancelationToken("delay-send--user-yes--abc-123") + .build() + ) + .brand("brand") + .data( + InvokeInvokeAdHocParams.Data.builder() + .putAdditionalProperty("name", JsonValue.from("bar")) + .build() + ) + .profile( + InvokeInvokeAdHocParams.Profile.builder() + .putAdditionalProperty("tenant_id", JsonValue.from("bar")) + .build() + ) + .recipient("user-yes") + .template("template") + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + InvokeInvokeAdHocParams.builder() + .automation( + InvokeInvokeAdHocParams.Automation.builder() + .addStep( + InvokeInvokeAdHocParams.Automation.Step.AutomationDelayStep.builder() + .action( + InvokeInvokeAdHocParams.Automation.Step.AutomationDelayStep + .Action + .DELAY + ) + .build() + ) + .addStep( + InvokeInvokeAdHocParams.Automation.Step.AutomationSendStep.builder() + .action( + InvokeInvokeAdHocParams.Automation.Step.AutomationSendStep + .Action + .SEND + ) + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = InvokeInvokeAdHocParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .automation( InvokeInvokeAdHocParams.Automation.builder() .addStep( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParamsTest.kt index dc2b417a..f313a97c 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.automations.invoke import com.courier.core.JsonValue +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,6 +13,8 @@ internal class InvokeInvokeByTemplateParamsTest { fun create() { InvokeInvokeByTemplateParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .recipient("recipient") .brand("brand") .data( @@ -41,11 +44,59 @@ internal class InvokeInvokeByTemplateParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + InvokeInvokeByTemplateParams.builder() + .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .recipient("recipient") + .brand("brand") + .data( + InvokeInvokeByTemplateParams.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .profile( + InvokeInvokeByTemplateParams.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .template("template") + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + InvokeInvokeByTemplateParams.builder() + .templateId("templateId") + .recipient("recipient") + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = InvokeInvokeByTemplateParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .recipient("recipient") .brand("brand") .data( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/brands/BrandCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/brands/BrandCreateParamsTest.kt index bd3db269..5e303868 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/brands/BrandCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/brands/BrandCreateParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.brands +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -10,6 +11,8 @@ internal class BrandCreateParamsTest { @Test fun create() { BrandCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .name("My Brand") .settings( BrandSettings.builder() @@ -90,10 +93,126 @@ internal class BrandCreateParamsTest { .build() } + @Test + fun headers() { + val params = + BrandCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .name("My Brand") + .settings( + BrandSettings.builder() + .colors( + BrandColors.builder().primary("#9D3789").secondary("#FFFFFF").build() + ) + .email( + BrandSettingsEmail.builder() + .footer( + EmailFooter.builder() + .content("content") + .inheritDefault(true) + .build() + ) + .head( + EmailHead.builder() + .inheritDefault(true) + .content("content") + .build() + ) + .header( + EmailHeader.builder() + .logo(Logo.builder().href("href").image("image").build()) + .barColor("barColor") + .inheritDefault(true) + .build() + ) + .templateOverride( + BrandSettingsEmail.TemplateOverride.builder() + .enabled(true) + .backgroundColor("backgroundColor") + .blocksBackgroundColor("blocksBackgroundColor") + .footer("footer") + .head("head") + .header("header") + .width("width") + .mjml( + BrandTemplate.builder() + .enabled(true) + .backgroundColor("backgroundColor") + .blocksBackgroundColor("blocksBackgroundColor") + .footer("footer") + .head("head") + .header("header") + .width("width") + .build() + ) + .footerBackgroundColor("footerBackgroundColor") + .footerFullWidth(true) + .build() + ) + .build() + ) + .inapp( + BrandSettingsInApp.builder() + .colors( + BrandColors.builder() + .primary("primary") + .secondary("secondary") + .build() + ) + .icons(Icons.builder().bell("bell").message("message").build()) + .widgetBackground( + WidgetBackground.builder() + .bottomColor("bottomColor") + .topColor("topColor") + .build() + ) + .borderRadius("borderRadius") + .disableMessageIcon(true) + .fontFamily("fontFamily") + .placement(BrandSettingsInApp.Placement.TOP) + .build() + ) + .build() + ) + .id("id") + .snippets( + BrandSnippets.builder() + .addItem(BrandSnippet.builder().name("name").value("value").build()) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + BrandCreateParams.builder() + .name("My Brand") + .settings(BrandSettings.builder().build()) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = BrandCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .name("My Brand") .settings( BrandSettings.builder() diff --git a/courier-java-core/src/test/kotlin/com/courier/models/inbox/messages/MessageDeleteParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/inbox/messages/MessageDeleteParamsTest.kt new file mode 100644 index 00000000..7858a6a3 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/inbox/messages/MessageDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.inbox.messages + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class MessageDeleteParamsTest { + + @Test + fun create() { + MessageDeleteParams.builder().messageId("message_id").build() + } + + @Test + fun pathParams() { + val params = MessageDeleteParams.builder().messageId("message_id").build() + + assertThat(params._pathParam(0)).isEqualTo("message_id") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/inbox/messages/MessageRestoreParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/inbox/messages/MessageRestoreParamsTest.kt new file mode 100644 index 00000000..3dc903d7 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/inbox/messages/MessageRestoreParamsTest.kt @@ -0,0 +1,44 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.inbox.messages + +import com.courier.core.JsonValue +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class MessageRestoreParamsTest { + + @Test + fun create() { + MessageRestoreParams.builder() + .messageId("message_id") + .body(JsonValue.from(mapOf())) + .build() + } + + @Test + fun pathParams() { + val params = + MessageRestoreParams.builder() + .messageId("message_id") + .body(JsonValue.from(mapOf())) + .build() + + assertThat(params._pathParam(0)).isEqualTo("message_id") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + MessageRestoreParams.builder() + .messageId("message_id") + .body(JsonValue.from(mapOf())) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(JsonValue.from(mapOf())) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCancelParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCancelParamsTest.kt index edb7b0c0..61ed8992 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCancelParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCancelParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.journeys +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -10,6 +11,8 @@ internal class JourneyCancelParamsTest { @Test fun create() { JourneyCancelParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .cancelJourneyRequest( CancelJourneyRequest.ByCancelationToken.builder() .cancelationToken("order-1234") @@ -18,8 +21,73 @@ internal class JourneyCancelParamsTest { .build() } + @Test + fun headers() { + val params = + JourneyCancelParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .cancelJourneyRequest( + CancelJourneyRequest.ByCancelationToken.builder() + .cancelationToken("order-1234") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + JourneyCancelParams.builder() + .cancelJourneyRequest( + CancelJourneyRequest.ByCancelationToken.builder() + .cancelationToken("order-1234") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { + val params = + JourneyCancelParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .cancelJourneyRequest( + CancelJourneyRequest.ByCancelationToken.builder() + .cancelationToken("order-1234") + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + CancelJourneyRequest.ofByCancelationToken( + CancelJourneyRequest.ByCancelationToken.builder() + .cancelationToken("order-1234") + .build() + ) + ) + } + + @Test + fun bodyWithoutOptionalFields() { val params = JourneyCancelParams.builder() .cancelJourneyRequest( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt index af849ba6..2390c4e3 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.journeys import com.courier.core.JsonValue +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -11,6 +12,8 @@ internal class JourneyCreateParamsTest { @Test fun create() { JourneyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .createJourneyRequest( CreateJourneyRequest.builder() .name("Welcome Journey") @@ -47,10 +50,92 @@ internal class JourneyCreateParamsTest { .build() } + @Test + fun headers() { + val params = + JourneyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + JourneyCreateParams.builder() + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = JourneyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .createJourneyRequest( CreateJourneyRequest.builder() .name("Welcome Journey") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyInvokeParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyInvokeParamsTest.kt index 1b4b5bcc..3fa85431 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyInvokeParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyInvokeParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.journeys import com.courier.core.JsonValue +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,6 +13,8 @@ internal class JourneyInvokeParamsTest { fun create() { JourneyInvokeParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeysInvokeRequest( JourneysInvokeRequest.builder() .data( @@ -44,11 +47,62 @@ internal class JourneyInvokeParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + JourneyInvokeParams.builder() + .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .journeysInvokeRequest( + JourneysInvokeRequest.builder() + .data( + JourneysInvokeRequest.Data.builder() + .putAdditionalProperty("order_id", JsonValue.from("bar")) + .putAdditionalProperty("amount", JsonValue.from("bar")) + .build() + ) + .profile( + JourneysInvokeRequest.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .userId("user-123") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + JourneyInvokeParams.builder() + .templateId("templateId") + .journeysInvokeRequest(JourneysInvokeRequest.builder().build()) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = JourneyInvokeParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeysInvokeRequest( JourneysInvokeRequest.builder() .data( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt index 722aef4e..9dec496a 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.journeys +import com.courier.core.http.Headers import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,6 +13,8 @@ internal class JourneyPublishParamsTest { fun create() { JourneyPublishParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyPublishRequest(JourneyPublishRequest.builder().version("v321669910225").build()) .build() } @@ -25,11 +28,45 @@ internal class JourneyPublishParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + JourneyPublishParams.builder() + .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .journeyPublishRequest( + JourneyPublishRequest.builder().version("v321669910225").build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = JourneyPublishParams.builder().templateId("x").build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = JourneyPublishParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyPublishRequest( JourneyPublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt index cb39db3e..a9cdf663 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.journeys.templates +import com.courier.core.http.Headers import com.courier.models.ElementalTextNodeWithType import com.courier.models.journeys.JourneyTemplateCreateRequest import org.assertj.core.api.Assertions.assertThat @@ -13,6 +14,8 @@ internal class TemplateCreateParamsTest { fun create() { TemplateCreateParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplateCreateRequest( JourneyTemplateCreateRequest.builder() .channel("email") @@ -103,11 +106,121 @@ internal class TemplateCreateParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + TemplateCreateParams.builder() + .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = TemplateCreateParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplateCreateRequest( JourneyTemplateCreateRequest.builder() .channel("email") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt index b7917c8c..5f754c52 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.journeys.templates +import com.courier.core.http.Headers import com.courier.models.journeys.JourneyTemplatePublishRequest import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat @@ -14,6 +15,8 @@ internal class TemplatePublishParamsTest { TemplatePublishParams.builder() .templateId("x") .notificationId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplatePublishRequest( JourneyTemplatePublishRequest.builder().version("v321669910225").build() ) @@ -30,12 +33,47 @@ internal class TemplatePublishParamsTest { assertThat(params._pathParam(2)).isEqualTo("") } + @Test + fun headers() { + val params = + TemplatePublishParams.builder() + .templateId("x") + .notificationId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .journeyTemplatePublishRequest( + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = TemplatePublishParams.builder().templateId("x").notificationId("x").build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = TemplatePublishParams.builder() .templateId("x") .notificationId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplatePublishRequest( JourneyTemplatePublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParamsTest.kt index 2d3d1db8..f7a61a1b 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.lists.subscriptions import com.courier.core.JsonValue +import com.courier.core.http.Headers import com.courier.models.RecipientPreferences import com.courier.models.lists.PutSubscriptionsRecipient import org.assertj.core.api.Assertions.assertThat @@ -14,6 +15,8 @@ internal class SubscriptionAddParamsTest { fun create() { SubscriptionAddParams.builder() .listId("list_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addRecipient( PutSubscriptionsRecipient.builder() .recipientId("recipientId") @@ -83,11 +86,103 @@ internal class SubscriptionAddParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + SubscriptionAddParams.builder() + .listId("list_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .addRecipient( + PutSubscriptionsRecipient.builder() + .recipientId("recipientId") + .preferences( + RecipientPreferences.builder() + .categories( + RecipientPreferences.Categories.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "status" to "OPTED_IN", + "channel_preferences" to + listOf( + mapOf("channel" to "direct_message") + ), + "rules" to + listOf( + mapOf( + "until" to "until", + "start" to "start", + ) + ), + ) + ), + ) + .build() + ) + .notifications( + RecipientPreferences.Notifications.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "status" to "OPTED_IN", + "channel_preferences" to + listOf( + mapOf("channel" to "direct_message") + ), + "rules" to + listOf( + mapOf( + "until" to "until", + "start" to "start", + ) + ), + ) + ), + ) + .build() + ) + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + SubscriptionAddParams.builder() + .listId("list_id") + .addRecipient( + PutSubscriptionsRecipient.builder().recipientId("recipientId").build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = SubscriptionAddParams.builder() .listId("list_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addRecipient( PutSubscriptionsRecipient.builder() .recipientId("recipientId") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationCreateParamsTest.kt index bfdcf9a0..b4011724 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationCreateParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.notifications +import com.courier.core.http.Headers import com.courier.models.ElementalChannelNodeWithType import com.courier.models.ElementalContent import com.courier.models.ElementalTextNodeWithType @@ -13,6 +14,8 @@ internal class NotificationCreateParamsTest { @Test fun create() { NotificationCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .notificationTemplateCreateRequest( NotificationTemplateCreateRequest.builder() .notification( @@ -53,10 +56,111 @@ internal class NotificationCreateParamsTest { .build() } + @Test + fun headers() { + val params = + NotificationCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .notificationTemplateCreateRequest( + NotificationTemplateCreateRequest.builder() + .notification( + NotificationTemplatePayload.builder() + .brand( + NotificationTemplatePayload.Brand.builder() + .id("bnd_01kx4mrd0pfzw8wt7pn7p2fzag") + .build() + ) + .content( + ElementalContent.builder() + .addElement( + ElementalChannelNodeWithType.builder() + .type(ElementalChannelNodeWithType.Type.CHANNEL) + .build() + ) + .version("2022-01-01") + .build() + ) + .name("Welcome Email") + .routing( + NotificationTemplatePayload.Routing.builder() + .strategyId("rs_01kx4h2jdafq8bk9amzvy6hbv0") + .build() + ) + .subscription( + NotificationTemplatePayload.Subscription.builder() + .topicId("pt_01kx4h2jdafq8bk9a26x0kvd1t") + .build() + ) + .addTag("onboarding") + .addTag("welcome") + .build() + ) + .state(NotificationTemplateCreateRequest.State.DRAFT) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + NotificationCreateParams.builder() + .notificationTemplateCreateRequest( + NotificationTemplateCreateRequest.builder() + .notification( + NotificationTemplatePayload.builder() + .brand( + NotificationTemplatePayload.Brand.builder() + .id("bnd_01kx4mrd0pfzw8wt7pn7p2fzag") + .build() + ) + .content( + ElementalContent.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version("2022-01-01") + .build() + ) + .name("Welcome Email") + .routing( + NotificationTemplatePayload.Routing.builder() + .strategyId("rs_01kx4h2jdafq8bk9amzvy6hbv0") + .build() + ) + .subscription( + NotificationTemplatePayload.Subscription.builder() + .topicId("pt_01kx4h2jdafq8bk9a26x0kvd1t") + .build() + ) + .addTag("onboarding") + .addTag("welcome") + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = NotificationCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .notificationTemplateCreateRequest( NotificationTemplateCreateRequest.builder() .notification( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationPublishParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationPublishParamsTest.kt index c093a673..64e3c824 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationPublishParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/notifications/NotificationPublishParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.notifications +import com.courier.core.http.Headers import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,6 +13,8 @@ internal class NotificationPublishParamsTest { fun create() { NotificationPublishParams.builder() .id("id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .notificationTemplatePublishRequest( NotificationTemplatePublishRequest.builder().version("v321669910225").build() ) @@ -27,11 +30,45 @@ internal class NotificationPublishParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + NotificationPublishParams.builder() + .id("id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .notificationTemplatePublishRequest( + NotificationTemplatePublishRequest.builder().version("v321669910225").build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = NotificationPublishParams.builder().id("id").build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = NotificationPublishParams.builder() .id("id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .notificationTemplatePublishRequest( NotificationTemplatePublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/profiles/ProfileCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/profiles/ProfileCreateParamsTest.kt index 8a977510..91c2d4df 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/profiles/ProfileCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/profiles/ProfileCreateParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.profiles import com.courier.core.JsonValue +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,6 +13,8 @@ internal class ProfileCreateParamsTest { fun create() { ProfileCreateParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .profile( ProfileCreateParams.Profile.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) @@ -37,8 +40,74 @@ internal class ProfileCreateParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + ProfileCreateParams.builder() + .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .profile( + ProfileCreateParams.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + ProfileCreateParams.builder() + .userId("user_id") + .profile( + ProfileCreateParams.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { + val params = + ProfileCreateParams.builder() + .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .profile( + ProfileCreateParams.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val body = params._body() + + assertThat(body.profile()) + .isEqualTo( + ProfileCreateParams.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { val params = ProfileCreateParams.builder() .userId("user_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/profiles/lists/ListSubscribeParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/profiles/lists/ListSubscribeParamsTest.kt index 2ec7cab9..a7d59629 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/profiles/lists/ListSubscribeParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/profiles/lists/ListSubscribeParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.profiles.lists import com.courier.core.JsonValue +import com.courier.core.http.Headers import com.courier.models.RecipientPreferences import com.courier.models.profiles.SubscribeToListsRequestItem import org.assertj.core.api.Assertions.assertThat @@ -14,6 +15,8 @@ internal class ListSubscribeParamsTest { fun create() { ListSubscribeParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addList( SubscribeToListsRequestItem.builder() .listId("listId") @@ -81,11 +84,101 @@ internal class ListSubscribeParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + ListSubscribeParams.builder() + .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .addList( + SubscribeToListsRequestItem.builder() + .listId("listId") + .preferences( + RecipientPreferences.builder() + .categories( + RecipientPreferences.Categories.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "status" to "OPTED_IN", + "channel_preferences" to + listOf( + mapOf("channel" to "direct_message") + ), + "rules" to + listOf( + mapOf( + "until" to "until", + "start" to "start", + ) + ), + ) + ), + ) + .build() + ) + .notifications( + RecipientPreferences.Notifications.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "status" to "OPTED_IN", + "channel_preferences" to + listOf( + mapOf("channel" to "direct_message") + ), + "rules" to + listOf( + mapOf( + "until" to "until", + "start" to "start", + ) + ), + ) + ), + ) + .build() + ) + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + ListSubscribeParams.builder() + .userId("user_id") + .addList(SubscribeToListsRequestItem.builder().listId("listId").build()) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = ListSubscribeParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addList( SubscribeToListsRequestItem.builder() .listId("listId") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/providers/ProviderCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/providers/ProviderCreateParamsTest.kt index fc1f19be..1bec9fea 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/providers/ProviderCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/providers/ProviderCreateParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.providers import com.courier.core.JsonValue +import com.courier.core.http.Headers import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -11,6 +12,8 @@ internal class ProviderCreateParamsTest { @Test fun create() { ProviderCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .provider("provider") .alias("alias") .settings( @@ -22,10 +25,48 @@ internal class ProviderCreateParamsTest { .build() } + @Test + fun headers() { + val params = + ProviderCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .provider("provider") + .alias("alias") + .settings( + ProviderCreateParams.Settings.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .title("title") + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = ProviderCreateParams.builder().provider("provider").build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = ProviderCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .provider("provider") .alias("alias") .settings( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParamsTest.kt index 7c8e565f..e60583b8 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.routingstrategies import com.courier.core.JsonValue +import com.courier.core.http.Headers import com.courier.models.MessageChannels import com.courier.models.MessageProviders import com.courier.models.MessageRouting @@ -14,6 +15,8 @@ internal class RoutingStrategyCreateParamsTest { @Test fun create() { RoutingStrategyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .routingStrategyCreateRequest( RoutingStrategyCreateRequest.builder() .name("Email via SendGrid") @@ -84,10 +87,120 @@ internal class RoutingStrategyCreateParamsTest { .build() } + @Test + fun headers() { + val params = + RoutingStrategyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .routingStrategyCreateRequest( + RoutingStrategyCreateRequest.builder() + .name("Email via SendGrid") + .routing( + MessageRouting.builder() + .addChannel("email") + .method(MessageRouting.Method.SINGLE) + .build() + ) + .channels( + MessageChannels.builder() + .putAdditionalProperty( + "email", + JsonValue.from( + mapOf( + "brand_id" to "brand_id", + "if" to "if", + "metadata" to + mapOf( + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf("foo" to "bar"), + "providers" to listOf("sendgrid", "ses"), + "routing_method" to "all", + "timeouts" to mapOf("channel" to 0, "provider" to 0), + ) + ), + ) + .build() + ) + .description("Routes email through sendgrid with SES failover") + .providers( + MessageProviders.builder() + .putAdditionalProperty( + "sendgrid", + JsonValue.from( + mapOf( + "if" to "if", + "metadata" to + mapOf( + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf(), + "timeouts" to 0, + ) + ), + ) + .build() + ) + .addTag("production") + .addTag("email") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + RoutingStrategyCreateParams.builder() + .routingStrategyCreateRequest( + RoutingStrategyCreateRequest.builder() + .name("Email via SendGrid") + .routing( + MessageRouting.builder() + .addChannel("email") + .method(MessageRouting.Method.SINGLE) + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = RoutingStrategyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .routingStrategyCreateRequest( RoutingStrategyCreateRequest.builder() .name("Email via SendGrid") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt index 6ce5de55..6c2d5b3c 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.send import com.courier.core.JsonValue +import com.courier.core.http.Headers import com.courier.models.ElementalContentSugar import com.courier.models.MessageChannels import com.courier.models.MessageContext @@ -17,6 +18,8 @@ internal class SendMessageParamsTest { @Test fun create() { SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -213,10 +216,242 @@ internal class SendMessageParamsTest { .build() } + @Test + fun headers() { + val params = + SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .message( + SendMessageParams.Message.builder() + .brandId("brand_id") + .channels( + MessageChannels.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "brand_id" to "brand_id", + "if" to "if", + "metadata" to + mapOf( + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf("foo" to "bar"), + "providers" to listOf("string"), + "routing_method" to "all", + "timeouts" to mapOf("channel" to 0, "provider" to 0), + ) + ), + ) + .build() + ) + .content( + ElementalContentSugar.builder().body("body").title("title").build() + ) + .context(MessageContext.builder().tenantId("tenant_id").build()) + .data( + SendMessageParams.Message.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .delay( + SendMessageParams.Message.Delay.builder() + .duration(0L) + .timezone("timezone") + .until("until") + .build() + ) + .expiry( + SendMessageParams.Message.Expiry.builder() + .expiresIn("string") + .expiresAt("expires_at") + .build() + ) + .metadata( + SendMessageParams.Message.Metadata.builder() + .event("event") + .addTag("string") + .traceId("trace_id") + .utm( + Utm.builder() + .campaign("campaign") + .content("content") + .medium("medium") + .source("source") + .term("term") + .build() + ) + .build() + ) + .preferences( + SendMessageParams.Message.Preferences.builder() + .subscriptionTopicId("subscription_topic_id") + .build() + ) + .providers( + MessageProviders.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "if" to "if", + "metadata" to + mapOf( + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf("foo" to "bar"), + "timeouts" to 0, + ) + ), + ) + .build() + ) + .routing( + SendMessageParams.Message.Routing.builder() + .addChannel("string") + .method(SendMessageParams.Message.Routing.Method.ALL) + .build() + ) + .template("template_id") + .timeout( + SendMessageParams.Message.Timeout.builder() + .channel( + SendMessageParams.Message.Timeout.Channel.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .criteria(SendMessageParams.Message.Timeout.Criteria.NO_ESCALATION) + .escalation(0L) + .message(0L) + .provider( + SendMessageParams.Message.Timeout.Provider.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + ) + .build() + ) + .to( + UserRecipient.builder() + .accountId("account_id") + .context(MessageContext.builder().tenantId("tenant_id").build()) + .data( + UserRecipient.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .email("email") + .listId("list_id") + .locale("locale") + .phoneNumber("phone_number") + .preferences( + UserRecipient.Preferences.builder() + .notifications( + UserRecipient.Preferences.Notifications.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "status" to "OPTED_IN", + "channel_preferences" to + listOf( + mapOf( + "channel" to + "direct_message" + ) + ), + "rules" to + listOf( + mapOf( + "until" to "until", + "start" to "start", + ) + ), + "source" to "subscription", + ) + ), + ) + .build() + ) + .categories( + UserRecipient.Preferences.Categories.builder() + .putAdditionalProperty( + "foo", + JsonValue.from( + mapOf( + "status" to "OPTED_IN", + "channel_preferences" to + listOf( + mapOf( + "channel" to + "direct_message" + ) + ), + "rules" to + listOf( + mapOf( + "until" to "until", + "start" to "start", + ) + ), + "source" to "subscription", + ) + ), + ) + .build() + ) + .templateId("templateId") + .build() + ) + .tenantId("tenant_id") + .userId("user_id") + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + SendMessageParams.builder().message(SendMessageParams.Message.builder().build()).build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParamsTest.kt index 98c1a915..6da771c0 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/users/preferences/PreferenceBulkUpdateParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.users.preferences +import com.courier.core.http.Headers import com.courier.core.http.QueryParams import com.courier.models.ChannelClassification import org.assertj.core.api.Assertions.assertThat @@ -14,6 +15,8 @@ internal class PreferenceBulkUpdateParamsTest { PreferenceBulkUpdateParams.builder() .userId("user_id") .tenantId("tenant_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addTopic( PreferenceBulkUpdateParams.Topic.builder() .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) @@ -58,12 +61,76 @@ internal class PreferenceBulkUpdateParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + PreferenceBulkUpdateParams.builder() + .userId("user_id") + .tenantId("tenant_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .addTopic( + PreferenceBulkUpdateParams.Topic.builder() + .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) + .topicId("pt_01kx4h2jdafq8bk996nn92357r") + .addCustomRouting(ChannelClassification.INBOX) + .addCustomRouting(ChannelClassification.EMAIL) + .hasCustomRouting(true) + .build() + ) + .addTopic( + PreferenceBulkUpdateParams.Topic.builder() + .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_OUT) + .topicId("pt_01kx4h2jdafq8bk99eyt3dx43x") + .addCustomRouting(ChannelClassification.DIRECT_MESSAGE) + .hasCustomRouting(true) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + PreferenceBulkUpdateParams.builder() + .userId("user_id") + .addTopic( + PreferenceBulkUpdateParams.Topic.builder() + .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) + .topicId("pt_01kx4h2jdafq8bk996nn92357r") + .build() + ) + .addTopic( + PreferenceBulkUpdateParams.Topic.builder() + .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_OUT) + .topicId("pt_01kx4h2jdafq8bk99eyt3dx43x") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun queryParams() { val params = PreferenceBulkUpdateParams.builder() .userId("user_id") .tenantId("tenant_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addTopic( PreferenceBulkUpdateParams.Topic.builder() .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) @@ -119,6 +186,8 @@ internal class PreferenceBulkUpdateParamsTest { PreferenceBulkUpdateParams.builder() .userId("user_id") .tenantId("tenant_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addTopic( PreferenceBulkUpdateParams.Topic.builder() .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParamsTest.kt index 9d8776e8..d5f37e33 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferenceCreateParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.workspacepreferences +import com.courier.core.http.Headers import com.courier.models.ChannelClassification import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -11,6 +12,8 @@ internal class WorkspacePreferenceCreateParamsTest { @Test fun create() { WorkspacePreferenceCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .workspacePreferenceCreateRequest( WorkspacePreferenceCreateRequest.builder() .name("Account Notifications") @@ -22,10 +25,53 @@ internal class WorkspacePreferenceCreateParamsTest { .build() } + @Test + fun headers() { + val params = + WorkspacePreferenceCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .workspacePreferenceCreateRequest( + WorkspacePreferenceCreateRequest.builder() + .name("Account Notifications") + .description("description") + .hasCustomRouting(true) + .addRoutingOption(ChannelClassification.DIRECT_MESSAGE) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + WorkspacePreferenceCreateParams.builder() + .workspacePreferenceCreateRequest( + WorkspacePreferenceCreateRequest.builder().name("Account Notifications").build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = WorkspacePreferenceCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .workspacePreferenceCreateRequest( WorkspacePreferenceCreateRequest.builder() .name("Account Notifications") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParamsTest.kt index 347c6cc9..cbfe0bc4 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/WorkspacePreferencePublishParamsTest.kt @@ -2,6 +2,7 @@ package com.courier.models.workspacepreferences +import com.courier.core.http.Headers import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -11,6 +12,8 @@ internal class WorkspacePreferencePublishParamsTest { @Test fun create() { WorkspacePreferencePublishParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .publishPreferencesRequest( PublishPreferencesRequest.builder() .brandId("brand_id") @@ -21,10 +24,47 @@ internal class WorkspacePreferencePublishParamsTest { .build() } + @Test + fun headers() { + val params = + WorkspacePreferencePublishParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .publishPreferencesRequest( + PublishPreferencesRequest.builder() + .brandId("brand_id") + .description("description") + .heading("heading") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = WorkspacePreferencePublishParams.builder().build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = WorkspacePreferencePublishParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .publishPreferencesRequest( PublishPreferencesRequest.builder() .brandId("brand_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParamsTest.kt index f04922d0..82068bf8 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/workspacepreferences/topics/TopicCreateParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.workspacepreferences.topics import com.courier.core.JsonValue +import com.courier.core.http.Headers import com.courier.models.ChannelClassification import com.courier.models.workspacepreferences.WorkspacePreferenceTopicCreateRequest import org.assertj.core.api.Assertions.assertThat @@ -14,6 +15,8 @@ internal class TopicCreateParamsTest { fun create() { TopicCreateParams.builder() .sectionId("section_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .workspacePreferenceTopicCreateRequest( WorkspacePreferenceTopicCreateRequest.builder() .defaultStatus(WorkspacePreferenceTopicCreateRequest.DefaultStatus.OPTED_OUT) @@ -54,11 +57,72 @@ internal class TopicCreateParamsTest { assertThat(params._pathParam(1)).isEqualTo("") } + @Test + fun headers() { + val params = + TopicCreateParams.builder() + .sectionId("section_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .workspacePreferenceTopicCreateRequest( + WorkspacePreferenceTopicCreateRequest.builder() + .defaultStatus( + WorkspacePreferenceTopicCreateRequest.DefaultStatus.OPTED_OUT + ) + .name("Marketing") + .addAllowedPreference( + WorkspacePreferenceTopicCreateRequest.AllowedPreference.SNOOZE + ) + .description("description") + .includeUnsubscribeHeader(true) + .addRoutingOption(ChannelClassification.DIRECT_MESSAGE) + .topicData( + WorkspacePreferenceTopicCreateRequest.TopicData.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers) + .isEqualTo( + Headers.builder() + .put("Idempotency-Key", "order-ORD-456-user-123") + .put("x-idempotency-expiration", "1785312000") + .build() + ) + } + + @Test + fun headersWithoutOptionalFields() { + val params = + TopicCreateParams.builder() + .sectionId("section_id") + .workspacePreferenceTopicCreateRequest( + WorkspacePreferenceTopicCreateRequest.builder() + .defaultStatus( + WorkspacePreferenceTopicCreateRequest.DefaultStatus.OPTED_OUT + ) + .name("Marketing") + .build() + ) + .build() + + val headers = params._headers() + + assertThat(headers).isEqualTo(Headers.builder().build()) + } + @Test fun body() { val params = TopicCreateParams.builder() .sectionId("section_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .workspacePreferenceTopicCreateRequest( WorkspacePreferenceTopicCreateRequest.builder() .defaultStatus( diff --git a/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt index c47f3113..449720ea 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt @@ -78,6 +78,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -311,6 +313,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -544,6 +548,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -777,6 +783,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -1010,6 +1018,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -1243,6 +1253,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -1476,6 +1488,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -1709,6 +1723,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -1942,6 +1958,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -2175,6 +2193,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -2408,6 +2428,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -2641,6 +2663,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -2874,6 +2898,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -3107,6 +3133,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -3340,6 +3368,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -3573,6 +3603,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") @@ -3804,6 +3836,8 @@ internal class ErrorHandlingTest { assertThrows { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt index 4eab125f..86ac7ff0 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt @@ -50,6 +50,8 @@ internal class ServiceParamsTest { sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/BrandServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/BrandServiceAsyncTest.kt index 0989ced2..01b225cd 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/BrandServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/BrandServiceAsyncTest.kt @@ -33,6 +33,8 @@ internal class BrandServiceAsyncTest { val brandFuture = brandServiceAsync.create( BrandCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .name("My Brand") .settings( BrandSettings.builder() diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt index 34878453..b2f63d79 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt @@ -7,6 +7,8 @@ import com.courier.core.JsonValue import com.courier.models.journeys.CancelJourneyRequest import com.courier.models.journeys.CreateJourneyRequest import com.courier.models.journeys.JourneyApiInvokeTriggerNode +import com.courier.models.journeys.JourneyCancelParams +import com.courier.models.journeys.JourneyCreateParams import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams import com.courier.models.journeys.JourneyPublishParams @@ -28,36 +30,42 @@ internal class JourneyServiceAsyncTest { val journeyResponseFuture = journeyServiceAsync.create( - CreateJourneyRequest.builder() - .name("Welcome Journey") - .addNode( - JourneyApiInvokeTriggerNode.builder() - .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) - .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) - .id("trigger-1") - .conditionsOfConditionAtom(listOf("string", "string")) - .schema( - JourneyApiInvokeTriggerNode.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) + JourneyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) - .build() - ) - .addNode( - JourneyApiInvokeTriggerNode.builder() - .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) - .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) - .id("send-1") - .conditionsOfConditionAtom(listOf("string", "string")) - .schema( - JourneyApiInvokeTriggerNode.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) + .enabled(true) + .state(JourneyState.DRAFT) .build() ) - .enabled(true) - .state(JourneyState.DRAFT) .build() ) @@ -117,8 +125,14 @@ internal class JourneyServiceAsyncTest { val cancelJourneyResponseFuture = journeyServiceAsync.cancel( - CancelJourneyRequest.ByCancelationToken.builder() - .cancelationToken("order-1234") + JourneyCancelParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .cancelJourneyRequest( + CancelJourneyRequest.ByCancelationToken.builder() + .cancelationToken("order-1234") + .build() + ) .build() ) @@ -136,6 +150,8 @@ internal class JourneyServiceAsyncTest { journeyServiceAsync.invoke( JourneyInvokeParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeysInvokeRequest( JourneysInvokeRequest.builder() .data( @@ -181,6 +197,8 @@ internal class JourneyServiceAsyncTest { journeyServiceAsync.publish( JourneyPublishParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyPublishRequest( JourneyPublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt index b06be93b..0d069b1f 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/NotificationServiceAsyncTest.kt @@ -7,6 +7,7 @@ import com.courier.core.JsonValue import com.courier.models.ElementalChannelNodeWithType import com.courier.models.ElementalContent import com.courier.models.notifications.NotificationContentPutRequest +import com.courier.models.notifications.NotificationCreateParams import com.courier.models.notifications.NotificationElementPutRequest import com.courier.models.notifications.NotificationListParams import com.courier.models.notifications.NotificationListVersionsParams @@ -36,40 +37,46 @@ internal class NotificationServiceAsyncTest { val notificationTemplateResponseFuture = notificationServiceAsync.create( - NotificationTemplateCreateRequest.builder() - .notification( - NotificationTemplatePayload.builder() - .brand( - NotificationTemplatePayload.Brand.builder() - .id("bnd_01kx4mrd0pfzw8wt7pn7p2fzag") - .build() - ) - .content( - ElementalContent.builder() - .addElement( - ElementalChannelNodeWithType.builder() - .type(ElementalChannelNodeWithType.Type.CHANNEL) + NotificationCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .notificationTemplateCreateRequest( + NotificationTemplateCreateRequest.builder() + .notification( + NotificationTemplatePayload.builder() + .brand( + NotificationTemplatePayload.Brand.builder() + .id("bnd_01kx4mrd0pfzw8wt7pn7p2fzag") .build() ) - .version("2022-01-01") - .build() - ) - .name("Welcome Email") - .routing( - NotificationTemplatePayload.Routing.builder() - .strategyId("rs_01kx4h2jdafq8bk9amzvy6hbv0") - .build() - ) - .subscription( - NotificationTemplatePayload.Subscription.builder() - .topicId("pt_01kx4h2jdafq8bk9a26x0kvd1t") + .content( + ElementalContent.builder() + .addElement( + ElementalChannelNodeWithType.builder() + .type(ElementalChannelNodeWithType.Type.CHANNEL) + .build() + ) + .version("2022-01-01") + .build() + ) + .name("Welcome Email") + .routing( + NotificationTemplatePayload.Routing.builder() + .strategyId("rs_01kx4h2jdafq8bk9amzvy6hbv0") + .build() + ) + .subscription( + NotificationTemplatePayload.Subscription.builder() + .topicId("pt_01kx4h2jdafq8bk9a26x0kvd1t") + .build() + ) + .addTag("onboarding") + .addTag("welcome") .build() ) - .addTag("onboarding") - .addTag("welcome") + .state(NotificationTemplateCreateRequest.State.DRAFT) .build() ) - .state(NotificationTemplateCreateRequest.State.DRAFT) .build() ) @@ -164,6 +171,8 @@ internal class NotificationServiceAsyncTest { notificationServiceAsync.publish( NotificationPublishParams.builder() .id("id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .notificationTemplatePublishRequest( NotificationTemplatePublishRequest.builder() .version("v321669910225") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/ProfileServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/ProfileServiceAsyncTest.kt index e626346f..2a647872 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/ProfileServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/ProfileServiceAsyncTest.kt @@ -22,6 +22,8 @@ internal class ProfileServiceAsyncTest { profileServiceAsync.create( ProfileCreateParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .profile( ProfileCreateParams.Profile.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/ProviderServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/ProviderServiceAsyncTest.kt index d759f497..e6a49f66 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/ProviderServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/ProviderServiceAsyncTest.kt @@ -21,6 +21,8 @@ internal class ProviderServiceAsyncTest { val providerFuture = providerServiceAsync.create( ProviderCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .provider("provider") .alias("alias") .settings( diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncTest.kt index 0543782f..1018c450 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/RoutingStrategyServiceAsyncTest.kt @@ -7,6 +7,7 @@ import com.courier.core.JsonValue import com.courier.models.MessageChannels import com.courier.models.MessageProviders import com.courier.models.MessageRouting +import com.courier.models.routingstrategies.RoutingStrategyCreateParams import com.courier.models.routingstrategies.RoutingStrategyCreateRequest import com.courier.models.routingstrategies.RoutingStrategyListNotificationsParams import com.courier.models.routingstrategies.RoutingStrategyListParams @@ -25,70 +26,76 @@ internal class RoutingStrategyServiceAsyncTest { val routingStrategyGetResponseFuture = routingStrategyServiceAsync.create( - RoutingStrategyCreateRequest.builder() - .name("Email via SendGrid") - .routing( - MessageRouting.builder() - .addChannel("email") - .method(MessageRouting.Method.SINGLE) - .build() - ) - .channels( - MessageChannels.builder() - .putAdditionalProperty( - "email", - JsonValue.from( - mapOf( - "brand_id" to "brand_id", - "if" to "if", - "metadata" to + RoutingStrategyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .routingStrategyCreateRequest( + RoutingStrategyCreateRequest.builder() + .name("Email via SendGrid") + .routing( + MessageRouting.builder() + .addChannel("email") + .method(MessageRouting.Method.SINGLE) + .build() + ) + .channels( + MessageChannels.builder() + .putAdditionalProperty( + "email", + JsonValue.from( mapOf( - "utm" to + "brand_id" to "brand_id", + "if" to "if", + "metadata" to mapOf( - "campaign" to "campaign", - "content" to "content", - "medium" to "medium", - "source" to "source", - "term" to "term", - ) - ), - "override" to mapOf("foo" to "bar"), - "providers" to listOf("sendgrid", "ses"), - "routing_method" to "all", - "timeouts" to mapOf("channel" to 0, "provider" to 0), + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf("foo" to "bar"), + "providers" to listOf("sendgrid", "ses"), + "routing_method" to "all", + "timeouts" to mapOf("channel" to 0, "provider" to 0), + ) + ), ) - ), + .build() ) - .build() - ) - .description("Routes email through sendgrid with SES failover") - .providers( - MessageProviders.builder() - .putAdditionalProperty( - "sendgrid", - JsonValue.from( - mapOf( - "if" to "if", - "metadata" to + .description("Routes email through sendgrid with SES failover") + .providers( + MessageProviders.builder() + .putAdditionalProperty( + "sendgrid", + JsonValue.from( mapOf( - "utm" to + "if" to "if", + "metadata" to mapOf( - "campaign" to "campaign", - "content" to "content", - "medium" to "medium", - "source" to "source", - "term" to "term", - ) - ), - "override" to mapOf(), - "timeouts" to 0, + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf(), + "timeouts" to 0, + ) + ), ) - ), + .build() ) + .addTag("production") + .addTag("email") .build() ) - .addTag("production") - .addTag("email") .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt index e0001f6a..896a1af2 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt @@ -25,6 +25,8 @@ internal class SendServiceAsyncTest { val responseFuture = sendServiceAsync.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncTest.kt index dfae2fbb..5a4f48cf 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/WorkspacePreferenceServiceAsyncTest.kt @@ -5,7 +5,9 @@ package com.courier.services.async import com.courier.client.okhttp.CourierOkHttpClientAsync import com.courier.models.ChannelClassification import com.courier.models.workspacepreferences.PublishPreferencesRequest +import com.courier.models.workspacepreferences.WorkspacePreferenceCreateParams import com.courier.models.workspacepreferences.WorkspacePreferenceCreateRequest +import com.courier.models.workspacepreferences.WorkspacePreferencePublishParams import com.courier.models.workspacepreferences.WorkspacePreferenceReplaceParams import com.courier.models.workspacepreferences.WorkspacePreferenceReplaceRequest import org.junit.jupiter.api.Disabled @@ -21,11 +23,17 @@ internal class WorkspacePreferenceServiceAsyncTest { val workspacePreferenceGetResponseFuture = workspacePreferenceServiceAsync.create( - WorkspacePreferenceCreateRequest.builder() - .name("Account Notifications") - .description("description") - .hasCustomRouting(true) - .addRoutingOption(ChannelClassification.DIRECT_MESSAGE) + WorkspacePreferenceCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .workspacePreferenceCreateRequest( + WorkspacePreferenceCreateRequest.builder() + .name("Account Notifications") + .description("description") + .hasCustomRouting(true) + .addRoutingOption(ChannelClassification.DIRECT_MESSAGE) + .build() + ) .build() ) @@ -77,10 +85,16 @@ internal class WorkspacePreferenceServiceAsyncTest { val publishPreferencesResponseFuture = workspacePreferenceServiceAsync.publish( - PublishPreferencesRequest.builder() - .brandId("brand_id") - .description("description") - .heading("heading") + WorkspacePreferencePublishParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .publishPreferencesRequest( + PublishPreferencesRequest.builder() + .brandId("brand_id") + .description("description") + .heading("heading") + .build() + ) .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/automations/InvokeServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/automations/InvokeServiceAsyncTest.kt index 56472f96..3c1ac049 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/automations/InvokeServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/automations/InvokeServiceAsyncTest.kt @@ -20,6 +20,8 @@ internal class InvokeServiceAsyncTest { val automationInvokeResponseFuture = invokeServiceAsync.invokeAdHoc( InvokeInvokeAdHocParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .automation( InvokeInvokeAdHocParams.Automation.builder() .addStep( @@ -93,6 +95,8 @@ internal class InvokeServiceAsyncTest { invokeServiceAsync.invokeByTemplate( InvokeInvokeByTemplateParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .recipient("recipient") .brand("brand") .data( diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/inbox/MessageServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/inbox/MessageServiceAsyncTest.kt new file mode 100644 index 00000000..444389bf --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/inbox/MessageServiceAsyncTest.kt @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.inbox + +import com.courier.client.okhttp.CourierOkHttpClientAsync +import com.courier.core.JsonValue +import com.courier.models.inbox.messages.MessageRestoreParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +internal class MessageServiceAsyncTest { + + @Disabled("Mock server tests are disabled") + @Test + fun delete() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val messageServiceAsync = client.inbox().messages() + + val future = messageServiceAsync.delete("message_id") + + val response = future.get() + } + + @Disabled("Mock server tests are disabled") + @Test + fun restore() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val messageServiceAsync = client.inbox().messages() + + val future = + messageServiceAsync.restore( + MessageRestoreParams.builder() + .messageId("message_id") + .body(JsonValue.from(mapOf())) + .build() + ) + + val response = future.get() + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt index f0f99112..30436d61 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt @@ -36,6 +36,8 @@ internal class TemplateServiceAsyncTest { templateServiceAsync.create( TemplateCreateParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplateCreateRequest( JourneyTemplateCreateRequest.builder() .channel("email") @@ -161,6 +163,8 @@ internal class TemplateServiceAsyncTest { TemplatePublishParams.builder() .templateId("x") .notificationId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplatePublishRequest( JourneyTemplatePublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncTest.kt index b5fc41f6..001afa36 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/lists/SubscriptionServiceAsyncTest.kt @@ -41,6 +41,8 @@ internal class SubscriptionServiceAsyncTest { subscriptionServiceAsync.add( SubscriptionAddParams.builder() .listId("list_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addRecipient( PutSubscriptionsRecipient.builder() .recipientId("recipientId") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/profiles/ListServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/profiles/ListServiceAsyncTest.kt index e4f24d3a..38f75d96 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/profiles/ListServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/profiles/ListServiceAsyncTest.kt @@ -50,6 +50,8 @@ internal class ListServiceAsyncTest { listServiceAsync.subscribe( ListSubscribeParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addList( SubscribeToListsRequestItem.builder() .listId("listId") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/users/PreferenceServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/users/PreferenceServiceAsyncTest.kt index 88e1d5ee..b8faefee 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/users/PreferenceServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/users/PreferenceServiceAsyncTest.kt @@ -69,6 +69,8 @@ internal class PreferenceServiceAsyncTest { PreferenceBulkUpdateParams.builder() .userId("user_id") .tenantId("tenant_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addTopic( PreferenceBulkUpdateParams.Topic.builder() .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncTest.kt index 81463825..2d075c8e 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/workspacepreferences/TopicServiceAsyncTest.kt @@ -26,6 +26,8 @@ internal class TopicServiceAsyncTest { topicServiceAsync.create( TopicCreateParams.builder() .sectionId("section_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .workspacePreferenceTopicCreateRequest( WorkspacePreferenceTopicCreateRequest.builder() .defaultStatus( diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/BrandServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/BrandServiceTest.kt index 1458d88d..229abfc7 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/BrandServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/BrandServiceTest.kt @@ -33,6 +33,8 @@ internal class BrandServiceTest { val brand = brandService.create( BrandCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .name("My Brand") .settings( BrandSettings.builder() diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt index 9e8d9996..b2d5a3cb 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt @@ -7,6 +7,8 @@ import com.courier.core.JsonValue import com.courier.models.journeys.CancelJourneyRequest import com.courier.models.journeys.CreateJourneyRequest import com.courier.models.journeys.JourneyApiInvokeTriggerNode +import com.courier.models.journeys.JourneyCancelParams +import com.courier.models.journeys.JourneyCreateParams import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams import com.courier.models.journeys.JourneyPublishParams @@ -28,36 +30,42 @@ internal class JourneyServiceTest { val journeyResponse = journeyService.create( - CreateJourneyRequest.builder() - .name("Welcome Journey") - .addNode( - JourneyApiInvokeTriggerNode.builder() - .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) - .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) - .id("trigger-1") - .conditionsOfConditionAtom(listOf("string", "string")) - .schema( - JourneyApiInvokeTriggerNode.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) + JourneyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) - .build() - ) - .addNode( - JourneyApiInvokeTriggerNode.builder() - .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) - .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) - .id("send-1") - .conditionsOfConditionAtom(listOf("string", "string")) - .schema( - JourneyApiInvokeTriggerNode.Schema.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .build() ) + .enabled(true) + .state(JourneyState.DRAFT) .build() ) - .enabled(true) - .state(JourneyState.DRAFT) .build() ) @@ -112,8 +120,14 @@ internal class JourneyServiceTest { val cancelJourneyResponse = journeyService.cancel( - CancelJourneyRequest.ByCancelationToken.builder() - .cancelationToken("order-1234") + JourneyCancelParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .cancelJourneyRequest( + CancelJourneyRequest.ByCancelationToken.builder() + .cancelationToken("order-1234") + .build() + ) .build() ) @@ -130,6 +144,8 @@ internal class JourneyServiceTest { journeyService.invoke( JourneyInvokeParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeysInvokeRequest( JourneysInvokeRequest.builder() .data( @@ -173,6 +189,8 @@ internal class JourneyServiceTest { journeyService.publish( JourneyPublishParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyPublishRequest( JourneyPublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt index 4d405dcb..48e96fcb 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/NotificationServiceTest.kt @@ -7,6 +7,7 @@ import com.courier.core.JsonValue import com.courier.models.ElementalChannelNodeWithType import com.courier.models.ElementalContent import com.courier.models.notifications.NotificationContentPutRequest +import com.courier.models.notifications.NotificationCreateParams import com.courier.models.notifications.NotificationElementPutRequest import com.courier.models.notifications.NotificationListParams import com.courier.models.notifications.NotificationListVersionsParams @@ -36,40 +37,46 @@ internal class NotificationServiceTest { val notificationTemplateResponse = notificationService.create( - NotificationTemplateCreateRequest.builder() - .notification( - NotificationTemplatePayload.builder() - .brand( - NotificationTemplatePayload.Brand.builder() - .id("bnd_01kx4mrd0pfzw8wt7pn7p2fzag") - .build() - ) - .content( - ElementalContent.builder() - .addElement( - ElementalChannelNodeWithType.builder() - .type(ElementalChannelNodeWithType.Type.CHANNEL) + NotificationCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .notificationTemplateCreateRequest( + NotificationTemplateCreateRequest.builder() + .notification( + NotificationTemplatePayload.builder() + .brand( + NotificationTemplatePayload.Brand.builder() + .id("bnd_01kx4mrd0pfzw8wt7pn7p2fzag") .build() ) - .version("2022-01-01") - .build() - ) - .name("Welcome Email") - .routing( - NotificationTemplatePayload.Routing.builder() - .strategyId("rs_01kx4h2jdafq8bk9amzvy6hbv0") - .build() - ) - .subscription( - NotificationTemplatePayload.Subscription.builder() - .topicId("pt_01kx4h2jdafq8bk9a26x0kvd1t") + .content( + ElementalContent.builder() + .addElement( + ElementalChannelNodeWithType.builder() + .type(ElementalChannelNodeWithType.Type.CHANNEL) + .build() + ) + .version("2022-01-01") + .build() + ) + .name("Welcome Email") + .routing( + NotificationTemplatePayload.Routing.builder() + .strategyId("rs_01kx4h2jdafq8bk9amzvy6hbv0") + .build() + ) + .subscription( + NotificationTemplatePayload.Subscription.builder() + .topicId("pt_01kx4h2jdafq8bk9a26x0kvd1t") + .build() + ) + .addTag("onboarding") + .addTag("welcome") .build() ) - .addTag("onboarding") - .addTag("welcome") + .state(NotificationTemplateCreateRequest.State.DRAFT) .build() ) - .state(NotificationTemplateCreateRequest.State.DRAFT) .build() ) @@ -155,6 +162,8 @@ internal class NotificationServiceTest { notificationService.publish( NotificationPublishParams.builder() .id("id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .notificationTemplatePublishRequest( NotificationTemplatePublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProfileServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProfileServiceTest.kt index a07319c9..7a110927 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProfileServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProfileServiceTest.kt @@ -22,6 +22,8 @@ internal class ProfileServiceTest { profileService.create( ProfileCreateParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .profile( ProfileCreateParams.Profile.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProviderServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProviderServiceTest.kt index 0e5152b2..faa5e3f6 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProviderServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/ProviderServiceTest.kt @@ -21,6 +21,8 @@ internal class ProviderServiceTest { val provider = providerService.create( ProviderCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .provider("provider") .alias("alias") .settings( diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/RoutingStrategyServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/RoutingStrategyServiceTest.kt index f15b2225..0cc278db 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/RoutingStrategyServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/RoutingStrategyServiceTest.kt @@ -7,6 +7,7 @@ import com.courier.core.JsonValue import com.courier.models.MessageChannels import com.courier.models.MessageProviders import com.courier.models.MessageRouting +import com.courier.models.routingstrategies.RoutingStrategyCreateParams import com.courier.models.routingstrategies.RoutingStrategyCreateRequest import com.courier.models.routingstrategies.RoutingStrategyListNotificationsParams import com.courier.models.routingstrategies.RoutingStrategyListParams @@ -25,70 +26,76 @@ internal class RoutingStrategyServiceTest { val routingStrategyGetResponse = routingStrategyService.create( - RoutingStrategyCreateRequest.builder() - .name("Email via SendGrid") - .routing( - MessageRouting.builder() - .addChannel("email") - .method(MessageRouting.Method.SINGLE) - .build() - ) - .channels( - MessageChannels.builder() - .putAdditionalProperty( - "email", - JsonValue.from( - mapOf( - "brand_id" to "brand_id", - "if" to "if", - "metadata" to + RoutingStrategyCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .routingStrategyCreateRequest( + RoutingStrategyCreateRequest.builder() + .name("Email via SendGrid") + .routing( + MessageRouting.builder() + .addChannel("email") + .method(MessageRouting.Method.SINGLE) + .build() + ) + .channels( + MessageChannels.builder() + .putAdditionalProperty( + "email", + JsonValue.from( mapOf( - "utm" to + "brand_id" to "brand_id", + "if" to "if", + "metadata" to mapOf( - "campaign" to "campaign", - "content" to "content", - "medium" to "medium", - "source" to "source", - "term" to "term", - ) - ), - "override" to mapOf("foo" to "bar"), - "providers" to listOf("sendgrid", "ses"), - "routing_method" to "all", - "timeouts" to mapOf("channel" to 0, "provider" to 0), + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf("foo" to "bar"), + "providers" to listOf("sendgrid", "ses"), + "routing_method" to "all", + "timeouts" to mapOf("channel" to 0, "provider" to 0), + ) + ), ) - ), + .build() ) - .build() - ) - .description("Routes email through sendgrid with SES failover") - .providers( - MessageProviders.builder() - .putAdditionalProperty( - "sendgrid", - JsonValue.from( - mapOf( - "if" to "if", - "metadata" to + .description("Routes email through sendgrid with SES failover") + .providers( + MessageProviders.builder() + .putAdditionalProperty( + "sendgrid", + JsonValue.from( mapOf( - "utm" to + "if" to "if", + "metadata" to mapOf( - "campaign" to "campaign", - "content" to "content", - "medium" to "medium", - "source" to "source", - "term" to "term", - ) - ), - "override" to mapOf(), - "timeouts" to 0, + "utm" to + mapOf( + "campaign" to "campaign", + "content" to "content", + "medium" to "medium", + "source" to "source", + "term" to "term", + ) + ), + "override" to mapOf(), + "timeouts" to 0, + ) + ), ) - ), + .build() ) + .addTag("production") + .addTag("email") .build() ) - .addTag("production") - .addTag("email") .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt index 402fbbf5..325d92ef 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt @@ -25,6 +25,8 @@ internal class SendServiceTest { val response = sendService.message( SendMessageParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .message( SendMessageParams.Message.builder() .brandId("brand_id") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceTest.kt index 0bc07a7f..f223e864 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/WorkspacePreferenceServiceTest.kt @@ -5,7 +5,9 @@ package com.courier.services.blocking import com.courier.client.okhttp.CourierOkHttpClient import com.courier.models.ChannelClassification import com.courier.models.workspacepreferences.PublishPreferencesRequest +import com.courier.models.workspacepreferences.WorkspacePreferenceCreateParams import com.courier.models.workspacepreferences.WorkspacePreferenceCreateRequest +import com.courier.models.workspacepreferences.WorkspacePreferencePublishParams import com.courier.models.workspacepreferences.WorkspacePreferenceReplaceParams import com.courier.models.workspacepreferences.WorkspacePreferenceReplaceRequest import org.junit.jupiter.api.Disabled @@ -21,11 +23,17 @@ internal class WorkspacePreferenceServiceTest { val workspacePreferenceGetResponse = workspacePreferenceService.create( - WorkspacePreferenceCreateRequest.builder() - .name("Account Notifications") - .description("description") - .hasCustomRouting(true) - .addRoutingOption(ChannelClassification.DIRECT_MESSAGE) + WorkspacePreferenceCreateParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .workspacePreferenceCreateRequest( + WorkspacePreferenceCreateRequest.builder() + .name("Account Notifications") + .description("description") + .hasCustomRouting(true) + .addRoutingOption(ChannelClassification.DIRECT_MESSAGE) + .build() + ) .build() ) @@ -71,10 +79,16 @@ internal class WorkspacePreferenceServiceTest { val publishPreferencesResponse = workspacePreferenceService.publish( - PublishPreferencesRequest.builder() - .brandId("brand_id") - .description("description") - .heading("heading") + WorkspacePreferencePublishParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") + .publishPreferencesRequest( + PublishPreferencesRequest.builder() + .brandId("brand_id") + .description("description") + .heading("heading") + .build() + ) .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/automations/InvokeServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/automations/InvokeServiceTest.kt index 125ed88b..cdc8fa62 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/automations/InvokeServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/automations/InvokeServiceTest.kt @@ -20,6 +20,8 @@ internal class InvokeServiceTest { val automationInvokeResponse = invokeService.invokeAdHoc( InvokeInvokeAdHocParams.builder() + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .automation( InvokeInvokeAdHocParams.Automation.builder() .addStep( @@ -92,6 +94,8 @@ internal class InvokeServiceTest { invokeService.invokeByTemplate( InvokeInvokeByTemplateParams.builder() .templateId("templateId") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .recipient("recipient") .brand("brand") .data( diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/inbox/MessageServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/inbox/MessageServiceTest.kt new file mode 100644 index 00000000..a9fd08ab --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/inbox/MessageServiceTest.kt @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.inbox + +import com.courier.client.okhttp.CourierOkHttpClient +import com.courier.core.JsonValue +import com.courier.models.inbox.messages.MessageRestoreParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +internal class MessageServiceTest { + + @Disabled("Mock server tests are disabled") + @Test + fun delete() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val messageService = client.inbox().messages() + + messageService.delete("message_id") + } + + @Disabled("Mock server tests are disabled") + @Test + fun restore() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val messageService = client.inbox().messages() + + messageService.restore( + MessageRestoreParams.builder() + .messageId("message_id") + .body(JsonValue.from(mapOf())) + .build() + ) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt index 053460a3..886722e2 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt @@ -36,6 +36,8 @@ internal class TemplateServiceTest { templateService.create( TemplateCreateParams.builder() .templateId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplateCreateRequest( JourneyTemplateCreateRequest.builder() .channel("email") @@ -152,6 +154,8 @@ internal class TemplateServiceTest { TemplatePublishParams.builder() .templateId("x") .notificationId("x") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .journeyTemplatePublishRequest( JourneyTemplatePublishRequest.builder().version("v321669910225").build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/lists/SubscriptionServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/lists/SubscriptionServiceTest.kt index a17df3c0..ed883d4f 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/lists/SubscriptionServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/lists/SubscriptionServiceTest.kt @@ -39,6 +39,8 @@ internal class SubscriptionServiceTest { subscriptionService.add( SubscriptionAddParams.builder() .listId("list_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addRecipient( PutSubscriptionsRecipient.builder() .recipientId("recipientId") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/profiles/ListServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/profiles/ListServiceTest.kt index f1261d7e..f458d5c9 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/profiles/ListServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/profiles/ListServiceTest.kt @@ -48,6 +48,8 @@ internal class ListServiceTest { listService.subscribe( ListSubscribeParams.builder() .userId("user_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addList( SubscribeToListsRequestItem.builder() .listId("listId") diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/users/PreferenceServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/users/PreferenceServiceTest.kt index 221477d1..e7e5d2d1 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/users/PreferenceServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/users/PreferenceServiceTest.kt @@ -67,6 +67,8 @@ internal class PreferenceServiceTest { PreferenceBulkUpdateParams.builder() .userId("user_id") .tenantId("tenant_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .addTopic( PreferenceBulkUpdateParams.Topic.builder() .status(PreferenceBulkUpdateParams.Topic.Status.OPTED_IN) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceTest.kt index e70923ec..8a5e3539 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/workspacepreferences/TopicServiceTest.kt @@ -26,6 +26,8 @@ internal class TopicServiceTest { topicService.create( TopicCreateParams.builder() .sectionId("section_id") + .idempotencyKey("order-ORD-456-user-123") + .xIdempotencyExpiration("1785312000") .workspacePreferenceTopicCreateRequest( WorkspacePreferenceTopicCreateRequest.builder() .defaultStatus( diff --git a/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt b/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt index 1f9b81c5..99c0af4d 100644 --- a/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt +++ b/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt @@ -61,6 +61,7 @@ internal class ProGuardCompatibilityTest { assertThat(client.digests()).isNotNull() assertThat(client.inbound()).isNotNull() assertThat(client.lists()).isNotNull() + assertThat(client.inbox()).isNotNull() assertThat(client.messages()).isNotNull() assertThat(client.requests()).isNotNull() assertThat(client.notifications()).isNotNull()