diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1b159305..b85eea74 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "4.29.0"
+ ".": "4.29.1"
}
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c6278093..85257fac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 4.29.1 (2026-03-19)
+
+Full Changelog: [v4.29.0...v4.29.1](https://github.com/openai/openai-java/compare/v4.29.0...v4.29.1)
+
+### Bug Fixes
+
+* **client:** allow updating header/query affecting fields in `toBuilder()` ([fd3b67c](https://github.com/openai/openai-java/commit/fd3b67cef9c4457506a76b9e994210e512e0181f))
+* **client:** remove redundant apiKey override ([8383a7d](https://github.com/openai/openai-java/commit/8383a7de659aa6f17e1707614f5a246ced127532))
+
## 4.29.0 (2026-03-17)
Full Changelog: [v4.28.0...v4.29.0](https://github.com/openai/openai-java/compare/v4.28.0...v4.29.0)
diff --git a/README.md b/README.md
index fc9c3910..9ac2349c 100644
--- a/README.md
+++ b/README.md
@@ -2,8 +2,8 @@
-[](https://central.sonatype.com/artifact/com.openai/openai-java/4.29.0)
-[](https://javadoc.io/doc/com.openai/openai-java/4.29.0)
+[](https://central.sonatype.com/artifact/com.openai/openai-java/4.29.1)
+[](https://javadoc.io/doc/com.openai/openai-java/4.29.1)
@@ -11,7 +11,7 @@ The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https://
-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.29.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.29.1).
@@ -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.29.0")
+implementation("com.openai:openai-java:4.29.1")
```
### Maven
@@ -33,7 +33,7 @@ implementation("com.openai:openai-java:4.29.0")
com.openai
openai-java
- 4.29.0
+ 4.29.1
```
@@ -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.29.0")
+implementation("com.openai:openai-java-spring-boot-starter:4.29.1")
```
#### Maven
@@ -1351,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:4.29.0")
com.openai
openai-java-spring-boot-starter
- 4.29.0
+ 4.29.1
```
diff --git a/build.gradle.kts b/build.gradle.kts
index bbdcad0c..782ec6a0 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -8,7 +8,7 @@ repositories {
allprojects {
group = "com.openai"
- version = "4.29.0" // x-release-please-version
+ version = "4.29.1" // x-release-please-version
}
subprojects {
diff --git a/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt b/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt
index f1a1aff1..e48abf7b 100644
--- a/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt
+++ b/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt
@@ -533,9 +533,7 @@ private constructor(
headers.put("X-Stainless-Runtime", "JRE")
headers.put("X-Stainless-Runtime-Version", getJavaVersion())
headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString())
- organization?.let { headers.put("OpenAI-Organization", it) }
- project?.let { headers.put("OpenAI-Project", it) }
-
+ // We replace after all the default headers to allow end-users to overwrite them.
headers.replaceAll(this.headers.build())
when (credential) {
is AzureApiKeyCredential -> {
@@ -568,6 +566,8 @@ private constructor(
}
queryParams.replaceAll(this.queryParams.build())
+ organization?.let { headers.replace("OpenAI-Organization", it) }
+ project?.let { headers.replace("OpenAI-Project", it) }
return ClientOptions(
httpClient,
diff --git a/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt b/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt
index 9aef2402..74ab42f4 100644
--- a/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt
+++ b/openai-java-core/src/test/kotlin/com/openai/core/ClientOptionsTest.kt
@@ -16,6 +16,44 @@ internal class ClientOptionsTest {
private val httpClient = mock()
+ @Test
+ fun putHeader_canOverwriteDefaultHeader() {
+ val clientOptions =
+ ClientOptions.builder()
+ .httpClient(httpClient)
+ .putHeader("User-Agent", "My User Agent")
+ .apiKey("My API Key")
+ .build()
+
+ assertThat(clientOptions.headers.values("User-Agent")).containsExactly("My User Agent")
+ }
+
+ @Test
+ fun toBuilder_organizationCanBeUpdated() {
+ var clientOptions =
+ ClientOptions.builder()
+ .httpClient(httpClient)
+ .organization("My Organization")
+ .apiKey("My API Key")
+ .build()
+
+ clientOptions = clientOptions.toBuilder().organization("another My Organization").build()
+
+ assertThat(clientOptions.headers.values("OpenAI-Organization"))
+ .containsExactly("another My Organization")
+ }
+
+ @Test
+ fun toBuilder_bearerAuthCanBeUpdated() {
+ var clientOptions =
+ ClientOptions.builder().httpClient(httpClient).apiKey("My API Key").build()
+
+ clientOptions = clientOptions.toBuilder().apiKey("another My API Key").build()
+
+ assertThat(clientOptions.headers.values("Authorization"))
+ .containsExactly("Bearer another My API Key")
+ }
+
@Test
fun toBuilder_whenOriginalClientOptionsGarbageCollected_doesNotCloseOriginalClient() {
var clientOptions =