Skip to content

release: 2.17.0 #546

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "2.16.0"
".": "2.17.0"
}
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 2.17.0 (2025-07-21)

Full Changelog: [v2.16.0...v2.17.0](https://github.com/openai/openai-java/compare/v2.16.0...v2.17.0)

### Features

* **client:** add https config options ([3f74519](https://github.com/openai/openai-java/commit/3f745195fa5d72ee72653adbd8087915c0db2fa5))
* **client:** allow setting additional multipart body props ([220503e](https://github.com/openai/openai-java/commit/220503efc745bd1c74c02f1d4d6d3305198bf942))


### Chores

* **internal:** refactor delegating from client to options ([e89596d](https://github.com/openai/openai-java/commit/e89596d624fd77fdef750fb65a9ca5c6497e76cb))

## 2.16.0 (2025-07-17)

Full Changelog: [v2.15.0...v2.16.0](https://github.com/openai/openai-java/compare/v2.15.0...v2.16.0)
Expand Down
31 changes: 26 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

<!-- x-release-please-start-version -->

[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/2.16.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/2.16.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/2.16.0)
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/2.17.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/2.17.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/2.17.0)

<!-- x-release-please-end -->

The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https://platform.openai.com/docs) from applications written in Java.

<!-- x-release-please-start-version -->

The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/2.16.0).
The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/2.17.0).

<!-- x-release-please-end -->

Expand All @@ -22,7 +22,7 @@ The REST API documentation can be found on [platform.openai.com](https://platfor
### Gradle

```kotlin
implementation("com.openai:openai-java:2.16.0")
implementation("com.openai:openai-java:2.17.0")
```

### Maven
Expand All @@ -31,7 +31,7 @@ implementation("com.openai:openai-java:2.16.0")
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>2.16.0</version>
<version>2.17.0</version>
</dependency>
```

Expand Down Expand Up @@ -1398,6 +1398,27 @@ OpenAIClient client = OpenAIOkHttpClient.builder()
.build();
```

### HTTPS

> [!NOTE]
> Most applications should not call these methods, and instead use the system defaults. The defaults include
> special optimizations that can be lost if the implementations are modified.

To configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods:

```java
import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
.fromEnv()
// If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa.
.sslSocketFactory(yourSSLSocketFactory)
.trustManager(yourTrustManager)
.hostnameVerifier(yourHostnameVerifier)
.build();
```

### Custom HTTP client

The SDK consists of three artifacts:
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.openai"
version = "2.16.0" // x-release-please-version
version = "2.17.0" // x-release-please-version
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import java.io.InputStream
import java.net.Proxy
import java.time.Duration
import java.util.concurrent.CompletableFuture
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Call
import okhttp3.Callback
import okhttp3.HttpUrl.Companion.toHttpUrl
Expand Down Expand Up @@ -189,13 +192,28 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC

private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null

fun timeout(timeout: Timeout) = apply { this.timeout = timeout }

fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())

fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }

fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
this.sslSocketFactory = sslSocketFactory
}

fun trustManager(trustManager: X509TrustManager?) = apply {
this.trustManager = trustManager
}

fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
this.hostnameVerifier = hostnameVerifier
}

fun build(): OkHttpClient =
OkHttpClient(
okhttp3.OkHttpClient.Builder()
Expand All @@ -204,6 +222,19 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC
.writeTimeout(timeout.write())
.callTimeout(timeout.request())
.proxy(proxy)
.apply {
val sslSocketFactory = sslSocketFactory
val trustManager = trustManager
if (sslSocketFactory != null && trustManager != null) {
sslSocketFactory(sslSocketFactory, trustManager)
} else {
check((sslSocketFactory != null) == (trustManager != null)) {
"Both or none of `sslSocketFactory` and `trustManager` must be set, but only one was set"
}
}

hostnameVerifier?.let(::hostnameVerifier)
}
.build()
.apply {
// We usually make all our requests to the same host so it makes sense to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ import com.openai.core.ClientOptions
import com.openai.core.Timeout
import com.openai.core.http.Headers
import com.openai.core.http.QueryParams
import com.openai.core.jsonMapper
import com.openai.credential.Credential
import java.net.Proxy
import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import kotlin.jvm.optionals.getOrNull

class OpenAIOkHttpClient private constructor() {
Expand All @@ -32,10 +36,63 @@ class OpenAIOkHttpClient private constructor() {
class Builder internal constructor() {

private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null

fun baseUrl(baseUrl: String) = apply { clientOptions.baseUrl(baseUrl) }
fun proxy(proxy: Proxy?) = apply { this.proxy = proxy }

/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
fun proxy(proxy: Optional<Proxy>) = proxy(proxy.getOrNull())

/**
* The socket factory used to secure HTTPS connections.
*
* If this is set, then [trustManager] must also be set.
*
* If unset, then the system default is used. Most applications should not call this method,
* and instead use the system default. The default include special optimizations that can be
* lost if the implementation is modified.
*/
fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
this.sslSocketFactory = sslSocketFactory
}

/** Alias for calling [Builder.sslSocketFactory] with `sslSocketFactory.orElse(null)`. */
fun sslSocketFactory(sslSocketFactory: Optional<SSLSocketFactory>) =
sslSocketFactory(sslSocketFactory.getOrNull())

/**
* The trust manager used to secure HTTPS connections.
*
* If this is set, then [sslSocketFactory] must also be set.
*
* If unset, then the system default is used. Most applications should not call this method,
* and instead use the system default. The default include special optimizations that can be
* lost if the implementation is modified.
*/
fun trustManager(trustManager: X509TrustManager?) = apply {
this.trustManager = trustManager
}

/** Alias for calling [Builder.trustManager] with `trustManager.orElse(null)`. */
fun trustManager(trustManager: Optional<X509TrustManager>) =
trustManager(trustManager.getOrNull())

/**
* The verifier used to confirm that response certificates apply to requested hostnames for
* HTTPS connections.
*
* If unset, then a default hostname verifier is used.
*/
fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply {
this.hostnameVerifier = hostnameVerifier
}

/** Alias for calling [Builder.hostnameVerifier] with `hostnameVerifier.orElse(null)`. */
fun hostnameVerifier(hostnameVerifier: Optional<HostnameVerifier>) =
hostnameVerifier(hostnameVerifier.getOrNull())

/**
* Whether to throw an exception if any of the Jackson versions detected at runtime are
Expand All @@ -56,6 +113,54 @@ class OpenAIOkHttpClient private constructor() {

fun clock(clock: Clock) = apply { clientOptions.clock(clock) }

fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) }

/** Alias for calling [Builder.baseUrl] with `baseUrl.orElse(null)`. */
fun baseUrl(baseUrl: Optional<String>) = baseUrl(baseUrl.getOrNull())

fun responseValidation(responseValidation: Boolean) = apply {
clientOptions.responseValidation(responseValidation)
}

fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) }

/**
* Sets the maximum time allowed for a complete HTTP call, not including retries.
*
* See [Timeout.request] for more details.
*
* For fine-grained control, pass a [Timeout] object.
*/
fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) }

fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) }

