Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cb336a3
fix(types): remove brand field from ElementalContent model
stainless-app[bot] Feb 12, 2026
26b5aed
chore(internal): update `TestServerExtension` comment
stainless-app[bot] Feb 18, 2026
4e39320
chore(internal): make `OkHttp` constructor internal
stainless-app[bot] Feb 19, 2026
b2e1bcb
feat(client): add connection pooling option
stainless-app[bot] Feb 19, 2026
b63945e
chore(internal): remove mock server code
stainless-app[bot] Feb 20, 2026
ff62ef0
chore: update mock server docs
stainless-app[bot] Feb 20, 2026
ef1c1fb
codegen metadata
stainless-app[bot] Feb 20, 2026
401bc43
chore: make `Properties` more resilient to `null`
stainless-app[bot] Feb 24, 2026
90094b9
chore: drop apache dependency
stainless-app[bot] Feb 24, 2026
b1b8ef3
chore(internal): expand imports
stainless-app[bot] Feb 25, 2026
6fb4394
codegen metadata
stainless-app[bot] Feb 27, 2026
ad19d70
codegen metadata
stainless-app[bot] Mar 2, 2026
8978717
codegen metadata
stainless-app[bot] Mar 3, 2026
9577dec
fix(api): restructure token add single request body, rename pathToken…
stainless-app[bot] Mar 3, 2026
6a1cfae
chore(internal): codegen related update
stainless-app[bot] Mar 6, 2026
0057417
chore(internal): bump palantir-java-format
stainless-app[bot] Mar 6, 2026
330979b
chore(ci): skip uploading artifacts on stainless-internal branches
stainless-app[bot] Mar 7, 2026
4719954
fix(client): incorrect `Retry-After` parsing
stainless-app[bot] Mar 11, 2026
2c7587e
feat(api): add journeys resource with list/invoke methods
stainless-app[bot] Mar 11, 2026
e948f83
fix: mark MessageDetails timestamp fields as optional
stainless-app[bot] Mar 12, 2026
a287098
codegen metadata
stainless-app[bot] Mar 12, 2026
c632891
release: 4.10.0
stainless-app[bot] Mar 12, 2026
c62091f
Merge branch 'main' into release-please--branches--main--changes--next
mikemilla Mar 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}
Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "4.9.1"
".": "4.10.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -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
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -17,7 +17,7 @@ implementation("com.courier:courier-java:4.9.1")
<dependency>
<groupId>com.courier</groupId>
<artifactId>courier-java</artifactId>
<version>4.9.1</version>
<version>4.10.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/courier.java.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ tasks.withType<Test>().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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -75,6 +77,46 @@ class CourierOkHttpClient private constructor() {
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional<Proxy>) = 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<Int>) =
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<Duration>) =
keepAliveDuration(keepAliveDuration.getOrNull())

/**
* The socket factory used to secure HTTPS connections.
*
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -75,6 +77,46 @@ class CourierOkHttpClientAsync private constructor() {
/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional<Proxy>) = 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<Int>) =
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<Duration>) =
keepAliveDuration(keepAliveDuration.getOrNull())

/**
* The socket factory used to secure HTTPS connections.
*
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 0 additions & 2 deletions courier-java-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -67,6 +68,8 @@ interface CourierClient {

fun automations(): AutomationService

fun journeys(): JourneyService

fun brands(): BrandService

fun bulk(): BulkService
Expand Down Expand Up @@ -122,6 +125,8 @@ interface CourierClient {

fun automations(): AutomationService.WithRawResponse

fun journeys(): JourneyService.WithRawResponse

fun brands(): BrandService.WithRawResponse

fun bulk(): BulkService.WithRawResponse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -67,6 +68,8 @@ interface CourierClientAsync {

fun automations(): AutomationServiceAsync

fun journeys(): JourneyServiceAsync

fun brands(): BrandServiceAsync

fun bulk(): BulkServiceAsync
Expand Down Expand Up @@ -126,6 +129,8 @@ interface CourierClientAsync {

fun automations(): AutomationServiceAsync.WithRawResponse

fun journeys(): JourneyServiceAsync.WithRawResponse

fun brands(): BrandServiceAsync.WithRawResponse

fun bulk(): BulkServiceAsync.WithRawResponse
Expand Down
Loading
Loading