diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ea98b61f..b7046597 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -65,14 +65,18 @@ jobs:
run: ./scripts/build
- name: Get GitHub OIDC Token
- if: github.repository == 'stainless-sdks/courier-java'
+ if: |-
+ github.repository == 'stainless-sdks/courier-java' &&
+ !startsWith(github.ref, 'refs/heads/stl/')
id: github-oidc
uses: actions/github-script@v8
with:
script: core.setOutput('github_token', await core.getIDToken());
- name: Build and upload Maven artifacts
- if: github.repository == 'stainless-sdks/courier-java'
+ if: |-
+ github.repository == 'stainless-sdks/courier-java' &&
+ !startsWith(github.ref, 'refs/heads/stl/')
env:
URL: https://pkg.stainless.com/s
AUTH: ${{ steps.github-oidc.outputs.github_token }}
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 0056f0ab..ad56a78c 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.9.1"
+ ".": "4.10.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 17749e26..75c12180 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 81
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-3fc1c86b4a83a16393aaf17d1fb3ac6098d30dd057ba872973b57285a7a3f0d0.yml
-openapi_spec_hash: 02a545d217b13399f311e99561f9de1d
-config_hash: 0789c3cddc625bb9712b3bded274ab6c
+configured_endpoints: 83
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-19330fca8fa9bbae835ec9d9f83b37b3df364d9b462090b9623bfc9b6eae99c2.yml
+openapi_spec_hash: 0bc6889464c9ac2542b4837f569c1837
+config_hash: 1ae49ed522c8423378d9463cdd0fb880
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d183d7d5..712ef68f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,41 @@
# Changelog
+## 4.10.0 (2026-03-12)
+
+Full Changelog: [v4.9.1...v4.10.0](https://github.com/trycourier/courier-java/compare/v4.9.1...v4.10.0)
+
+### Features
+
+* **api:** add journeys resource with list/invoke methods ([2c7587e](https://github.com/trycourier/courier-java/commit/2c7587e7b3eb0ae29e77b5bbe26f96d19aed5076))
+* **client:** add connection pooling option ([b2e1bcb](https://github.com/trycourier/courier-java/commit/b2e1bcbd856bbe7d247497b2296dd8f368fdc6da))
+
+
+### Bug Fixes
+
+* **api:** restructure token add single request body, rename pathToken to token ([9577dec](https://github.com/trycourier/courier-java/commit/9577decaf5da849b9c35d2c7a6302ef2b105193e))
+* **client:** incorrect `Retry-After` parsing ([4719954](https://github.com/trycourier/courier-java/commit/471995496d38e95ca4f0b832064ae529fc02dabf))
+* mark MessageDetails timestamp fields as optional ([e948f83](https://github.com/trycourier/courier-java/commit/e948f832f3ac9e5b71b24a3f02387e88ffb6be12))
+* **types:** remove brand field from ElementalContent model ([cb336a3](https://github.com/trycourier/courier-java/commit/cb336a3bb81b5e2bd25483be06c45bdfd518fe2b))
+
+
+### Chores
+
+* **ci:** skip uploading artifacts on stainless-internal branches ([330979b](https://github.com/trycourier/courier-java/commit/330979bc70a21d68fa33ca16f949bc378aa818c9))
+* drop apache dependency ([90094b9](https://github.com/trycourier/courier-java/commit/90094b91bb84ab5f9b01d351031431990495e2fa))
+* **internal:** bump palantir-java-format ([0057417](https://github.com/trycourier/courier-java/commit/0057417ffd2fcb14a33a42ebb8d81bce4232197a))
+* **internal:** codegen related update ([6a1cfae](https://github.com/trycourier/courier-java/commit/6a1cfaeee2212a162513951b903778d4a35e48b3))
+* **internal:** expand imports ([b1b8ef3](https://github.com/trycourier/courier-java/commit/b1b8ef384a3acddc0ce6cd79cfca840e6da4c748))
+* **internal:** make `OkHttp` constructor internal ([4e39320](https://github.com/trycourier/courier-java/commit/4e393200781dd186e45a32ff8d18be7083e83b31))
+* **internal:** remove mock server code ([b63945e](https://github.com/trycourier/courier-java/commit/b63945ee56673ba3e736de9d2170b0a27e7dcd82))
+* **internal:** update `TestServerExtension` comment ([26b5aed](https://github.com/trycourier/courier-java/commit/26b5aede00f47e7a0bae77e058e36a00361060b0))
+* make `Properties` more resilient to `null` ([401bc43](https://github.com/trycourier/courier-java/commit/401bc435edc5a6798afb1c1619a0de37cdb7a9fe))
+* update mock server docs ([ff62ef0](https://github.com/trycourier/courier-java/commit/ff62ef0c2c8c232f96a3b3e5ade9c6ac22a1b248))
+
+
+### Documentation
+
+* add AUTO-GENERATED-OVERVIEW markers for README sync ([#92](https://github.com/trycourier/courier-java/issues/92)) ([4bc2f46](https://github.com/trycourier/courier-java/commit/4bc2f4661c8c7d35d72234c1f5520eec71a39bcc))
+
## 4.9.1 (2026-02-07)
Full Changelog: [v4.9.0...v4.9.1](https://github.com/trycourier/courier-java/compare/v4.9.0...v4.9.1)
diff --git a/README.md b/README.md
index c7b5ba8c..cf1a8f6d 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ The Courier Java SDK provides typed access to the Courier REST API from applicat
### Gradle
```kotlin
-implementation("com.courier:courier-java:4.9.1")
+implementation("com.courier:courier-java:4.10.0")
```
### Maven
@@ -17,7 +17,7 @@ implementation("com.courier:courier-java:4.9.1")
com.courier
courier-java
- 4.9.1
+ 4.10.0
```
diff --git a/build.gradle.kts b/build.gradle.kts
index aae0be02..653fe829 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,7 +8,7 @@ repositories {
allprojects {
group = "com.courier"
- version = "4.9.1" // x-release-please-version
+ version = "4.10.0" // x-release-please-version
}
subprojects {
diff --git a/buildSrc/src/main/kotlin/courier.java.gradle.kts b/buildSrc/src/main/kotlin/courier.java.gradle.kts
index 70fc33f4..8f4f902a 100644
--- a/buildSrc/src/main/kotlin/courier.java.gradle.kts
+++ b/buildSrc/src/main/kotlin/courier.java.gradle.kts
@@ -45,7 +45,7 @@ tasks.withType().configureEach {
val palantir by configurations.creating
dependencies {
- palantir("com.palantir.javaformat:palantir-java-format:2.73.0")
+ palantir("com.palantir.javaformat:palantir-java-format:2.89.0")
}
fun registerPalantir(
diff --git a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt
index 429e095e..73be7c55 100644
--- a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt
+++ b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt
@@ -47,6 +47,8 @@ class CourierOkHttpClient private constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
+ private var maxIdleConnections: Int? = null
+ private var keepAliveDuration: Duration? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
@@ -75,6 +77,46 @@ class CourierOkHttpClient private constructor() {
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional) = proxy(proxy.getOrNull())
+ /**
+ * The maximum number of idle connections kept by the underlying OkHttp connection pool.
+ *
+ * If this is set, then [keepAliveDuration] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int?) = apply {
+ this.maxIdleConnections = maxIdleConnections
+ }
+
+ /**
+ * Alias for [Builder.maxIdleConnections].
+ *
+ * This unboxed primitive overload exists for backwards compatibility.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int) =
+ maxIdleConnections(maxIdleConnections as Int?)
+
+ /**
+ * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
+ */
+ fun maxIdleConnections(maxIdleConnections: Optional) =
+ maxIdleConnections(maxIdleConnections.getOrNull())
+
+ /**
+ * The keep-alive duration for idle connections in the underlying OkHttp connection pool.
+ *
+ * If this is set, then [maxIdleConnections] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
+ this.keepAliveDuration = keepAliveDuration
+ }
+
+ /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
+ fun keepAliveDuration(keepAliveDuration: Optional) =
+ keepAliveDuration(keepAliveDuration.getOrNull())
+
/**
* The socket factory used to secure HTTPS connections.
*
@@ -317,6 +359,8 @@ class CourierOkHttpClient private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .maxIdleConnections(maxIdleConnections)
+ .keepAliveDuration(keepAliveDuration)
.dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
diff --git a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt
index 2e2adb16..8a1baa2a 100644
--- a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt
+++ b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt
@@ -47,6 +47,8 @@ class CourierOkHttpClientAsync private constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var dispatcherExecutorService: ExecutorService? = null
private var proxy: Proxy? = null
+ private var maxIdleConnections: Int? = null
+ private var keepAliveDuration: Duration? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
@@ -75,6 +77,46 @@ class CourierOkHttpClientAsync private constructor() {
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional) = proxy(proxy.getOrNull())
+ /**
+ * The maximum number of idle connections kept by the underlying OkHttp connection pool.
+ *
+ * If this is set, then [keepAliveDuration] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int?) = apply {
+ this.maxIdleConnections = maxIdleConnections
+ }
+
+ /**
+ * Alias for [Builder.maxIdleConnections].
+ *
+ * This unboxed primitive overload exists for backwards compatibility.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int) =
+ maxIdleConnections(maxIdleConnections as Int?)
+
+ /**
+ * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`.
+ */
+ fun maxIdleConnections(maxIdleConnections: Optional) =
+ maxIdleConnections(maxIdleConnections.getOrNull())
+
+ /**
+ * The keep-alive duration for idle connections in the underlying OkHttp connection pool.
+ *
+ * If this is set, then [maxIdleConnections] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
+ this.keepAliveDuration = keepAliveDuration
+ }
+
+ /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */
+ fun keepAliveDuration(keepAliveDuration: Optional) =
+ keepAliveDuration(keepAliveDuration.getOrNull())
+
/**
* The socket factory used to secure HTTPS connections.
*
@@ -317,6 +359,8 @@ class CourierOkHttpClientAsync private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
+ .maxIdleConnections(maxIdleConnections)
+ .keepAliveDuration(keepAliveDuration)
.dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
diff --git a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt
index ca6ffdbe..86340f02 100644
--- a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt
+++ b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt
@@ -16,11 +16,13 @@ import java.time.Duration
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
+import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Call
import okhttp3.Callback
+import okhttp3.ConnectionPool
import okhttp3.Dispatcher
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType
@@ -33,7 +35,7 @@ import okhttp3.logging.HttpLoggingInterceptor
import okio.BufferedSink
class OkHttpClient
-private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient {
+internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient {
override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse {
val call = newCall(request, requestOptions)
@@ -200,6 +202,8 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
+ private var maxIdleConnections: Int? = null
+ private var keepAliveDuration: Duration? = null
private var dispatcherExecutorService: ExecutorService? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
@@ -211,6 +215,28 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }
+ /**
+ * Sets the maximum number of idle connections kept by the underlying [ConnectionPool].
+ *
+ * If this is set, then [keepAliveDuration] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun maxIdleConnections(maxIdleConnections: Int?) = apply {
+ this.maxIdleConnections = maxIdleConnections
+ }
+
+ /**
+ * Sets the keep-alive duration for idle connections in the underlying [ConnectionPool].
+ *
+ * If this is set, then [maxIdleConnections] must also be set.
+ *
+ * If unset, then OkHttp's default is used.
+ */
+ fun keepAliveDuration(keepAliveDuration: Duration?) = apply {
+ this.keepAliveDuration = keepAliveDuration
+ }
+
fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
this.dispatcherExecutorService = dispatcherExecutorService
}
@@ -240,6 +266,22 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
.apply {
dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }
+ val maxIdleConnections = maxIdleConnections
+ val keepAliveDuration = keepAliveDuration
+ if (maxIdleConnections != null && keepAliveDuration != null) {
+ connectionPool(
+ ConnectionPool(
+ maxIdleConnections,
+ keepAliveDuration.toNanos(),
+ TimeUnit.NANOSECONDS,
+ )
+ )
+ } else {
+ check((maxIdleConnections != null) == (keepAliveDuration != null)) {
+ "Both or none of `maxIdleConnections` and `keepAliveDuration` must be set, but only one was set"
+ }
+ }
+
val sslSocketFactory = sslSocketFactory
val trustManager = trustManager
if (sslSocketFactory != null && trustManager != null) {
diff --git a/courier-java-core/build.gradle.kts b/courier-java-core/build.gradle.kts
index 15e9f371..d4f0b6c8 100644
--- a/courier-java-core/build.gradle.kts
+++ b/courier-java-core/build.gradle.kts
@@ -27,8 +27,6 @@ dependencies {
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2")
implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.2")
- implementation("org.apache.httpcomponents.core5:httpcore5:5.2.4")
- implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")
testImplementation(kotlin("test"))
testImplementation(project(":courier-java-client-okhttp"))
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 953d9b6a..3f4207eb 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.BulkService
import com.courier.services.blocking.InboundService
+import com.courier.services.blocking.JourneyService
import com.courier.services.blocking.ListService
import com.courier.services.blocking.MessageService
import com.courier.services.blocking.NotificationService
@@ -67,6 +68,8 @@ interface CourierClient {
fun automations(): AutomationService
+ fun journeys(): JourneyService
+
fun brands(): BrandService
fun bulk(): BulkService
@@ -122,6 +125,8 @@ interface CourierClient {
fun automations(): AutomationService.WithRawResponse
+ fun journeys(): JourneyService.WithRawResponse
+
fun brands(): BrandService.WithRawResponse
fun bulk(): BulkService.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 58cc94de..facdb00c 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.BulkServiceAsync
import com.courier.services.async.InboundServiceAsync
+import com.courier.services.async.JourneyServiceAsync
import com.courier.services.async.ListServiceAsync
import com.courier.services.async.MessageServiceAsync
import com.courier.services.async.NotificationServiceAsync
@@ -67,6 +68,8 @@ interface CourierClientAsync {
fun automations(): AutomationServiceAsync
+ fun journeys(): JourneyServiceAsync
+
fun brands(): BrandServiceAsync
fun bulk(): BulkServiceAsync
@@ -126,6 +129,8 @@ interface CourierClientAsync {
fun automations(): AutomationServiceAsync.WithRawResponse
+ fun journeys(): JourneyServiceAsync.WithRawResponse
+
fun brands(): BrandServiceAsync.WithRawResponse
fun bulk(): BulkServiceAsync.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 7155339b..a540243c 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.BulkServiceAsync
import com.courier.services.async.BulkServiceAsyncImpl
import com.courier.services.async.InboundServiceAsync
import com.courier.services.async.InboundServiceAsyncImpl
+import com.courier.services.async.JourneyServiceAsync
+import com.courier.services.async.JourneyServiceAsyncImpl
import com.courier.services.async.ListServiceAsync
import com.courier.services.async.ListServiceAsyncImpl
import com.courier.services.async.MessageServiceAsync
@@ -71,6 +73,10 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier
AutomationServiceAsyncImpl(clientOptionsWithUserAgent)
}
+ private val journeys: JourneyServiceAsync by lazy {
+ JourneyServiceAsyncImpl(clientOptionsWithUserAgent)
+ }
+
private val brands: BrandServiceAsync by lazy {
BrandServiceAsyncImpl(clientOptionsWithUserAgent)
}
@@ -126,6 +132,8 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier
override fun automations(): AutomationServiceAsync = automations
+ override fun journeys(): JourneyServiceAsync = journeys
+
override fun brands(): BrandServiceAsync = brands
override fun bulk(): BulkServiceAsync = bulk
@@ -173,6 +181,10 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier
AutomationServiceAsyncImpl.WithRawResponseImpl(clientOptions)
}
+ private val journeys: JourneyServiceAsync.WithRawResponse by lazy {
+ JourneyServiceAsyncImpl.WithRawResponseImpl(clientOptions)
+ }
+
private val brands: BrandServiceAsync.WithRawResponse by lazy {
BrandServiceAsyncImpl.WithRawResponseImpl(clientOptions)
}
@@ -234,6 +246,8 @@ class CourierClientAsyncImpl(private val clientOptions: ClientOptions) : Courier
override fun automations(): AutomationServiceAsync.WithRawResponse = automations
+ override fun journeys(): JourneyServiceAsync.WithRawResponse = journeys
+
override fun brands(): BrandServiceAsync.WithRawResponse = brands
override fun bulk(): BulkServiceAsync.WithRawResponse = bulk
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 ee61b28d..2ab15a6c 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.BulkService
import com.courier.services.blocking.BulkServiceImpl
import com.courier.services.blocking.InboundService
import com.courier.services.blocking.InboundServiceImpl
+import com.courier.services.blocking.JourneyService
+import com.courier.services.blocking.JourneyServiceImpl
import com.courier.services.blocking.ListService
import com.courier.services.blocking.ListServiceImpl
import com.courier.services.blocking.MessageService
@@ -71,6 +73,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien
AutomationServiceImpl(clientOptionsWithUserAgent)
}
+ private val journeys: JourneyService by lazy { JourneyServiceImpl(clientOptionsWithUserAgent) }
+
private val brands: BrandService by lazy { BrandServiceImpl(clientOptionsWithUserAgent) }
private val bulk: BulkService by lazy { BulkServiceImpl(clientOptionsWithUserAgent) }
@@ -114,6 +118,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien
override fun automations(): AutomationService = automations
+ override fun journeys(): JourneyService = journeys
+
override fun brands(): BrandService = brands
override fun bulk(): BulkService = bulk
@@ -161,6 +167,10 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien
AutomationServiceImpl.WithRawResponseImpl(clientOptions)
}
+ private val journeys: JourneyService.WithRawResponse by lazy {
+ JourneyServiceImpl.WithRawResponseImpl(clientOptions)
+ }
+
private val brands: BrandService.WithRawResponse by lazy {
BrandServiceImpl.WithRawResponseImpl(clientOptions)
}
@@ -222,6 +232,8 @@ class CourierClientImpl(private val clientOptions: ClientOptions) : CourierClien
override fun automations(): AutomationService.WithRawResponse = automations
+ override fun journeys(): JourneyService.WithRawResponse = journeys
+
override fun brands(): BrandService.WithRawResponse = brands
override fun bulk(): BulkService.WithRawResponse = bulk
diff --git a/courier-java-core/src/main/kotlin/com/courier/core/Properties.kt b/courier-java-core/src/main/kotlin/com/courier/core/Properties.kt
index f1fb24f6..20b78089 100644
--- a/courier-java-core/src/main/kotlin/com/courier/core/Properties.kt
+++ b/courier-java-core/src/main/kotlin/com/courier/core/Properties.kt
@@ -34,9 +34,9 @@ fun getOsName(): String {
}
}
-fun getOsVersion(): String = System.getProperty("os.version", "unknown")
+fun getOsVersion(): String = System.getProperty("os.version", "unknown") ?: "unknown"
fun getPackageVersion(): String =
- CourierClient::class.java.`package`.implementationVersion ?: "unknown"
+ CourierClient::class.java.`package`?.implementationVersion ?: "unknown"
-fun getJavaVersion(): String = System.getProperty("java.version", "unknown")
+fun getJavaVersion(): String = System.getProperty("java.version", "unknown") ?: "unknown"
diff --git a/courier-java-core/src/main/kotlin/com/courier/core/http/HttpRequestBodies.kt b/courier-java-core/src/main/kotlin/com/courier/core/http/HttpRequestBodies.kt
index 5736754c..c2ddbd06 100644
--- a/courier-java-core/src/main/kotlin/com/courier/core/http/HttpRequestBodies.kt
+++ b/courier-java-core/src/main/kotlin/com/courier/core/http/HttpRequestBodies.kt
@@ -5,16 +5,16 @@
package com.courier.core.http
import com.courier.core.MultipartField
+import com.courier.core.toImmutable
import com.courier.errors.CourierInvalidDataException
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.databind.node.JsonNodeType
+import java.io.ByteArrayInputStream
import java.io.InputStream
import java.io.OutputStream
+import java.util.UUID
import kotlin.jvm.optionals.getOrNull
-import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder
-import org.apache.hc.core5.http.ContentType
-import org.apache.hc.core5.http.HttpEntity
@JvmSynthetic
internal inline fun json(jsonMapper: JsonMapper, value: T): HttpRequestBody =
@@ -37,92 +37,231 @@ internal fun multipartFormData(
jsonMapper: JsonMapper,
fields: Map>,
): HttpRequestBody =
- object : HttpRequestBody {
- private val entity: HttpEntity by lazy {
- MultipartEntityBuilder.create()
- .apply {
- fields.forEach { (name, field) ->
- val knownValue = field.value.asKnown().getOrNull()
- val parts =
- if (knownValue is InputStream) {
- // Read directly from the `InputStream` instead of reading it all
- // into memory due to the `jsonMapper` serialization below.
- sequenceOf(name to knownValue)
- } else {
- val node = jsonMapper.valueToTree(field.value)
- serializePart(name, node)
+ MultipartBody.Builder()
+ .apply {
+ fields.forEach { (name, field) ->
+ val knownValue = field.value.asKnown().getOrNull()
+ val parts =
+ if (knownValue is InputStream) {
+ // Read directly from the `InputStream` instead of reading it all
+ // into memory due to the `jsonMapper` serialization below.
+ sequenceOf(name to knownValue)
+ } else {
+ val node = jsonMapper.valueToTree(field.value)
+ serializePart(name, node)
+ }
+
+ parts.forEach { (name, bytes) ->
+ val partBody =
+ if (bytes is ByteArrayInputStream) {
+ val byteArray = bytes.readBytes()
+
+ object : HttpRequestBody {
+
+ override fun writeTo(outputStream: OutputStream) {
+ outputStream.write(byteArray)
+ }
+
+ override fun contentType(): String = field.contentType
+
+ override fun contentLength(): Long = byteArray.size.toLong()
+
+ override fun repeatable(): Boolean = true
+
+ override fun close() {}
}
+ } else {
+ object : HttpRequestBody {
+
+ override fun writeTo(outputStream: OutputStream) {
+ bytes.copyTo(outputStream)
+ }
+
+ override fun contentType(): String = field.contentType
+
+ override fun contentLength(): Long = -1L
- parts.forEach { (name, bytes) ->
- addBinaryBody(
- name,
- bytes,
- ContentType.parseLenient(field.contentType),
- field.filename().getOrNull(),
- )
+ override fun repeatable(): Boolean = false
+
+ override fun close() = bytes.close()
+ }
}
- }
+
+ addPart(
+ MultipartBody.Part.create(
+ name,
+ field.filename().getOrNull(),
+ field.contentType,
+ partBody,
+ )
+ )
}
- .build()
+ }
}
+ .build()
- private fun serializePart(
- name: String,
- node: JsonNode,
- ): Sequence> =
- when (node.nodeType) {
- JsonNodeType.MISSING,
- JsonNodeType.NULL -> emptySequence()
- JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream())
- JsonNodeType.STRING -> sequenceOf(name to node.textValue().inputStream())
- JsonNodeType.BOOLEAN ->
- sequenceOf(name to node.booleanValue().toString().inputStream())
- JsonNodeType.NUMBER ->
- sequenceOf(name to node.numberValue().toString().inputStream())
- JsonNodeType.ARRAY ->
- sequenceOf(
- name to
- node
- .elements()
- .asSequence()
- .mapNotNull { element ->
- when (element.nodeType) {
- JsonNodeType.MISSING,
- JsonNodeType.NULL -> null
- JsonNodeType.STRING -> node.textValue()
- JsonNodeType.BOOLEAN -> node.booleanValue().toString()
- JsonNodeType.NUMBER -> node.numberValue().toString()
- null,
- JsonNodeType.BINARY,
- JsonNodeType.ARRAY,
- JsonNodeType.OBJECT,
- JsonNodeType.POJO ->
- throw CourierInvalidDataException(
- "Unexpected JsonNode type in array: ${node.nodeType}"
- )
- }
- }
- .joinToString(",")
- .inputStream()
- )
- JsonNodeType.OBJECT ->
- node.fields().asSequence().flatMap { (key, value) ->
- serializePart("$name[$key]", value)
- }
- JsonNodeType.POJO,
- null ->
- throw CourierInvalidDataException("Unexpected JsonNode type: ${node.nodeType}")
+private fun serializePart(name: String, node: JsonNode): Sequence> =
+ when (node.nodeType) {
+ JsonNodeType.MISSING,
+ JsonNodeType.NULL -> emptySequence()
+ JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream())
+ JsonNodeType.STRING -> sequenceOf(name to node.textValue().byteInputStream())
+ JsonNodeType.BOOLEAN -> sequenceOf(name to node.booleanValue().toString().byteInputStream())
+ JsonNodeType.NUMBER -> sequenceOf(name to node.numberValue().toString().byteInputStream())
+ JsonNodeType.ARRAY ->
+ sequenceOf(
+ name to
+ node
+ .elements()
+ .asSequence()
+ .mapNotNull { element ->
+ when (element.nodeType) {
+ JsonNodeType.MISSING,
+ JsonNodeType.NULL -> null
+ JsonNodeType.STRING -> element.textValue()
+ JsonNodeType.BOOLEAN -> element.booleanValue().toString()
+ JsonNodeType.NUMBER -> element.numberValue().toString()
+ null,
+ JsonNodeType.BINARY,
+ JsonNodeType.ARRAY,
+ JsonNodeType.OBJECT,
+ JsonNodeType.POJO ->
+ throw CourierInvalidDataException(
+ "Unexpected JsonNode type in array: ${element.nodeType}"
+ )
+ }
+ }
+ .joinToString(",")
+ .byteInputStream()
+ )
+ JsonNodeType.OBJECT ->
+ node.fields().asSequence().flatMap { (key, value) ->
+ serializePart("$name[$key]", value)
+ }
+ JsonNodeType.POJO,
+ null -> throw CourierInvalidDataException("Unexpected JsonNode type: ${node.nodeType}")
+ }
+
+private class MultipartBody
+private constructor(private val boundary: String, private val parts: List) : HttpRequestBody {
+ private val boundaryBytes: ByteArray = boundary.toByteArray()
+ private val contentType = "multipart/form-data; boundary=$boundary"
+
+ // This must remain in sync with `contentLength`.
+ override fun writeTo(outputStream: OutputStream) {
+ parts.forEach { part ->
+ outputStream.write(DASHDASH)
+ outputStream.write(boundaryBytes)
+ outputStream.write(CRLF)
+
+ outputStream.write(CONTENT_DISPOSITION)
+ outputStream.write(part.contentDisposition.toByteArray())
+ outputStream.write(CRLF)
+
+ outputStream.write(CONTENT_TYPE)
+ outputStream.write(part.contentType.toByteArray())
+ outputStream.write(CRLF)
+
+ outputStream.write(CRLF)
+ part.body.writeTo(outputStream)
+ outputStream.write(CRLF)
+ }
+
+ outputStream.write(DASHDASH)
+ outputStream.write(boundaryBytes)
+ outputStream.write(DASHDASH)
+ outputStream.write(CRLF)
+ }
+
+ override fun contentType(): String = contentType
+
+ // This must remain in sync with `writeTo`.
+ override fun contentLength(): Long {
+ var byteCount = 0L
+
+ parts.forEach { part ->
+ val contentLength = part.body.contentLength()
+ if (contentLength == -1L) {
+ return -1L
}
- private fun String.inputStream(): InputStream = toByteArray().inputStream()
+ byteCount +=
+ DASHDASH.size +
+ boundaryBytes.size +
+ CRLF.size +
+ CONTENT_DISPOSITION.size +
+ part.contentDisposition.toByteArray().size +
+ CRLF.size +
+ CONTENT_TYPE.size +
+ part.contentType.toByteArray().size +
+ CRLF.size +
+ CRLF.size +
+ contentLength +
+ CRLF.size
+ }
- override fun writeTo(outputStream: OutputStream) = entity.writeTo(outputStream)
+ byteCount += DASHDASH.size + boundaryBytes.size + DASHDASH.size + CRLF.size
+ return byteCount
+ }
- override fun contentType(): String = entity.contentType
+ override fun repeatable(): Boolean = parts.all { it.body.repeatable() }
- override fun contentLength(): Long = entity.contentLength
+ override fun close() {
+ parts.forEach { it.body.close() }
+ }
- override fun repeatable(): Boolean = entity.isRepeatable
+ class Builder {
+ private val boundary = UUID.randomUUID().toString()
+ private val parts: MutableList = mutableListOf()
- override fun close() = entity.close()
+ fun addPart(part: Part) = apply { parts.add(part) }
+
+ fun build() = MultipartBody(boundary, parts.toImmutable())
+ }
+
+ class Part
+ private constructor(
+ val contentDisposition: String,
+ val contentType: String,
+ val body: HttpRequestBody,
+ ) {
+ companion object {
+ fun create(
+ name: String,
+ filename: String?,
+ contentType: String,
+ body: HttpRequestBody,
+ ): Part {
+ val disposition = buildString {
+ append("form-data; name=")
+ appendQuotedString(name)
+ if (filename != null) {
+ append("; filename=")
+ appendQuotedString(filename)
+ }
+ }
+ return Part(disposition, contentType, body)
+ }
+ }
+ }
+
+ companion object {
+ private val CRLF = byteArrayOf('\r'.code.toByte(), '\n'.code.toByte())
+ private val DASHDASH = byteArrayOf('-'.code.toByte(), '-'.code.toByte())
+ private val CONTENT_DISPOSITION = "Content-Disposition: ".toByteArray()
+ private val CONTENT_TYPE = "Content-Type: ".toByteArray()
+
+ private fun StringBuilder.appendQuotedString(key: String) {
+ append('"')
+ for (ch in key) {
+ when (ch) {
+ '\n' -> append("%0A")
+ '\r' -> append("%0D")
+ '"' -> append("%22")
+ else -> append(ch)
+ }
+ }
+ append('"')
+ }
}
+}
diff --git a/courier-java-core/src/main/kotlin/com/courier/core/http/RetryingHttpClient.kt b/courier-java-core/src/main/kotlin/com/courier/core/http/RetryingHttpClient.kt
index 91211328..82315391 100644
--- a/courier-java-core/src/main/kotlin/com/courier/core/http/RetryingHttpClient.kt
+++ b/courier-java-core/src/main/kotlin/com/courier/core/http/RetryingHttpClient.kt
@@ -1,3 +1,5 @@
+// File generated from our OpenAPI spec by Stainless.
+
package com.courier.core.http
import com.courier.core.DefaultSleeper
@@ -199,7 +201,7 @@ private constructor(
?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter ->
retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1))
?: try {
- ChronoUnit.MILLIS.between(
+ ChronoUnit.NANOS.between(
OffsetDateTime.now(clock),
OffsetDateTime.parse(
retryAfter,
@@ -212,13 +214,8 @@ private constructor(
}
}
?.let { retryAfterNanos ->
- // If the API asks us to wait a certain amount of time (and it's a reasonable
- // amount), just
- // do what it says.
- val retryAfter = Duration.ofNanos(retryAfterNanos.toLong())
- if (retryAfter in Duration.ofNanos(0)..Duration.ofMinutes(1)) {
- return retryAfter
- }
+ // If the API asks us to wait a certain amount of time, do what it says.
+ return Duration.ofNanos(retryAfterNanos.toLong())
}
// Apply exponential backoff, but not more than the max.
diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt
index ec80329c..e3659f80 100644
--- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt
+++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt
@@ -16,7 +16,6 @@ import com.fasterxml.jackson.annotation.JsonCreator
import com.fasterxml.jackson.annotation.JsonProperty
import java.util.Collections
import java.util.Objects
-import java.util.Optional
import kotlin.jvm.optionals.getOrNull
class ElementalContent
@@ -24,7 +23,6 @@ class ElementalContent
private constructor(
private val elements: JsonField>,
private val version: JsonField,
- private val brand: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -34,8 +32,7 @@ private constructor(
@ExcludeMissing
elements: JsonField> = JsonMissing.of(),
@JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of(),
- @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(),
- ) : this(elements, version, brand, mutableMapOf())
+ ) : this(elements, version, mutableMapOf())
/**
* @throws CourierInvalidDataException if the JSON field has an unexpected type or is
@@ -51,12 +48,6 @@ private constructor(
*/
fun version(): String = version.getRequired("version")
- /**
- * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
- * server responded with an unexpected value).
- */
- fun brand(): Optional = brand.getOptional("brand")
-
/**
* Returns the raw JSON value of [elements].
*
@@ -73,13 +64,6 @@ private constructor(
*/
@JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version
- /**
- * Returns the raw JSON value of [brand].
- *
- * Unlike [brand], this method doesn't throw if the JSON field has an unexpected type.
- */
- @JsonProperty("brand") @ExcludeMissing fun _brand(): JsonField = brand
-
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
additionalProperties.put(key, value)
@@ -111,14 +95,12 @@ private constructor(
private var elements: JsonField>? = null
private var version: JsonField? = null
- private var brand: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@JvmSynthetic
internal fun from(elementalContent: ElementalContent) = apply {
elements = elementalContent.elements.map { it.toMutableList() }
version = elementalContent.version
- brand = elementalContent.brand
additionalProperties = elementalContent.additionalProperties.toMutableMap()
}
@@ -205,19 +187,6 @@ private constructor(
*/
fun version(version: JsonField) = apply { this.version = version }
- fun brand(brand: String?) = brand(JsonField.ofNullable(brand))
-
- /** Alias for calling [Builder.brand] with `brand.orElse(null)`. */
- fun brand(brand: Optional) = brand(brand.getOrNull())
-
- /**
- * Sets [Builder.brand] to an arbitrary JSON value.
- *
- * You should usually call [Builder.brand] with a well-typed [String] value instead. This
- * method is primarily for setting the field to an undocumented or not yet supported value.
- */
- fun brand(brand: JsonField) = apply { this.brand = brand }
-
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
putAllAdditionalProperties(additionalProperties)
@@ -254,7 +223,6 @@ private constructor(
ElementalContent(
checkRequired("elements", elements).map { it.toImmutable() },
checkRequired("version", version),
- brand,
additionalProperties.toMutableMap(),
)
}
@@ -268,7 +236,6 @@ private constructor(
elements().forEach { it.validate() }
version()
- brand()
validated = true
}
@@ -288,8 +255,7 @@ private constructor(
@JvmSynthetic
internal fun validity(): Int =
(elements.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) +
- (if (version.asKnown().isPresent) 1 else 0) +
- (if (brand.asKnown().isPresent) 1 else 0)
+ (if (version.asKnown().isPresent) 1 else 0)
override fun equals(other: Any?): Boolean {
if (this === other) {
@@ -299,16 +265,13 @@ private constructor(
return other is ElementalContent &&
elements == other.elements &&
version == other.version &&
- brand == other.brand &&
additionalProperties == other.additionalProperties
}
- private val hashCode: Int by lazy {
- Objects.hash(elements, version, brand, additionalProperties)
- }
+ private val hashCode: Int by lazy { Objects.hash(elements, version, additionalProperties) }
override fun hashCode(): Int = hashCode
override fun toString() =
- "ElementalContent{elements=$elements, version=$version, brand=$brand, additionalProperties=$additionalProperties}"
+ "ElementalContent{elements=$elements, version=$version, additionalProperties=$additionalProperties}"
}
diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt
new file mode 100644
index 00000000..71feee7c
--- /dev/null
+++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt
@@ -0,0 +1,458 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.courier.models.journeys
+
+import com.courier.core.Enum
+import com.courier.core.ExcludeMissing
+import com.courier.core.JsonField
+import com.courier.core.JsonMissing
+import com.courier.core.JsonValue
+import com.courier.core.checkRequired
+import com.courier.errors.CourierInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.time.OffsetDateTime
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+/** A journey template representing an automation workflow. */
+class Journey
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val id: JsonField,
+ private val name: JsonField,
+ private val version: JsonField,
+ private val createdAt: JsonField,
+ private val updatedAt: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(),
+ @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(),
+ @JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of(),
+ @JsonProperty("createdAt")
+ @ExcludeMissing
+ createdAt: JsonField = JsonMissing.of(),
+ @JsonProperty("updatedAt")
+ @ExcludeMissing
+ updatedAt: JsonField = JsonMissing.of(),
+ ) : this(id, name, version, createdAt, updatedAt, mutableMapOf())
+
+ /**
+ * The unique identifier of the journey.
+ *
+ * @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 id(): String = id.getRequired("id")
+
+ /**
+ * The name of the journey.
+ *
+ * @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 name(): String = name.getRequired("name")
+
+ /**
+ * The version of the journey (published or draft).
+ *
+ * @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 version(): Version = version.getRequired("version")
+
+ /**
+ * ISO 8601 timestamp when the journey was created.
+ *
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun createdAt(): Optional = createdAt.getOptional("createdAt")
+
+ /**
+ * ISO 8601 timestamp when the journey was last updated.
+ *
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun updatedAt(): Optional = updatedAt.getOptional("updatedAt")
+
+ /**
+ * Returns the raw JSON value of [id].
+ *
+ * Unlike [id], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id
+
+ /**
+ * Returns the raw JSON value of [name].
+ *
+ * Unlike [name], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name
+
+ /**
+ * Returns the raw JSON value of [version].
+ *
+ * Unlike [version], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version
+
+ /**
+ * Returns the raw JSON value of [createdAt].
+ *
+ * Unlike [createdAt], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("createdAt")
+ @ExcludeMissing
+ fun _createdAt(): JsonField = createdAt
+
+ /**
+ * Returns the raw JSON value of [updatedAt].
+ *
+ * Unlike [updatedAt], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("updatedAt")
+ @ExcludeMissing
+ fun _updatedAt(): JsonField = updatedAt
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [Journey].
+ *
+ * The following fields are required:
+ * ```java
+ * .id()
+ * .name()
+ * .version()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [Journey]. */
+ class Builder internal constructor() {
+
+ private var id: JsonField? = null
+ private var name: JsonField? = null
+ private var version: JsonField? = null
+ private var createdAt: JsonField = JsonMissing.of()
+ private var updatedAt: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(journey: Journey) = apply {
+ id = journey.id
+ name = journey.name
+ version = journey.version
+ createdAt = journey.createdAt
+ updatedAt = journey.updatedAt
+ additionalProperties = journey.additionalProperties.toMutableMap()
+ }
+
+ /** The unique identifier of the journey. */
+ fun id(id: String) = id(JsonField.of(id))
+
+ /**
+ * Sets [Builder.id] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.id] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun id(id: JsonField) = apply { this.id = id }
+
+ /** The name of the journey. */
+ fun name(name: String) = name(JsonField.of(name))
+
+ /**
+ * Sets [Builder.name] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.name] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun name(name: JsonField) = apply { this.name = name }
+
+ /** The version of the journey (published or draft). */
+ fun version(version: Version) = version(JsonField.of(version))
+
+ /**
+ * Sets [Builder.version] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.version] with a well-typed [Version] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun version(version: JsonField) = apply { this.version = version }
+
+ /** ISO 8601 timestamp when the journey was created. */
+ fun createdAt(createdAt: OffsetDateTime) = createdAt(JsonField.of(createdAt))
+
+ /**
+ * Sets [Builder.createdAt] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.createdAt] with a well-typed [OffsetDateTime] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun createdAt(createdAt: JsonField) = apply { this.createdAt = createdAt }
+
+ /** ISO 8601 timestamp when the journey was last updated. */
+ fun updatedAt(updatedAt: OffsetDateTime) = updatedAt(JsonField.of(updatedAt))
+
+ /**
+ * Sets [Builder.updatedAt] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.updatedAt] with a well-typed [OffsetDateTime] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun updatedAt(updatedAt: JsonField) = apply { this.updatedAt = updatedAt }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [Journey].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .id()
+ * .name()
+ * .version()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Journey =
+ Journey(
+ checkRequired("id", id),
+ checkRequired("name", name),
+ checkRequired("version", version),
+ createdAt,
+ updatedAt,
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Journey = apply {
+ if (validated) {
+ return@apply
+ }
+
+ id()
+ name()
+ version().validate()
+ createdAt()
+ updatedAt()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (id.asKnown().isPresent) 1 else 0) +
+ (if (name.asKnown().isPresent) 1 else 0) +
+ (version.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (createdAt.asKnown().isPresent) 1 else 0) +
+ (if (updatedAt.asKnown().isPresent) 1 else 0)
+
+ /** The version of the journey (published or draft). */
+ class Version @JsonCreator private constructor(private val value: JsonField) : Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val PUBLISHED = of("published")
+
+ @JvmField val DRAFT = of("draft")
+
+ @JvmStatic fun of(value: String) = Version(JsonField.of(value))
+ }
+
+ /** An enum containing [Version]'s known values. */
+ enum class Known {
+ PUBLISHED,
+ DRAFT,
+ }
+
+ /**
+ * An enum containing [Version]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Version] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ PUBLISHED,
+ DRAFT,
+ /** An enum member indicating that [Version] was instantiated with an unknown value. */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ PUBLISHED -> Value.PUBLISHED
+ DRAFT -> Value.DRAFT
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws CourierInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ PUBLISHED -> Known.PUBLISHED
+ DRAFT -> Known.DRAFT
+ else -> throw CourierInvalidDataException("Unknown Version: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws CourierInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") }
+
+ private var validated: Boolean = false
+
+ fun validate(): Version = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Version && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Journey &&
+ id == other.id &&
+ name == other.name &&
+ version == other.version &&
+ createdAt == other.createdAt &&
+ updatedAt == other.updatedAt &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(id, name, version, createdAt, updatedAt, additionalProperties)
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Journey{id=$id, name=$name, version=$version, createdAt=$createdAt, updatedAt=$updatedAt, additionalProperties=$additionalProperties}"
+}
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
new file mode 100644
index 00000000..d4585542
--- /dev/null
+++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt
@@ -0,0 +1,234 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.courier.models.journeys
+
+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
+
+/** Invoke a journey run from a journey template. */
+class JourneyInvokeParams
+private constructor(
+ private val templateId: String?,
+ private val journeysInvokeRequest: JourneysInvokeRequest,
+ private val additionalHeaders: Headers,
+ private val additionalQueryParams: QueryParams,
+) : Params {
+
+ fun templateId(): Optional = Optional.ofNullable(templateId)
+
+ /**
+ * 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
+ * profile/data objects (user_id, userId, or anonymousId fields).
+ */
+ fun journeysInvokeRequest(): JourneysInvokeRequest = journeysInvokeRequest
+
+ fun _additionalBodyProperties(): Map =
+ journeysInvokeRequest._additionalProperties()
+
+ /** 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 [JourneyInvokeParams].
+ *
+ * The following fields are required:
+ * ```java
+ * .journeysInvokeRequest()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [JourneyInvokeParams]. */
+ class Builder internal constructor() {
+
+ private var templateId: String? = null
+ private var journeysInvokeRequest: JourneysInvokeRequest? = null
+ private var additionalHeaders: Headers.Builder = Headers.builder()
+ private var additionalQueryParams: QueryParams.Builder = QueryParams.builder()
+
+ @JvmSynthetic
+ internal fun from(journeyInvokeParams: JourneyInvokeParams) = apply {
+ templateId = journeyInvokeParams.templateId
+ journeysInvokeRequest = journeyInvokeParams.journeysInvokeRequest
+ additionalHeaders = journeyInvokeParams.additionalHeaders.toBuilder()
+ additionalQueryParams = journeyInvokeParams.additionalQueryParams.toBuilder()
+ }
+
+ fun templateId(templateId: String?) = apply { this.templateId = templateId }
+
+ /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */
+ fun templateId(templateId: Optional) = templateId(templateId.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
+ * profile/data objects (user_id, userId, or anonymousId fields).
+ */
+ fun journeysInvokeRequest(journeysInvokeRequest: JourneysInvokeRequest) = apply {
+ this.journeysInvokeRequest = journeysInvokeRequest
+ }
+
+ 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 [JourneyInvokeParams].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .journeysInvokeRequest()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): JourneyInvokeParams =
+ JourneyInvokeParams(
+ templateId,
+ checkRequired("journeysInvokeRequest", journeysInvokeRequest),
+ additionalHeaders.build(),
+ additionalQueryParams.build(),
+ )
+ }
+
+ fun _body(): JourneysInvokeRequest = journeysInvokeRequest
+
+ fun _pathParam(index: Int): String =
+ when (index) {
+ 0 -> templateId ?: ""
+ 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 JourneyInvokeParams &&
+ templateId == other.templateId &&
+ journeysInvokeRequest == other.journeysInvokeRequest &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
+ }
+
+ override fun hashCode(): Int =
+ Objects.hash(templateId, journeysInvokeRequest, additionalHeaders, additionalQueryParams)
+
+ override fun toString() =
+ "JourneyInvokeParams{templateId=$templateId, 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
new file mode 100644
index 00000000..33c24c7c
--- /dev/null
+++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt
@@ -0,0 +1,356 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.courier.models.journeys
+
+import com.courier.core.Enum
+import com.courier.core.JsonField
+import com.courier.core.Params
+import com.courier.core.http.Headers
+import com.courier.core.http.QueryParams
+import com.courier.errors.CourierInvalidDataException
+import com.fasterxml.jackson.annotation.JsonCreator
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+/** Get the list of journeys. */
+class JourneyListParams
+private constructor(
+ private val cursor: String?,
+ private val version: Version?,
+ private val additionalHeaders: Headers,
+ private val additionalQueryParams: QueryParams,
+) : Params {
+
+ /**
+ * A cursor token for pagination. Use the cursor from the previous response to fetch the next
+ * page of results.
+ */
+ fun cursor(): Optional = Optional.ofNullable(cursor)
+
+ /**
+ * The version of journeys to retrieve. Accepted values are published (for published journeys)
+ * or draft (for draft journeys). Defaults to published.
+ */
+ fun version(): Optional = Optional.ofNullable(version)
+
+ /** 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(): JourneyListParams = builder().build()
+
+ /** Returns a mutable builder for constructing an instance of [JourneyListParams]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [JourneyListParams]. */
+ class Builder internal constructor() {
+
+ private var cursor: String? = null
+ private var version: Version? = null
+ private var additionalHeaders: Headers.Builder = Headers.builder()
+ private var additionalQueryParams: QueryParams.Builder = QueryParams.builder()
+
+ @JvmSynthetic
+ internal fun from(journeyListParams: JourneyListParams) = apply {
+ cursor = journeyListParams.cursor
+ version = journeyListParams.version
+ additionalHeaders = journeyListParams.additionalHeaders.toBuilder()
+ additionalQueryParams = journeyListParams.additionalQueryParams.toBuilder()
+ }
+
+ /**
+ * A cursor token for pagination. Use the cursor from the previous response to fetch the
+ * next page of results.
+ */
+ fun cursor(cursor: String?) = apply { this.cursor = cursor }
+
+ /** Alias for calling [Builder.cursor] with `cursor.orElse(null)`. */
+ fun cursor(cursor: Optional) = cursor(cursor.getOrNull())
+
+ /**
+ * The version of journeys to retrieve. Accepted values are published (for published
+ * journeys) or draft (for draft journeys). Defaults to published.
+ */
+ fun version(version: Version?) = apply { this.version = version }
+
+ /** Alias for calling [Builder.version] with `version.orElse(null)`. */
+ fun version(version: Optional) = version(version.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)
+ }
+
+ /**
+ * Returns an immutable instance of [JourneyListParams].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): JourneyListParams =
+ JourneyListParams(
+ cursor,
+ version,
+ additionalHeaders.build(),
+ additionalQueryParams.build(),
+ )
+ }
+
+ override fun _headers(): Headers = additionalHeaders
+
+ override fun _queryParams(): QueryParams =
+ QueryParams.builder()
+ .apply {
+ cursor?.let { put("cursor", it) }
+ version?.let { put("version", it.toString()) }
+ putAll(additionalQueryParams)
+ }
+ .build()
+
+ /**
+ * The version of journeys to retrieve. Accepted values are published (for published journeys)
+ * or draft (for draft journeys). Defaults to published.
+ */
+ class Version @JsonCreator private constructor(private val value: JsonField) : Enum {
+
+ /**
+ * Returns this class instance's raw value.
+ *
+ * This is usually only useful if this instance was deserialized from data that doesn't
+ * match any known member, and you want to know that value. For example, if the SDK is on an
+ * older version than the API, then the API may respond with new members that the SDK is
+ * unaware of.
+ */
+ @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value
+
+ companion object {
+
+ @JvmField val PUBLISHED = of("published")
+
+ @JvmField val DRAFT = of("draft")
+
+ @JvmStatic fun of(value: String) = Version(JsonField.of(value))
+ }
+
+ /** An enum containing [Version]'s known values. */
+ enum class Known {
+ PUBLISHED,
+ DRAFT,
+ }
+
+ /**
+ * An enum containing [Version]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Version] can contain an unknown value in a couple of cases:
+ * - It was deserialized from data that doesn't match any known member. For example, if the
+ * SDK is on an older version than the API, then the API may respond with new members that
+ * the SDK is unaware of.
+ * - It was constructed with an arbitrary value using the [of] method.
+ */
+ enum class Value {
+ PUBLISHED,
+ DRAFT,
+ /** An enum member indicating that [Version] was instantiated with an unknown value. */
+ _UNKNOWN,
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN]
+ * if the class was instantiated with an unknown value.
+ *
+ * Use the [known] method instead if you're certain the value is always known or if you want
+ * to throw for the unknown case.
+ */
+ fun value(): Value =
+ when (this) {
+ PUBLISHED -> Value.PUBLISHED
+ DRAFT -> Value.DRAFT
+ else -> Value._UNKNOWN
+ }
+
+ /**
+ * Returns an enum member corresponding to this class instance's value.
+ *
+ * Use the [value] method instead if you're uncertain the value is always known and don't
+ * want to throw for the unknown case.
+ *
+ * @throws CourierInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ PUBLISHED -> Known.PUBLISHED
+ DRAFT -> Known.DRAFT
+ else -> throw CourierInvalidDataException("Unknown Version: $value")
+ }
+
+ /**
+ * Returns this class instance's primitive wire representation.
+ *
+ * This differs from the [toString] method because that method is primarily for debugging
+ * and generally doesn't throw.
+ *
+ * @throws CourierInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") }
+
+ private var validated: Boolean = false
+
+ fun validate(): Version = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Version && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is JourneyListParams &&
+ cursor == other.cursor &&
+ version == other.version &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
+ }
+
+ override fun hashCode(): Int =
+ Objects.hash(cursor, version, additionalHeaders, additionalQueryParams)
+
+ override fun toString() =
+ "JourneyListParams{cursor=$cursor, version=$version, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
+}
diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt
new file mode 100644
index 00000000..91df020a
--- /dev/null
+++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt
@@ -0,0 +1,461 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.courier.models.journeys
+
+import com.courier.core.ExcludeMissing
+import com.courier.core.JsonField
+import com.courier.core.JsonMissing
+import com.courier.core.JsonValue
+import com.courier.core.toImmutable
+import com.courier.errors.CourierInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.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 profile/data
+ * objects (user_id, userId, or anonymousId fields).
+ */
+class JourneysInvokeRequest
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val data: JsonField,
+ private val profile: JsonField,
+ private val userId: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(),
+ @JsonProperty("profile") @ExcludeMissing profile: JsonField = JsonMissing.of(),
+ @JsonProperty("user_id") @ExcludeMissing userId: JsonField = JsonMissing.of(),
+ ) : this(data, profile, userId, mutableMapOf())
+
+ /**
+ * Data payload passed to the journey. The expected shape can be predefined using the schema
+ * builder in the journey editor. This data is available in journey steps for condition
+ * evaluation and template variable interpolation. Can also contain user identifiers (user_id,
+ * userId, anonymousId) if not provided elsewhere.
+ *
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun data(): Optional = data.getOptional("data")
+
+ /**
+ * Profile data for the user. Can contain contact information (email, phone_number), user
+ * identifiers (user_id, userId, anonymousId), or any custom profile fields. Profile fields are
+ * merged with any existing stored profile for the user. Include context.tenant_id to load a
+ * tenant-scoped profile for multi-tenant scenarios.
+ *
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun profile(): Optional = profile.getOptional("profile")
+
+ /**
+ * A unique identifier for the user. If not provided, the system will attempt to resolve the
+ * user identifier from profile or data objects.
+ *
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun userId(): Optional = userId.getOptional("user_id")
+
+ /**
+ * Returns the raw JSON value of [data].
+ *
+ * Unlike [data], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data
+
+ /**
+ * Returns the raw JSON value of [profile].
+ *
+ * Unlike [profile], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("profile") @ExcludeMissing fun _profile(): JsonField = profile
+
+ /**
+ * Returns the raw JSON value of [userId].
+ *
+ * Unlike [userId], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("user_id") @ExcludeMissing fun _userId(): JsonField = userId
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [JourneysInvokeRequest]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [JourneysInvokeRequest]. */
+ class Builder internal constructor() {
+
+ private var data: JsonField = JsonMissing.of()
+ private var profile: JsonField = JsonMissing.of()
+ private var userId: JsonField = JsonMissing.of()
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(journeysInvokeRequest: JourneysInvokeRequest) = apply {
+ data = journeysInvokeRequest.data
+ profile = journeysInvokeRequest.profile
+ userId = journeysInvokeRequest.userId
+ additionalProperties = journeysInvokeRequest.additionalProperties.toMutableMap()
+ }
+
+ /**
+ * Data payload passed to the journey. The expected shape can be predefined using the schema
+ * builder in the journey editor. This data is available in journey steps for condition
+ * evaluation and template variable interpolation. Can also contain user identifiers
+ * (user_id, userId, anonymousId) if not provided elsewhere.
+ */
+ fun data(data: Data) = data(JsonField.of(data))
+
+ /**
+ * Sets [Builder.data] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.data] with a well-typed [Data] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun data(data: JsonField) = apply { this.data = data }
+
+ /**
+ * Profile data for the user. Can contain contact information (email, phone_number), user
+ * identifiers (user_id, userId, anonymousId), or any custom profile fields. Profile fields
+ * are merged with any existing stored profile for the user. Include context.tenant_id to
+ * load a tenant-scoped profile for multi-tenant scenarios.
+ */
+ fun profile(profile: Profile) = profile(JsonField.of(profile))
+
+ /**
+ * Sets [Builder.profile] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.profile] with a well-typed [Profile] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun profile(profile: JsonField) = apply { this.profile = profile }
+
+ /**
+ * A unique identifier for the user. If not provided, the system will attempt to resolve the
+ * user identifier from profile or data objects.
+ */
+ fun userId(userId: String) = userId(JsonField.of(userId))
+
+ /**
+ * Sets [Builder.userId] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.userId] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun userId(userId: JsonField) = apply { this.userId = userId }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [JourneysInvokeRequest].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): JourneysInvokeRequest =
+ JourneysInvokeRequest(data, profile, userId, additionalProperties.toMutableMap())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): JourneysInvokeRequest = apply {
+ if (validated) {
+ return@apply
+ }
+
+ data().ifPresent { it.validate() }
+ profile().ifPresent { it.validate() }
+ userId()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (data.asKnown().getOrNull()?.validity() ?: 0) +
+ (profile.asKnown().getOrNull()?.validity() ?: 0) +
+ (if (userId.asKnown().isPresent) 1 else 0)
+
+ /**
+ * Data payload passed to the journey. The expected shape can be predefined using the schema
+ * builder in the journey editor. This data is available in journey steps for condition
+ * evaluation and template variable interpolation. Can also contain user identifiers (user_id,
+ * userId, anonymousId) if not provided elsewhere.
+ */
+ class Data
+ @JsonCreator
+ private constructor(
+ @com.fasterxml.jackson.annotation.JsonValue
+ private val additionalProperties: Map
+ ) {
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map = additionalProperties
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [Data]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [Data]. */
+ class Builder internal constructor() {
+
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(data: Data) = apply {
+ additionalProperties = data.additionalProperties.toMutableMap()
+ }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [Data].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): Data = Data(additionalProperties.toImmutable())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Data = apply {
+ if (validated) {
+ return@apply
+ }
+
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Data && additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() = "Data{additionalProperties=$additionalProperties}"
+ }
+
+ /**
+ * Profile data for the user. Can contain contact information (email, phone_number), user
+ * identifiers (user_id, userId, anonymousId), or any custom profile fields. Profile fields are
+ * merged with any existing stored profile for the user. Include context.tenant_id to load a
+ * tenant-scoped profile for multi-tenant scenarios.
+ */
+ class Profile
+ @JsonCreator
+ private constructor(
+ @com.fasterxml.jackson.annotation.JsonValue
+ private val additionalProperties: Map
+ ) {
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map = additionalProperties
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [Profile]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [Profile]. */
+ class Builder internal constructor() {
+
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(profile: Profile) = apply {
+ additionalProperties = profile.additionalProperties.toMutableMap()
+ }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [Profile].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): Profile = Profile(additionalProperties.toImmutable())
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Profile = apply {
+ if (validated) {
+ return@apply
+ }
+
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is Profile && additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() = "Profile{additionalProperties=$additionalProperties}"
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is JourneysInvokeRequest &&
+ data == other.data &&
+ profile == other.profile &&
+ userId == other.userId &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(data, profile, userId, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "JourneysInvokeRequest{data=$data, profile=$profile, userId=$userId, additionalProperties=$additionalProperties}"
+}
diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt
new file mode 100644
index 00000000..06b82bad
--- /dev/null
+++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt
@@ -0,0 +1,173 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.courier.models.journeys
+
+import com.courier.core.ExcludeMissing
+import com.courier.core.JsonField
+import com.courier.core.JsonMissing
+import com.courier.core.JsonValue
+import com.courier.core.checkRequired
+import com.courier.errors.CourierInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+
+class JourneysInvokeResponse
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val runId: JsonField,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("runId") @ExcludeMissing runId: JsonField = JsonMissing.of()
+ ) : this(runId, mutableMapOf())
+
+ /**
+ * A unique identifier for the journey run that was created.
+ *
+ * @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 runId(): String = runId.getRequired("runId")
+
+ /**
+ * Returns the raw JSON value of [runId].
+ *
+ * Unlike [runId], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("runId") @ExcludeMissing fun _runId(): JsonField = runId
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /**
+ * Returns a mutable builder for constructing an instance of [JourneysInvokeResponse].
+ *
+ * The following fields are required:
+ * ```java
+ * .runId()
+ * ```
+ */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [JourneysInvokeResponse]. */
+ class Builder internal constructor() {
+
+ private var runId: JsonField? = null
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(journeysInvokeResponse: JourneysInvokeResponse) = apply {
+ runId = journeysInvokeResponse.runId
+ additionalProperties = journeysInvokeResponse.additionalProperties.toMutableMap()
+ }
+
+ /** A unique identifier for the journey run that was created. */
+ fun runId(runId: String) = runId(JsonField.of(runId))
+
+ /**
+ * Sets [Builder.runId] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.runId] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun runId(runId: JsonField) = apply { this.runId = runId }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [JourneysInvokeResponse].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```java
+ * .runId()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): JourneysInvokeResponse =
+ JourneysInvokeResponse(
+ checkRequired("runId", runId),
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): JourneysInvokeResponse = apply {
+ if (validated) {
+ return@apply
+ }
+
+ runId()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic internal fun validity(): Int = (if (runId.asKnown().isPresent) 1 else 0)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is JourneysInvokeResponse &&
+ runId == other.runId &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(runId, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "JourneysInvokeResponse{runId=$runId, additionalProperties=$additionalProperties}"
+}
diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt
new file mode 100644
index 00000000..2ba010ef
--- /dev/null
+++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt
@@ -0,0 +1,214 @@
+// File generated from our OpenAPI spec by Stainless.
+
+package com.courier.models.journeys
+
+import com.courier.core.ExcludeMissing
+import com.courier.core.JsonField
+import com.courier.core.JsonMissing
+import com.courier.core.JsonValue
+import com.courier.core.checkKnown
+import com.courier.core.toImmutable
+import com.courier.errors.CourierInvalidDataException
+import com.fasterxml.jackson.annotation.JsonAnyGetter
+import com.fasterxml.jackson.annotation.JsonAnySetter
+import com.fasterxml.jackson.annotation.JsonCreator
+import com.fasterxml.jackson.annotation.JsonProperty
+import java.util.Collections
+import java.util.Objects
+import java.util.Optional
+import kotlin.jvm.optionals.getOrNull
+
+class JourneysListResponse
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
+private constructor(
+ private val cursor: JsonField,
+ private val templates: JsonField>,
+ private val additionalProperties: MutableMap,
+) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("cursor") @ExcludeMissing cursor: JsonField = JsonMissing.of(),
+ @JsonProperty("templates")
+ @ExcludeMissing
+ templates: JsonField> = JsonMissing.of(),
+ ) : this(cursor, templates, mutableMapOf())
+
+ /**
+ * A cursor token for pagination. Present when there are more results available.
+ *
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun cursor(): Optional = cursor.getOptional("cursor")
+
+ /**
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
+ */
+ fun templates(): Optional> = templates.getOptional("templates")
+
+ /**
+ * Returns the raw JSON value of [cursor].
+ *
+ * Unlike [cursor], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("cursor") @ExcludeMissing fun _cursor(): JsonField = cursor
+
+ /**
+ * Returns the raw JSON value of [templates].
+ *
+ * Unlike [templates], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("templates")
+ @ExcludeMissing
+ fun _templates(): JsonField> = templates
+
+ @JsonAnySetter
+ private fun putAdditionalProperty(key: String, value: JsonValue) {
+ additionalProperties.put(key, value)
+ }
+
+ @JsonAnyGetter
+ @ExcludeMissing
+ fun _additionalProperties(): Map =
+ Collections.unmodifiableMap(additionalProperties)
+
+ fun toBuilder() = Builder().from(this)
+
+ companion object {
+
+ /** Returns a mutable builder for constructing an instance of [JourneysListResponse]. */
+ @JvmStatic fun builder() = Builder()
+ }
+
+ /** A builder for [JourneysListResponse]. */
+ class Builder internal constructor() {
+
+ private var cursor: JsonField = JsonMissing.of()
+ private var templates: JsonField>? = null
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ @JvmSynthetic
+ internal fun from(journeysListResponse: JourneysListResponse) = apply {
+ cursor = journeysListResponse.cursor
+ templates = journeysListResponse.templates.map { it.toMutableList() }
+ additionalProperties = journeysListResponse.additionalProperties.toMutableMap()
+ }
+
+ /** A cursor token for pagination. Present when there are more results available. */
+ fun cursor(cursor: String) = cursor(JsonField.of(cursor))
+
+ /**
+ * Sets [Builder.cursor] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.cursor] with a well-typed [String] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun cursor(cursor: JsonField) = apply { this.cursor = cursor }
+
+ fun templates(templates: List) = templates(JsonField.of(templates))
+
+ /**
+ * Sets [Builder.templates] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.templates] with a well-typed `List` value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun templates(templates: JsonField>) = apply {
+ this.templates = templates.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [Journey] to [templates].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addTemplate(template: Journey) = apply {
+ templates =
+ (templates ?: JsonField.of(mutableListOf())).also {
+ checkKnown("templates", it).add(template)
+ }
+ }
+
+ fun additionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.clear()
+ putAllAdditionalProperties(additionalProperties)
+ }
+
+ fun putAdditionalProperty(key: String, value: JsonValue) = apply {
+ additionalProperties.put(key, value)
+ }
+
+ fun putAllAdditionalProperties(additionalProperties: Map) = apply {
+ this.additionalProperties.putAll(additionalProperties)
+ }
+
+ fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
+ /**
+ * Returns an immutable instance of [JourneysListResponse].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ */
+ fun build(): JourneysListResponse =
+ JourneysListResponse(
+ cursor,
+ (templates ?: JsonMissing.of()).map { it.toImmutable() },
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): JourneysListResponse = apply {
+ if (validated) {
+ return@apply
+ }
+
+ cursor()
+ templates().ifPresent { it.forEach { it.validate() } }
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: CourierInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ @JvmSynthetic
+ internal fun validity(): Int =
+ (if (cursor.asKnown().isPresent) 1 else 0) +
+ (templates.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0)
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return other is JourneysListResponse &&
+ cursor == other.cursor &&
+ templates == other.templates &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy { Objects.hash(cursor, templates, additionalProperties) }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "JourneysListResponse{cursor=$cursor, templates=$templates, additionalProperties=$additionalProperties}"
+}
diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt
index 885f927d..7c68c999 100644
--- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt
+++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt
@@ -22,49 +22,49 @@ class MessageDetails
@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
- private val clicked: JsonField,
- private val delivered: JsonField,
private val enqueued: JsonField,
private val event: JsonField,
private val notification: JsonField,
- private val opened: JsonField,
private val recipient: JsonField,
- private val sent: JsonField,
private val status: JsonField,
+ private val clicked: JsonField,
+ private val delivered: JsonField,
private val error: JsonField,
+ private val opened: JsonField,
private val reason: JsonField,
+ private val sent: JsonField,
private val additionalProperties: MutableMap,
) {
@JsonCreator
private constructor(
@JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(),
- @JsonProperty("clicked") @ExcludeMissing clicked: JsonField = JsonMissing.of(),
- @JsonProperty("delivered") @ExcludeMissing delivered: JsonField = JsonMissing.of(),
@JsonProperty("enqueued") @ExcludeMissing enqueued: JsonField = JsonMissing.of(),
@JsonProperty("event") @ExcludeMissing event: JsonField = JsonMissing.of(),
@JsonProperty("notification")
@ExcludeMissing
notification: JsonField = JsonMissing.of(),
- @JsonProperty("opened") @ExcludeMissing opened: JsonField = JsonMissing.of(),
@JsonProperty("recipient") @ExcludeMissing recipient: JsonField = JsonMissing.of(),
- @JsonProperty("sent") @ExcludeMissing sent: JsonField = JsonMissing.of(),
@JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(),
+ @JsonProperty("clicked") @ExcludeMissing clicked: JsonField = JsonMissing.of(),
+ @JsonProperty("delivered") @ExcludeMissing delivered: JsonField = JsonMissing.of(),
@JsonProperty("error") @ExcludeMissing error: JsonField = JsonMissing.of(),
+ @JsonProperty("opened") @ExcludeMissing opened: JsonField = JsonMissing.of(),
@JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(),
+ @JsonProperty("sent") @ExcludeMissing sent: JsonField = JsonMissing.of(),
) : this(
id,
- clicked,
- delivered,
enqueued,
event,
notification,
- opened,
recipient,
- sent,
status,
+ clicked,
+ delivered,
error,
+ opened,
reason,
+ sent,
mutableMapOf(),
)
@@ -76,24 +76,6 @@ private constructor(
*/
fun id(): String = id.getRequired("id")
- /**
- * A UTC timestamp at which the recipient clicked on a tracked link for the first time. Stored
- * as a millisecond representation of the Unix epoch.
- *
- * @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 clicked(): Long = clicked.getRequired("clicked")
-
- /**
- * A UTC timestamp at which the Integration provider delivered the message. Stored as a
- * millisecond representation of the Unix epoch.
- *
- * @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 delivered(): Long = delivered.getRequired("delivered")
-
/**
* A UTC timestamp at which Courier received the message request. Stored as a millisecond
* representation of the Unix epoch.
@@ -120,38 +102,38 @@ private constructor(
fun notification(): String = notification.getRequired("notification")
/**
- * A UTC timestamp at which the recipient opened a message for the first time. Stored as a
- * millisecond representation of the Unix epoch.
+ * A unique identifier associated with the recipient of the delivered message.
*
* @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 opened(): Long = opened.getRequired("opened")
+ fun recipient(): String = recipient.getRequired("recipient")
/**
- * A unique identifier associated with the recipient of the delivered message.
+ * The current status of the message.
*
* @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 recipient(): String = recipient.getRequired("recipient")
+ fun status(): Status = status.getRequired("status")
/**
- * A UTC timestamp at which Courier passed the message to the Integration provider. Stored as a
- * millisecond representation of the Unix epoch.
+ * A UTC timestamp at which the recipient clicked on a tracked link for the first time. Stored
+ * as a millisecond representation of the Unix epoch.
*
- * @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).
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
*/
- fun sent(): Long = sent.getRequired("sent")
+ fun clicked(): Optional = clicked.getOptional("clicked")
/**
- * The current status of the message.
+ * A UTC timestamp at which the Integration provider delivered the message. Stored as a
+ * millisecond representation of the Unix epoch.
*
- * @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).
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
*/
- fun status(): Status = status.getRequired("status")
+ fun delivered(): Optional = delivered.getOptional("delivered")
/**
* A message describing the error that occurred.
@@ -162,33 +144,37 @@ private constructor(
fun error(): Optional = error.getOptional("error")
/**
- * The reason for the current status of the message.
+ * A UTC timestamp at which the recipient opened a message for the first time. Stored as a
+ * millisecond representation of the Unix epoch.
*
* @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
* server responded with an unexpected value).
*/
- fun reason(): Optional = reason.getOptional("reason")
+ fun opened(): Optional = opened.getOptional("opened")
/**
- * Returns the raw JSON value of [id].
+ * The reason for the current status of the message.
*
- * Unlike [id], this method doesn't throw if the JSON field has an unexpected type.
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
*/
- @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id
+ fun reason(): Optional = reason.getOptional("reason")
/**
- * Returns the raw JSON value of [clicked].
+ * A UTC timestamp at which Courier passed the message to the Integration provider. Stored as a
+ * millisecond representation of the Unix epoch.
*
- * Unlike [clicked], this method doesn't throw if the JSON field has an unexpected type.
+ * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the
+ * server responded with an unexpected value).
*/
- @JsonProperty("clicked") @ExcludeMissing fun _clicked(): JsonField = clicked
+ fun sent(): Optional = sent.getOptional("sent")
/**
- * Returns the raw JSON value of [delivered].
+ * Returns the raw JSON value of [id].
*
- * Unlike [delivered], this method doesn't throw if the JSON field has an unexpected type.
+ * Unlike [id], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("delivered") @ExcludeMissing fun _delivered(): JsonField = delivered
+ @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id
/**
* Returns the raw JSON value of [enqueued].
@@ -214,32 +200,32 @@ private constructor(
fun _notification(): JsonField = notification
/**
- * Returns the raw JSON value of [opened].
+ * Returns the raw JSON value of [recipient].
*
- * Unlike [opened], this method doesn't throw if the JSON field has an unexpected type.
+ * Unlike [recipient], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("opened") @ExcludeMissing fun _opened(): JsonField = opened
+ @JsonProperty("recipient") @ExcludeMissing fun _recipient(): JsonField = recipient
/**
- * Returns the raw JSON value of [recipient].
+ * Returns the raw JSON value of [status].
*
- * Unlike [recipient], this method doesn't throw if the JSON field has an unexpected type.
+ * Unlike [status], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("recipient") @ExcludeMissing fun _recipient(): JsonField = recipient
+ @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status
/**
- * Returns the raw JSON value of [sent].
+ * Returns the raw JSON value of [clicked].
*
- * Unlike [sent], this method doesn't throw if the JSON field has an unexpected type.
+ * Unlike [clicked], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("sent") @ExcludeMissing fun _sent(): JsonField = sent
+ @JsonProperty("clicked") @ExcludeMissing fun _clicked(): JsonField = clicked
/**
- * Returns the raw JSON value of [status].
+ * Returns the raw JSON value of [delivered].
*
- * Unlike [status], this method doesn't throw if the JSON field has an unexpected type.
+ * Unlike [delivered], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status
+ @JsonProperty("delivered") @ExcludeMissing fun _delivered(): JsonField = delivered
/**
* Returns the raw JSON value of [error].
@@ -248,6 +234,13 @@ private constructor(
*/
@JsonProperty("error") @ExcludeMissing fun _error(): JsonField = error
+ /**
+ * Returns the raw JSON value of [opened].
+ *
+ * Unlike [opened], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("opened") @ExcludeMissing fun _opened(): JsonField = opened
+
/**
* Returns the raw JSON value of [reason].
*
@@ -255,6 +248,13 @@ private constructor(
*/
@JsonProperty("reason") @ExcludeMissing fun _reason(): JsonField = reason
+ /**
+ * Returns the raw JSON value of [sent].
+ *
+ * Unlike [sent], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("sent") @ExcludeMissing fun _sent(): JsonField = sent
+
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
additionalProperties.put(key, value)
@@ -275,14 +275,10 @@ private constructor(
* The following fields are required:
* ```java
* .id()
- * .clicked()
- * .delivered()
* .enqueued()
* .event()
* .notification()
- * .opened()
* .recipient()
- * .sent()
* .status()
* ```
*/
@@ -293,33 +289,33 @@ private constructor(
class Builder internal constructor() {
private var id: JsonField? = null
- private var clicked: JsonField? = null
- private var delivered: JsonField? = null
private var enqueued: JsonField? = null
private var event: JsonField? = null
private var notification: JsonField? = null
- private var opened: JsonField? = null
private var recipient: JsonField? = null
- private var sent: JsonField? = null
private var status: JsonField? = null
+ private var clicked: JsonField = JsonMissing.of()
+ private var delivered: JsonField = JsonMissing.of()
private var error: JsonField = JsonMissing.of()
+ private var opened: JsonField = JsonMissing.of()
private var reason: JsonField = JsonMissing.of()
+ private var sent: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@JvmSynthetic
internal fun from(messageDetails: MessageDetails) = apply {
id = messageDetails.id
- clicked = messageDetails.clicked
- delivered = messageDetails.delivered
enqueued = messageDetails.enqueued
event = messageDetails.event
notification = messageDetails.notification
- opened = messageDetails.opened
recipient = messageDetails.recipient
- sent = messageDetails.sent
status = messageDetails.status
+ clicked = messageDetails.clicked
+ delivered = messageDetails.delivered
error = messageDetails.error
+ opened = messageDetails.opened
reason = messageDetails.reason
+ sent = messageDetails.sent
additionalProperties = messageDetails.additionalProperties.toMutableMap()
}
@@ -337,34 +333,6 @@ private constructor(
*/
fun id(id: JsonField) = apply { this.id = id }
- /**
- * A UTC timestamp at which the recipient clicked on a tracked link for the first time.
- * Stored as a millisecond representation of the Unix epoch.
- */
- fun clicked(clicked: Long) = clicked(JsonField.of(clicked))
-
- /**
- * Sets [Builder.clicked] to an arbitrary JSON value.
- *
- * You should usually call [Builder.clicked] with a well-typed [Long] value instead. This
- * method is primarily for setting the field to an undocumented or not yet supported value.
- */
- fun clicked(clicked: JsonField) = apply { this.clicked = clicked }
-
- /**
- * A UTC timestamp at which the Integration provider delivered the message. Stored as a
- * millisecond representation of the Unix epoch.
- */
- fun delivered(delivered: Long) = delivered(JsonField.of(delivered))
-
- /**
- * Sets [Builder.delivered] to an arbitrary JSON value.
- *
- * You should usually call [Builder.delivered] with a well-typed [Long] value instead. This
- * method is primarily for setting the field to an undocumented or not yet supported value.
- */
- fun delivered(delivered: JsonField) = apply { this.delivered = delivered }
-
/**
* A UTC timestamp at which Courier received the message request. Stored as a millisecond
* representation of the Unix epoch.
@@ -404,20 +372,6 @@ private constructor(
this.notification = notification
}
- /**
- * A UTC timestamp at which the recipient opened a message for the first time. Stored as a
- * millisecond representation of the Unix epoch.
- */
- fun opened(opened: Long) = opened(JsonField.of(opened))
-
- /**
- * Sets [Builder.opened] to an arbitrary JSON value.
- *
- * You should usually call [Builder.opened] with a well-typed [Long] value instead. This
- * method is primarily for setting the field to an undocumented or not yet supported value.
- */
- fun opened(opened: JsonField) = apply { this.opened = opened }
-
/** A unique identifier associated with the recipient of the delivered message. */
fun recipient(recipient: String) = recipient(JsonField.of(recipient))
@@ -430,30 +384,44 @@ private constructor(
*/
fun recipient(recipient: JsonField) = apply { this.recipient = recipient }
+ /** The current status of the message. */
+ fun status(status: Status) = status(JsonField.of(status))
+
/**
- * A UTC timestamp at which Courier passed the message to the Integration provider. Stored
- * as a millisecond representation of the Unix epoch.
+ * Sets [Builder.status] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.status] with a well-typed [Status] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun sent(sent: Long) = sent(JsonField.of(sent))
+ fun status(status: JsonField) = apply { this.status = status }
/**
- * Sets [Builder.sent] to an arbitrary JSON value.
+ * A UTC timestamp at which the recipient clicked on a tracked link for the first time.
+ * Stored as a millisecond representation of the Unix epoch.
+ */
+ fun clicked(clicked: Long) = clicked(JsonField.of(clicked))
+
+ /**
+ * Sets [Builder.clicked] to an arbitrary JSON value.
*
- * You should usually call [Builder.sent] with a well-typed [Long] value instead. This
+ * You should usually call [Builder.clicked] with a well-typed [Long] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun sent(sent: JsonField) = apply { this.sent = sent }
+ fun clicked(clicked: JsonField) = apply { this.clicked = clicked }
- /** The current status of the message. */
- fun status(status: Status) = status(JsonField.of(status))
+ /**
+ * A UTC timestamp at which the Integration provider delivered the message. Stored as a
+ * millisecond representation of the Unix epoch.
+ */
+ fun delivered(delivered: Long) = delivered(JsonField.of(delivered))
/**
- * Sets [Builder.status] to an arbitrary JSON value.
+ * Sets [Builder.delivered] to an arbitrary JSON value.
*
- * You should usually call [Builder.status] with a well-typed [Status] value instead. This
+ * You should usually call [Builder.delivered] with a well-typed [Long] value instead. This
* method is primarily for setting the field to an undocumented or not yet supported value.
*/
- fun status(status: JsonField) = apply { this.status = status }
+ fun delivered(delivered: JsonField) = apply { this.delivered = delivered }
/** A message describing the error that occurred. */
fun error(error: String?) = error(JsonField.ofNullable(error))
@@ -469,6 +437,20 @@ private constructor(
*/
fun error(error: JsonField) = apply { this.error = error }
+ /**
+ * A UTC timestamp at which the recipient opened a message for the first time. Stored as a
+ * millisecond representation of the Unix epoch.
+ */
+ fun opened(opened: Long) = opened(JsonField.of(opened))
+
+ /**
+ * Sets [Builder.opened] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.opened] with a well-typed [Long] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported value.
+ */
+ fun opened(opened: JsonField) = apply { this.opened = opened }
+
/** The reason for the current status of the message. */
fun reason(reason: Reason?) = reason(JsonField.ofNullable(reason))
@@ -483,6 +465,20 @@ private constructor(
*/
fun reason(reason: JsonField