fun credential(credential: Credential) = apply { clientOptions.credential(credential) }

fun azureServiceVersion(azureServiceVersion: AzureOpenAIServiceVersion) = apply {
clientOptions.azureServiceVersion(azureServiceVersion)
}

fun organization(organization: String?) = apply { clientOptions.organization(organization) }

/** Alias for calling [Builder.organization] with `organization.orElse(null)`. */
fun organization(organization: Optional<String>) = organization(organization.getOrNull())

fun project(project: String?) = apply { clientOptions.project(project) }

/** Alias for calling [Builder.project] with `project.orElse(null)`. */
fun project(project: Optional<String>) = project(project.getOrNull())

fun webhookSecret(webhookSecret: String?) = apply {
clientOptions.webhookSecret(webhookSecret)
}

/** Alias for calling [Builder.webhookSecret] with `webhookSecret.orElse(null)`. */
fun webhookSecret(webhookSecret: Optional<String>) =
webhookSecret(webhookSecret.getOrNull())

fun headers(headers: Headers) = apply { clientOptions.headers(headers) }

fun headers(headers: Map<String, Iterable<String>>) = apply {
Expand Down Expand Up @@ -136,54 +241,6 @@ class OpenAIOkHttpClient private constructor() {
clientOptions.removeAllQueryParams(keys)
}

fun timeout(timeout: Timeout) = apply {
clientOptions.timeout(timeout)
this.timeout = timeout
}

/**
* Sets the maximum time allowed for a complete HTTP call, not including retries.
*
* See [Timeout.request] for more details.
*
* For fine-grained control, pass a [Timeout] object.
*/
fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build())

fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) }

fun proxy(proxy: Proxy) = apply { this.proxy = proxy }

fun responseValidation(responseValidation: Boolean) = apply {
clientOptions.responseValidation(responseValidation)
}

fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) }

fun credential(credential: Credential) = apply { clientOptions.credential(credential) }

fun azureServiceVersion(azureServiceVersion: AzureOpenAIServiceVersion) = apply {
clientOptions.azureServiceVersion(azureServiceVersion)
}

fun organization(organization: String?) = apply { clientOptions.organization(organization) }

/** Alias for calling [Builder.organization] with `organization.orElse(null)`. */
fun organization(organization: Optional<String>) = organization(organization.getOrNull())

fun project(project: String?) = apply { clientOptions.project(project) }

/** Alias for calling [Builder.project] with `project.orElse(null)`. */
fun project(project: Optional<String>) = project(project.getOrNull())

fun webhookSecret(webhookSecret: String?) = apply {
clientOptions.webhookSecret(webhookSecret)
}

/** Alias for calling [Builder.webhookSecret] with `webhookSecret.orElse(null)`. */
fun webhookSecret(webhookSecret: Optional<String>) =
webhookSecret(webhookSecret.getOrNull())

fun fromEnv() = apply { clientOptions.fromEnv() }

/**
Expand All @@ -194,7 +251,15 @@ class OpenAIOkHttpClient private constructor() {
fun build(): OpenAIClient =
OpenAIClientImpl(
clientOptions
.httpClient(OkHttpClient.builder().timeout(timeout).proxy(proxy).build())
.httpClient(
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
.build()
)
.build()
)
}
Expand Down
Loading
Loading