Skip to content
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 @@
{
".": "4.14.0"
".": "4.15.0"
}
6 changes: 3 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 136
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-75926226b642ebb2cb415694da9dff35e8ab40145ac1b791cefb82a83809db4d.yml
openapi_spec_hash: 6a0e391b0ba5747b6b4a3e5fe21de4da
config_hash: adcf23ecf5f84d3cadf1d71e82ec636a
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-9442fa9212dd61aac2bb0edd19744bee381e75888712f9098bc6ebb92c52b557.yml
openapi_spec_hash: f87823d164b7a8f72a42eba04e482a99
config_hash: ad7136f7366fddec432ec378939e58a7
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
# Changelog

## 4.15.0 (2026-01-09)

Full Changelog: [v4.14.0...v4.15.0](https://github.com/openai/openai-java/compare/v4.14.0...v4.15.0)

### Features

* **api:** add new Response completed_at prop ([703a651](https://github.com/openai/openai-java/commit/703a6511f98fd016a0a27e0694fccf1d81cc3280))
* **client:** allow configuring dispatcher executor service ([8e579d9](https://github.com/openai/openai-java/commit/8e579d9db0c7fde0da3abb180f5bc72c2798ede4))


### Bug Fixes

* **client:** allow `withOptions` to modify credentials ([#674](https://github.com/openai/openai-java/issues/674)) ([1d5a8f9](https://github.com/openai/openai-java/commit/1d5a8f9dda2420d3dfe916bb90f07ee596886511))


### Chores

* **internal:** use different example values for some enums ([d8c6ed4](https://github.com/openai/openai-java/commit/d8c6ed431b65bbf6746731de3052a3a2f3a6aaa8))

## 4.14.0 (2026-01-06)

Full Changelog: [v4.13.0...v4.14.0](https://github.com/openai/openai-java/compare/v4.13.0...v4.14.0)
Expand Down
26 changes: 13 additions & 13 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/4.14.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.14.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.14.0)
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/4.15.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/4.15.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/4.15.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/4.14.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/4.15.0).

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

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

```kotlin
implementation("com.openai:openai-java:4.14.0")
implementation("com.openai:openai-java:4.15.0")
```

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

Expand Down Expand Up @@ -82,7 +82,7 @@ OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.addUserMessage("Say this is a test")
.model(ChatModel.GPT_5_2)
.model(ChatModel.GPT_4O)
.build();
ChatCompletion chatCompletion = client.chat().completions().create(params);
```
Expand Down Expand Up @@ -188,7 +188,7 @@ OpenAIClient client = OpenAIOkHttpClient.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.addUserMessage("Say this is a test")
.model(ChatModel.GPT_5_2)
.model(ChatModel.GPT_4O)
.build();
CompletableFuture<ChatCompletion> chatCompletion = client.async().chat().completions().create(params);
```
Expand All @@ -209,7 +209,7 @@ OpenAIClientAsync client = OpenAIOkHttpClientAsync.fromEnv();

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.addUserMessage("Say this is a test")
.model(ChatModel.GPT_5_2)
.model(ChatModel.GPT_4O)
.build();
CompletableFuture<ChatCompletion> chatCompletion = client.chat().completions().create(params);
```
Expand Down Expand Up @@ -1143,7 +1143,7 @@ import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.addUserMessage("Say this is a test")
.model(ChatModel.GPT_5_2)
.model(ChatModel.GPT_4O)
.build();
HttpResponseFor<ChatCompletion> chatCompletion = client.chat().completions().withRawResponse().create(params);

Expand Down Expand Up @@ -1342,7 +1342,7 @@ If you're using Spring Boot, then you can use the SDK's [Spring Boot starter](ht
#### Gradle

```kotlin
implementation("com.openai:openai-java-spring-boot-starter:4.14.0")
implementation("com.openai:openai-java-spring-boot-starter:4.15.0")
```

#### Maven
Expand All @@ -1351,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:4.14.0")
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java-spring-boot-starter</artifactId>
<version>4.14.0</version>
<version>4.15.0</version>
</dependency>
```

Expand Down Expand Up @@ -1616,7 +1616,7 @@ import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.messages(JsonValue.from(42))
.model(ChatModel.GPT_5_2)
.model(ChatModel.GPT_4O)
.build();
```

Expand Down Expand Up @@ -1669,7 +1669,7 @@ import com.openai.models.ChatModel;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
.model(ChatModel.GPT_5_2)
.model(ChatModel.GPT_4O)
.messages(JsonMissing.of())
.build();
```
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 = "4.14.0" // x-release-please-version
version = "4.15.0" // x-release-please-version
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ import java.net.Proxy
import java.time.Duration
import java.util.concurrent.CancellationException
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Dispatcher
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType
import okhttp3.MediaType.Companion.toMediaType
Expand Down Expand Up @@ -198,6 +200,7 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien

private var timeout: Timeout = Timeout.default()
private var proxy: Proxy? = null
private var dispatcherExecutorService: ExecutorService? = null
private var sslSocketFactory: SSLSocketFactory? = null
private var trustManager: X509TrustManager? = null
private var hostnameVerifier: HostnameVerifier? = null
Expand All @@ -208,6 +211,10 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien

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

fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
this.dispatcherExecutorService = dispatcherExecutorService
}

fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply {
this.sslSocketFactory = sslSocketFactory
}
Expand All @@ -229,6 +236,8 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien
.callTimeout(timeout.request())
.proxy(proxy)
.apply {
dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) }

val sslSocketFactory = sslSocketFactory
val trustManager = trustManager
if (sslSocketFactory != null && trustManager != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
Expand Down Expand Up @@ -48,11 +49,31 @@ class OpenAIOkHttpClient private constructor() {
class Builder internal constructor() {

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

/**
* The executor service to use for running HTTP requests.
*
* Defaults to OkHttp's
* [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
*
* This class takes ownership of the executor service and shuts it down when closed.
*/
fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
this.dispatcherExecutorService = dispatcherExecutorService
}

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

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

/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
Expand Down Expand Up @@ -339,6 +360,7 @@ class OpenAIOkHttpClient private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
.dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.time.Clock
import java.time.Duration
import java.util.Optional
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
Expand Down Expand Up @@ -48,11 +49,31 @@ class OpenAIOkHttpClientAsync private constructor() {
class Builder internal constructor() {

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

/**
* The executor service to use for running HTTP requests.
*
* Defaults to OkHttp's
* [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104).
*
* This class takes ownership of the executor service and shuts it down when closed.
*/
fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply {
this.dispatcherExecutorService = dispatcherExecutorService
}

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

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

/** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */
Expand Down Expand Up @@ -339,6 +360,7 @@ class OpenAIOkHttpClientAsync private constructor() {
OkHttpClient.builder()
.timeout(clientOptions.timeout())
.proxy(proxy)
.dispatcherExecutorService(dispatcherExecutorService)
.sslSocketFactory(sslSocketFactory)
.trustManager(trustManager)
.hostnameVerifier(hostnameVerifier)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ private constructor(
fun model(): SpeechModel = body.model()

/**
* The voice to use when generating the audio. Supported voices are `alloy`, `ash`, `ballad`,
* `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and `verse`. Previews of the
* voices are available in the
* The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and
* `cedar`. Previews of the voices are available in the
* [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
*
* @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is
Expand Down Expand Up @@ -228,9 +228,9 @@ private constructor(
fun model(value: String) = apply { body.model(value) }

/**
* The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and `verse`.
* Previews of the voices are available in the
* The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`,
* and `cedar`. Previews of the voices are available in the
* [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
*/
fun voice(voice: Voice) = apply { body.voice(voice) }
Expand Down Expand Up @@ -520,9 +520,9 @@ private constructor(
fun model(): SpeechModel = model.getRequired("model")

/**
* The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and `verse`.
* Previews of the voices are available in the
* The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`,
* and `cedar`. Previews of the voices are available in the
* [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
*
* @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is
Expand Down Expand Up @@ -713,9 +713,9 @@ private constructor(
fun model(value: String) = model(SpeechModel.of(value))

/**
* The voice to use when generating the audio. Supported voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and `verse`.
* Previews of the voices are available in the
* The voice to use when generating the audio. Supported built-in voices are `alloy`,
* `ash`, `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`,
* `verse`, `marin`, and `cedar`. Previews of the voices are available in the
* [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
*/
fun voice(voice: Voice) = voice(JsonField.of(voice))
Expand Down Expand Up @@ -928,9 +928,9 @@ private constructor(
}

/**
* The voice to use when generating the audio. Supported voices are `alloy`, `ash`, `ballad`,
* `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, and `verse`. Previews of the
* voices are available in the
* The voice to use when generating the audio. Supported built-in voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `onyx`, `nova`, `sage`, `shimmer`, `verse`, `marin`, and
* `cedar`. Previews of the voices are available in the
* [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options).
*/
class Voice @JsonCreator private constructor(private val value: JsonField<String>) : Enum {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ private constructor(
fun format(): Format = format.getRequired("format")

/**
* The voice the model uses to respond. Supported voices are `alloy`, `ash`, `ballad`, `coral`,
* `echo`, `fable`, `nova`, `onyx`, `sage`, and `shimmer`.
* The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`,
* `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, `shimmer`, `marin`, and `cedar`.
*
* @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
Expand Down Expand Up @@ -121,8 +121,9 @@ private constructor(
fun format(format: JsonField<Format>) = apply { this.format = format }

/**
* The voice the model uses to respond. Supported voices are `alloy`, `ash`, `ballad`,
* `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, and `shimmer`.
* The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`,
* `ballad`, `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, `shimmer`, `marin`, and
* `cedar`.
*/
fun voice(voice: Voice) = voice(JsonField.of(voice))

Expand Down Expand Up @@ -364,8 +365,8 @@ private constructor(
}

/**
* The voice the model uses to respond. Supported voices are `alloy`, `ash`, `ballad`, `coral`,
* `echo`, `fable`, `nova`, `onyx`, `sage`, and `shimmer`.
* The voice the model uses to respond. Supported built-in voices are `alloy`, `ash`, `ballad`,
* `coral`, `echo`, `fable`, `nova`, `onyx`, `sage`, `shimmer`, `marin`, and `cedar`.
*/
class Voice @JsonCreator private constructor(private val value: JsonField<String>) : Enum {

Expand Down
Loading